I am learning Jersey and stumbling from one issue to another. I just got the service to work from Java client (after some help from someone here). The service class is as follows:
#Path("/user")
public class UserService extends AbstractService {
private static final NouLogger logger = NouLogger
.getLogger(UserService.class);
#Path("fbregister")
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String createNewFBUser(#FormParam("fbuserid") String userid,
#FormParam("fbmailid") String emailId,
#FormParam("fbfullname") String fullName,
#FormParam("fbusertoken") String userToken,
#Context HttpServletResponse servletResponse) throws IOException,
DatabaseException {
final String methodName = "createNewFBUser";
User user = new User();
user.setEmail(emailId);
user.setName(fullName);
user.setFacebookSecret(userToken);
Session session = null;
try {
session = getSession();
} catch (DatabaseException e) {
final String message = "Error occurred while fetching session.";
logger.error(methodName, message, e);
e.printStackTrace();
}
UserDAO userDAO = DAOFactory.DEFAULT.buildUserDAO();
Transaction txn = session.beginTransaction();
userDAO.save(user);
txn.commit();
closeSession();
return user.getId().toString();
}
}
This works fine when I call it from Java client. But when I call it from iOS code, I get all the null values for all the parameters. The iOS code is as below:
// To encode parameter.
NSString *fb_userid = [user objectForKey:#"id"];
NSString *fb_mailid = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,(CFStringRef)[user objectForKey:#"email"], NULL, (CFStringRef)#"!*'();:#&=+$,/?%#[]",kCFStringEncodingUTF8 ));
NSString *fb_fullname = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,(CFStringRef)user.name, NULL, (CFStringRef)#"!*'();:#&=+$,/?%#[]",kCFStringEncodingUTF8 ));
NSString *fbAccessToken = [[[FBSession activeSession] accessTokenData] accessToken];
NSLog(#"user = %#", user);
NSLog(#"fb_userid = %#", fb_userid);
NSLog(#"fb_mailid = %#", fb_mailid);
NSLog(#"fb_fullname = %#", fb_fullname);
// To send url Request.
NSString *url1 =[NSString stringWithFormat:#"http://myip:8080/nou/rest/user/fbregister?fbuserid=%#&fbmailid=%#&fbfullname=%#&fbusertoken=%#", fb_userid, fb_mailid, fb_fullname, fbAccessToken];
NSURL *url = [NSURL URLWithString:url1];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
[theRequest setHTTPMethod:#"POST"];
theConnection1 = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
Any idea why this is happening? I put it on remote debug, I could see the method being invoked also, my DB entry was created but all the null values were put in it. Help me solve this issue.
EDIT:
I tried sending just one parameter 'id' and it did not work either.
In your java code, you are accepting parameters as FormParam but while posting you are sending it as part of query string from the client code. So either:
Change the FormParam in server code to QueryParam
or Change the client code to send it as post params. Here is an example:
How to simulate HTTP form (POST) submit on iOS
Related
I have a question about "Authorization Request Denied - Insufficient privileges to complete the operation" message that I keep getting back from my requests to Windows Graph API.
Specifically, I'm working in Azure cloud. I have an iOS mobile app that invokes an API.
I have turned on "Authentication for Active Directory" in my Portal.
Then, on the client side (iOS):
[self.todoService.client loginWithProvider:#"windowsazureactivedirectory"
controller:self
animated:YES
completion:^(MSUser *user, NSError *error) {
if(!error && user) {
[self refresh];
}
}]; //loginWithProvider
So returns a valid MSUser object. I see the web login controller appear, I sign in with my un/pw, and then it lets me access my Easy Table's data...etc.
Now, I want to invoke an Easy API that I've created in Azure called getUserData. Hence, I simply insert the invokeAPI code like this (iOS):
[self.todoService.client loginWithProvider:#"windowsazureactivedirectory"
controller:self
animated:YES
completion:^(MSUser *user, NSError *error) {
if(!error && user) {
//NSMutableDictionary * dict = [NSMutableDictionary dictionary];
//[dict setObject:#YES forKey:#"complete"];
NSLog(#"%s - %#", __FUNCTION__, user);
[self refresh];
[self.todoService.client invokeAPI:#"getUserData"
body:nil
HTTPMethod:#"POST"
parameters:nil
headers:nil
completion:^(id _Nullable result, NSHTTPURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(#"%s - API returned response! ", __FUNCTION__);
NSLog(#"%#", result); //TODO: user info here!! :D
}]; //invokAPI
} //if user returned from AAD login is valid
}]; //loginWithProvider
Everything is fine as the API is called and I can see the response data.
On the server side (Node JS), I basically do 3 things:
1st is to get the user object id from the request object:
req.azureMobile.user.getIdentity().then((data) => {
//get user object ID
}
2nd, make a request to https://login.windows.net to get an Access Token with a username/password.
var options = {
url: "https://login.windows.net/" + tenant_domain + "/oauth2/token?api-version=1.0",
method: 'POST',
form: {
grant_type: "client_credentials",
resource: "https://graph.windows.net",
client_id: clientID,
client_secret: key
}
};
req(options, function (err, resp, body) {
//get the result back
}
I get a whole bunch of data back including the Access Token.
3rd, make a request to https://graph.windows.net/, and provide this Access Token along with my User Object ID:
var options = {
url: "https://graph.windows.net/" + tenant_domain + "/users/" + objectId + "?api-version=1.0",
method: 'GET',
headers: {
"Authorization": "Bearer " + access_token
}
};
This is so that I can User data. Now, in a separate test Subscription, I set up all the basic read permissions for AAD and Graph in my AAD management. I successfully get the user's full data back like so:
user = {
accountEnabled = 1;
assignedLicenses = (
);
assignedPlans = (
);
city = xxxxxxxxx;
country = xxxxxxxxxx;
department = Dev;
dirSyncEnabled = "<null>";
displayName = xxxxxx;
facsimileTelephoneNumber = "<null>";
givenName = hehe;
jobTitle = "iOS dev";
lastDirSyncTime = "<null>";
mail = "<null>";
mailNickname = "xxxxxxxxxx.com#EXT#";
mobile = "+xx xxx xxxx 3852";
objectId = "xxxxxxx-2c70-4aab-b261-3b2b97dc5c50";
objectType = User;
"odata.metadata" = "https://graph.windows.net/xxxxxxxxxx.onmicrosoft.com/$metadata#directoryObjects/Microsoft.WindowsAzure.ActiveDirectory.User/#Element";
"odata.type" = "Microsoft.WindowsAzure.ActiveDirectory.User";
otherMails = (
"xxxxxxxxxxxx#gmail.com"
);
...etc
}
However, in another subscription, I did the exact same steps. Even going as far as checking all the permissions like so:
I keep getting an "Authorization Request Denied, Insufficient privileges" message. The error is null so I know everything else went through correctly.
I can't figure out why because everything processes through and I checked all of my AAD and Graph permissions.
log result:
-----body------
'{"odata.error":{"code":"Authorization_RequestDenied","message":{"lang":"en","value":"Insufficient privileges to complete the operation."}}}'
Thanks for any help, and appreciate everyone's time
You can try to upgrade the role of the AD application you use to a administrator permission. Run the following commands in PowerShell:
Connect-MsolService
$ClientIdWebApp = '{your_AD_application_client_id}'
$webApp = Get-MsolServicePrincipal –AppPrincipalId $ClientIdWebApp
#use Add-MsolRoleMember to add it to "Company Administrator" role).
Add-MsolRoleMember -RoleName "Company Administrator" -RoleMemberType ServicePrincipal -RoleMemberObjectId $webApp.ObjectId
This is the code from the tutorial Getting Started and I'm only trying it, nothing else is running.
public class Launch {
private static final String url =
"http://api.linkedin.com/v1/people/~/connections:(id,first-name,last-name,email-address,picture-url)";
private static final String url2 =
"http://api.linkedin.com/v1/people/~/connections:(id,first-name,last-name)";
public Launch() {
OAuthService service = new ServiceBuilder()
.provider(LinkedInApi.class)
.apiKey("xxxx")
.apiSecret("xxxx")
.build();
Token requestToken = service.getRequestToken();
String authUrl = service.getAuthorizationUrl(requestToken);
Verifier v = new Verifier("verifier you got from the user");
Token accessToken = service.getAccessToken(requestToken, v); // the requestToken you had from step 2
OAuthRequest request = new OAuthRequest(Verb.GET, url2);
service.signRequest(accessToken, request); // the access token from step 4
Response response = request.send();
System.out.println(response.getBody());
}
In my controller I have:
#View
public Response.Content index(){
Launch launch = new Launch();
return index.ok();}
and when I try to launch it, it gives me this error:
org.scribe.exceptions.OAuthException: Response body is incorrect. Can't extract token and secret from this: 'oauth_problem=permission_unknown'
Found the solution: changed the code to add Scanner in = new Scanner(System.in); after the ServiceBuilder declaration to use it in Verifier verifier = new Verifier(in.nextLine());
And also, put manually the url found in the terminal which is the result of System.out.println(service.getAuthorizationUrl(requestToken));
It's a temporary url, but the only way this works till now.
I am making an app based on broadcasting I am using videoCore Lib for Broadcast for that I am using below code to start rtmp session
[_session startRtmpSessionWithURL:urlForStream
andStreamKey:streamID];
urlForStream is url of wowza server like rtmp://some.tv/some/username/username/randamvalue
that Randam value is don't want to override my videos every time so i am using that url and now My Problem is VCSessionState class state is not changing it is not coming to started state and I am getting the Error here is streamsessio.mm class and [NSRL(m_runLoop) run]; i don't kow where i miss please help me out
Considering from my experience of having created my own RTMP protocol library, I thought you have to separate the URL into two parts: tcUrl and stream key. In your case, the random value is likely to be a stream key.
NSString *tcUrl;
NSString *stream;
separateRtmpUrl(urlForStream, &tcUrl, &stream);
[_session startRtmpSessionWithURL:tcUrl andStreamKey:stream];
The definition of the separateRtmpUrl function can be like this.
static void separateRtmpUrl(NSString *baseUrl, NSString **tcUrl, NSString **stream)
{
NSURL *url = [NSURL URLWithString:baseUrl];
*stream = url.pathComponents.lastObject;
*tcUrl = [NSString stringWithFormat:#"%#://%#%#", url.scheme, url.host,
[NSString pathWithComponents:
[url.pathComponents subarrayWithRange:
NSMakeRange(0, url.pathComponents.count - 1)]]];
if (url.query) {
*stream = [#[*stream , url.query] componentsJoinedByString:#"?"];
*tcUrl = [#[*tcUrl , url.query] componentsJoinedByString:#"?"];
}
}
I am sending reguest to webserver in this function:
-(void)getData
{
NSURL *url = [NSURL URLWithString:#"http://10.10.10.10/application.php"]; //some address
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
request.delegate = self;
[request setPostValue:#"6577098" forKey:#"serial_number"];
[request startAsynchronous];
}
Then on server part in application.php :
<?php
//$serial_number from $_POST["serial_number"];
$serial_number = $this->getString('serial_number', 64);
$stmt = $this->pdo->prepare('SELECT S.DateTime, SN.Name FROM States S LEFT JOIN StateNames SN on SN.ID=S.State_ID WHERE S.SerialNumber = ?');
$stmt->execute(array($serial_number));
$states = $stmt->fetchAll(PDO::FETCH_ASSOC);
$result = array();
foreach ($states as $state)
{
$result[] = $state;
}
sendResponse(200, json_encode($result));
?>
This part works when I try it from browser, it works and I get this:
[{"DateTime":"2013-05-15 10:22:11","Name":"No water"},{"DateTime":"2013-05-13 14:55:31","Name":"Water"}]
Then back to process it in Xcode:
-(void)requestFinished:(ASIHTTPRequest *)request
{
if (request.responseStatusCode == 200)
{
NSString *responseString = [request responseString];
NSLog(#"%#",responseString); //if I try this nothing happened
}
}
I think I have to do something with JSON.
I thing I have bad response on my request. But I have responceStatusCode 200.
Can anyone help me? I didn't find what's wrong.
Thanks
I would need specifics to tell you what server settings you need to adjust. My next best advice - debug line by line. For example in php file, do:
$serial_number = $this->getString('serial_number', 64); //there I get serial_number from $_POST["serial_number"];
echo $serial_number; die;
// ...
at this point if you run your app again, you should see the serial # printed in -(void)requestFinished:(ASIHTTPRequest *)request, if nothing breaks up to here. If you do see it, remove echo and die, move on
//...
$stmt = $this->pdo->prepare('SELECT S.DateTime, SN.Name FROM States S LEFT JOIN StateNames SN on SN.ID=S.State_ID WHERE S.SerialNumber = ?');
$stmt->execute(array($serial_number));
$states = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($states); die;
// ...
if no responce there, this might mean that you don't have PDO driver installed with your php.
If the next line sendResponse(200, json_encode($result)); breaks it, then my guess is that your php installation lacks json module.
My requested URL is https://api.instagram.com/v1/media/MYMEDIA_ID/comments?access_token=MYTOKEN&text=MYTEXT
I get a reply like this:
{
meta = {
code = 400;
"error_message" = "Missing 'text'";
"error_type" = APIInvalidParametersError;
};
}
In the Instagram document it says the comment API takes two parameters: text and access_token. I have provided both, and I get the error saying text is missing.
I have tried with different symbols instead of & but nothing works. Does anybody have experience on how the text parameter should appear on the requested URL?
Thanks a lot !
i am using hybridauth, and here is the code, it is working..
function setUserComment($post_id, $message)
{
$flag = 0;
$parameters = array("text" => $message);
$response = $this->api->post( "media/$post_id/comments", $parameters );
// check the last HTTP status code returned
if ( $this->api->http_code != 200 ){
throw new Exception( "Comment failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ) );
}
else{
$flag = 1;
}
return $flag;
}
To add comments to Instagram you need to post the text it shouldn't be part of the URL. The Instagram API documentation provides an example using CURL:
curl -F 'access_token=1084932.f59def8.deb7db76ffc34f96bada217fe0b6cd9a' \
-F 'text=This+is+my+comment' \
https://api.instagram.com/v1/media/{media-id}/comments
So neither the access_token or the text are part of the URL just POST data.
Just add text=MYTEXT to your request's HTTPBody.
Here is sample code:
NSMutableURLRequest *apiRequest = [[NSMutableURLRequest alloc] initWithURL:apiURL];
apiRequest.HTTPMethod = #"POST";
NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:#"text=%#", MYTEXT] dataUsingEncoding:NSUTF8StringEncoding]];
apiRequest.HTTPBody = body;
[NSURLConnection sendAsynchronousRequest:apiRequest queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// Handle the response.
}];
you need to change the content type of the request ContentType="comment"
I believe the key here is ContentType header. At least nothing worked for me until I started to define it.
If you set "ContentType": "multipart/form-data" you need to set up quite a complex body content as described here:
https://dotnetthoughts.net/post-requests-from-azure-logic-apps/
I found much easier path:
Set your header "Content-Type": "application/x-www-form-urlencoded"
and then you can set your request body as simple as key=url_escaped(value):
text=My%20comment