How to implement Facebook Realtime Update Subscription with callback URL [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
How to implement Facebook Realtime API

Configure Facebook app and then install the app on Facebook pages/users that you want updates for.
We need to maintain a callback URL for Facebook to be able to post updates. Jersey based implementation as an example:
#Path("/social/facebook/update")
public class FacebookRealtimeAPIResource
{
private static final String HUB_MODE = "hub.mode";
private static final String HUB_CHALLENGE = "hub.challenge";
private static final String HUB_VERIFY_TOKEN = "hub.verify_token";
public FacebookRealtimeAPIResource()
{
// any desired implementation here
}
#GET
#Produces(MediaType.TEXT_HTML)
public void validateFacebookRequest(
#DefaultValue("") #QueryParam(HUB_MODE) String hubMode,
#DefaultValue("") #QueryParam(HUB_CHALLENGE) String hubChallenge,
#DefaultValue("") #QueryParam(HUB_VERIFY_TOKEN) String hubVerifyToken,
#Context HttpServletRequest request,
#Context HttpServletResponse response)
{
try
{
// hubVerifyToken based validation if desired
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().write(hubChallenge);
response.getWriter().flush();
response.getWriter().close();
}
catch (IOException exc)
{
throw new WebApplicationException(Response.Status.BAD_REQUEST);
}
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
public void processFacebookRealtimeUpdate(#Context HttpServletRequest request, InputStream inputStream)
{
StringBuilder sb = new StringBuilder();
String newLine = System.getProperty("line.separator");
String line;
String json = "";
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, request.getCharacterEncoding()));
while ((line = reader.readLine()) != null)
sb.append(line).append(newLine);
}
catch (Exception exc)
{
throw new WebApplicationException(Response.Status.BAD_REQUEST);
}
json = sb.toString(); // use this json string for desired purpose
}
}
Install app for page and then subscribe for page updates
public class FacebookRealtimeSubscriber
{
private AccessToken appAccessToken = null;
private String appSecret = // your app secret
private String userAccessToken = // access token for user that owns the page, generated using your app
private String applicationId = // your application id
private String callbackURL = "<your context root>/social/facebook/update";
private String pageName = // page name you want to install app for
private FacebookClient client = null;
private final String subscribedAppsEdge = "/subscribed_apps";
private final String appSubscriptions = "/subscriptions";
private final String verifyToken = "AnyRandomVerifyToken";
// below are all the fields that can be subscribed for page object
private final String pageFields = "feed,ratings,name,picture,category,description,founded,company_overview,conversations,mission,products,general_info,location,hours,parking,public_transit,phone,email,website,attire,payment_options,culinary_team,general_manager,price_range,restaurant_services,restaurant_specialties,videos,release_date,genre,starring,screenplay_by,directed_by,produced_by,studio,awards,plot_outline,network,season,schedule,written_by,band_members,hometown,current_location,record_label,booking_agent,press_contact,artists_we_like,influences,band_interests,bio,affiliation,birthday,personal_info,personal_interests,members,built,features,mpg,checkins,productlists";
public static void main(String[] args)
{
new FacebookRealtimeSubscriber().subscribe();
}
private void subscribe()
{
String pageAccessToken = "";
String pageId = "";
client = new DefaultFacebookClient(Version.VERSION_2_3);
appAccessToken = client.obtainAppAccessToken(applicationId, appSecret);
client = new DefaultFacebookClient(userAccessToken, Version.VERSION_2_3);
Connection<Account> pages = client.fetchConnection("me/accounts", Account.class);
List<Account> accounts = pages.getData();
for (Account account : accounts)
{
if (pageName.equals(account.getName()))
{
pageAccessToken = account.getAccessToken();
pageId = account.getId();
}
}
client = new DefaultFacebookClient(pageAccessToken, appSecret, Version.VERSION_2_3);
// subscribe app for page
Object obj = client.publish(pageId + subscribedAppsEdge, JsonObject.class, Parameter.with("id", Long.valueOf(pageId)));
System.out.println(obj.toString());
// list subscriptions for app
obj = client.fetchObject(pageId + subscribedAppsEdge, JsonObject.class);
System.out.println(obj.toString());
// subscribe for page updates for app
client = new DefaultFacebookClient(appAccessToken.getAccessToken(), appSecret, Version.VERSION_2_3);
obj = client.publish(applicationId + appSubscriptions,
JsonObject.class,
Parameter.with("object", "page"),
Parameter.with("callback_url", callbackURL),
Parameter.with("fields", pageFields),
Parameter.with("verify_token", verifyToken));
System.out.println(obj);
// get subscriptions for app
obj = client.fetchObject(applicationId + appSubscriptions, JsonObject.class);
System.out.println(obj);
}
}

Related

POST doesn't create object in Java

I am trying to develop a RESTful application that allows the client to add users to a database. This is the User class
public class User {
private String id;
private String name;
public User(String id, String name){
this.id = id;
this.name = name;
}
//------------Getters and setters-----------------------------------------------------
public String getId(){
return id;
}
public String getName(){
return name;
}
}
this is the User database class
public class UserDatabase {
private Map<String, String> users = new HashMap<String, String>();
public UserDatabase(){
users.put("2", "User2");
users.put("3", "User3");
}
public Map<String, String> getAllUsers(){
return users;
}
public String getUserName(String id){
return users.get(id);
}
public void addUser(String id, String name){
users.put(id, name);
}
}
this is the User resource
#Path("/users")
public class UserResource {
UserDatabase usersDatabase = new UserDatabase();
#GET
#Path("/{id}")
#Produces(MediaType.APPLICATION_JSON)
public String getUser(#PathParam("id") String id){
String response = String.valueOf(usersDatabase.getAllUsers().size());
return response + " " + usersDatabase.getUserName(id);
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response addUser(String userString) throws JSONException {
JSONObject user = new JSONObject(userString);
String userId = user.getString("id");
String userName = user.getString("name");
usersDatabase.addUser(userId, userName);
String result = "Created user with id: " + userId + " and name: " + usersDatabase.getUserName(userId);
return Response.status(201).entity(result).build();
}
}
And this is the client with which i make a POST request to add a new user and then a GET request to get the user i just added
public class TestClient {
private final String baseUrl = "http://localhost:8080/BoardGameManager/rest";
public static void main(String[] args) throws IOException{
TestClient client = new TestClient();
client.sendPostRequest("/users");
client.sendGetRequest("/users/1");
}
private void sendGetRequest(String urlString) throws IOException{
//Building and sending GET request
URL url = new URL(baseUrl+ urlString);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
System.out.println("Sending get request : "+ url);
System.out.println("Response code : "+ responseCode);
//Reading response from input Stream
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String output;
StringBuffer response = new StringBuffer();
while ((output = in.readLine()) != null){
response.append(output);
}
in.close();
//printing result from response
System.out.println(response.toString());
}
private void sendPostRequest(String urlString) throws IOException {
//Building POST request
URL url = new URL(baseUrl + urlString);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type","application/json");
String postData = "{\"id\": \"1\",\"name\": \"User1\"}";
//Sending POST request
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(postData);
outputStream.flush();
outputStream.close();
//Receiving response
int responseCode = connection.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post Data : " + postData);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String output;
StringBuffer response = new StringBuffer();
while ((output = in.readLine()) != null) {
response.append(output);
}
in.close();
//printing result from response
System.out.println(response.toString());
}
}
The problem is that when i make the POST request the user is added, but when I try to get it with the GET request the user i just added doesn't exist, and I can't understand why this happens.
Actually you are instantiating userDatabases as new UserDatabase() so everytime you get a new copy of userDatabases hence you get everytime a new users Map.
I propose to make your UserDatabasea singleton instead to keep every new added user to the Map:
public class UserDatabase {
private static UserDatabase instance = null;
public static UserDatabase getInstance() {
if(instance == null) {
instance = new UserDatabase();
}
return instance;
}
private UserDatabase(){
users.put("2", "User2");
users.put("3", "User3");
}
//....
}
Then instantiate UserDatabase like this :
#Path("/users")
public class UserResource {
UserDatabase usersDatabase = UserDatabase.getInstance();
}
Now everytime you call UserDatabase.getInstance() you will get the same copy of it hence the same users Map.
Actually you don't even have to implement singleton pattern here if you are using spring boot to develop your micro service. You can use #Service annotation on your UserDatabase class. Then in your UserResource class do the following.
#Autowired
UserDatabase usersDatabase = new UserDatabase();
Spring will manage singleton instances here on behalf of you.
Following dependencies would be enough. But I reckon you to create a project using spring initializer by adding dependencies as needed. The default dependencies as given below would be sufficient as I remember. Additionally you may find a sample project here.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

Error when sending a POST request, authenticated by OAuth, using signpost

I'm trying to send aמ HTTP POST request in order to send contacts information to a Mail Exchange Server, using their API (creating a new "subscriber"). I'm using Java and java.util.HttpURLConnection.
When I try signing the connection, I'm getting a null reference exception. If I try signing the connection prior to adding the setRequestProperty headers, I'm getting an Invalid Signature response from the server.
Using a GET request with the same general procedure works - which means, as far as I understand, that my signing method (and key values etc.) is OK.
The service I'm trying to use has some kind of a "SDK" available, written in .NET. I didn't try to use it but I do believe it to work (they declare so).
I tried to replicate their procedure. Below you can find my code, follow by theirs:
private static HttpURLConnection createAndSendOAuthPostRequestWithParams () throws MalformedURLException, IOException, Exception {
String url = "http://apisdomain/v1.0/lists/354467/subscribers";
// Here I set up the values given by the provider (API's admin) which I removed from the example
String clientKey = "";
String clientSecret = "";
String userKey = "";
String userSecret = "";
String postData = "NAME=TestSubscriber&EMAIL=test#gmail.com
byte[] postBody = postData.getBytes("UTF-8");
URL apiUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("content-length", String.valueOf(postBody.length));
connection.setRequestProperty("content-type", "application/x-www-form-urlencoded; charset=UTF-8");
//OAuth
OAuthConsumer consumer = new DefaultOAuthConsumer (clientKey, clientSecret);
//consumer.setAdditionalParameters(parameters);
consumer.setTokenWithSecret(userKey, userSecret);
HttpRequest httpReq = consumer.sign(connection); //Where the exception occurs
if (!postBody.toString().isEmpty()) {
connection.setDoOutput(true);
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.write(postBody);
outputStream.flush();
}
}
return connection;
}
From thier SDK:
using System.Text;
namespace ResponderSDK
{
using OAuth;
using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
class ResponderOAuth
{
/* Contains the last HTTP status code returned. */
public HttpStatusCode http_code;
/* Contains the last API call. */
public string url;
/* Set up the API root URL. */
public string host = "http://api.responder.co.il/v1.0/";
/* Set timeout default. */
public int timeout = 3000;
/* Set connect timeout. */
public int connect_timeout = 30;
/* Verify SSL Cert. */
public bool ssl_verifypeer = false;
/* Response format. */
public string format = "json";
/* Contains the last HTTP headers returned. */
public string http_info;
/* Set the useragent. */
public string useragent = "ResponderOAuth v0.1-beta";
/*debug info*/
public string headers_string;
public string base_string;
public string post_string;
/* Signature */
private OAuthSignatureMethod_HMAC_SHA1 signature;
/* OAuthConsumer */
private OAuthConsumer consumer;
/* Token */
private OAuthToken token;
public ResponderOAuth(string consumer_key, string consumer_secret, string oauth_token = null, string oauth_token_secret = null)
{
this.signature = new OAuthSignatureMethod_HMAC_SHA1();
this.consumer = new OAuthConsumer(consumer_key, consumer_secret);
if (!String.IsNullOrEmpty(oauth_token) && !String.IsNullOrEmpty(oauth_token_secret))
{
this.token = new OAuthToken(oauth_token, oauth_token_secret);
}
else
{
this.token = null;
}
}
public string http_request(string url, string method = "GET", ParametersArray parameters = null)
{
method = method.ToUpper();
if (url.LastIndexOf("https://") != 0 && url.LastIndexOf("http://") != 0)
{
url = String.Format("{0}{1}", this.host, url);
}
if (method.Equals("GET"))
parameters = null;
OAuthRequest request = OAuthRequest.from_consumer_and_token(this.consumer, this.token, method, url, parameters);
request.sign_request(this.signature, this.consumer, this.token);
this.base_string = request.base_string;
if (method.Equals("GET"))
return this.http(request.to_url(), "GET", request.to_header(), null);
else
return this.http(request.get_normalized_http_url(), method, request.to_header(), request.to_postdata());
}
private string http(string url, string method, WebHeaderCollection headers, string data = null)
{
List<string> new_http_info = new List<string>();
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);
HttpWebRequest request = null;
if (!method.Equals("DELETE"))
request = (HttpWebRequest)WebRequest.Create(url);
else
{
if (!String.IsNullOrEmpty(data))
{
url = String.Format("{0}?{1}", url, data);
}
request = (HttpWebRequest)WebRequest.Create(url);
}
/* WebRequest settings */
((HttpWebRequest)request).ProtocolVersion = System.Net.HttpVersion.Version10;
((HttpWebRequest)request).UserAgent = this.useragent;
((HttpWebRequest)request).ContinueTimeout = this.connect_timeout;
((HttpWebRequest)request).Timeout = this.timeout;
((HttpWebRequest)request).Headers = headers;
((HttpWebRequest)request).UseDefaultCredentials = true;
((HttpWebRequest)request).PreAuthenticate = true;
((HttpWebRequest)request).Credentials = CredentialCache.DefaultCredentials;
this.headers_string = headers.ToString();
this.post_string = data;
byte[] dataByteArray = null;
if ((!String.IsNullOrEmpty(data) && method.Equals("POST")) || method.Equals("PUT"))
{
((HttpWebRequest)request).ContentType = "application/x-www-form-urlencoded";
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
dataByteArray = encoding.GetBytes(data);
((HttpWebRequest)request).ContentLength = dataByteArray.Length;
((HttpWebRequest)request).Expect = "";
}
switch (method)
{
case "POST":
((HttpWebRequest)request).Method = "POST";
if (!String.IsNullOrEmpty(data))
{
Stream dataPost = request.GetRequestStream();
dataPost.Write(dataByteArray, 0, dataByteArray.Length);
dataPost.Close();
}
break;
case "PUT":
((HttpWebRequest)request).Method = "PUT";
if (!String.IsNullOrEmpty(data))
{
Stream dataPost = request.GetRequestStream();
dataPost.Write(dataByteArray, 0, dataByteArray.Length);
dataPost.Close();
}
break;
case "DELETE":
((HttpWebRequest)request).Method = "DELETE";
break;
}
WebResponse response = request.GetResponse();
this.http_code = ((HttpWebResponse)response).StatusCode;
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
return reader.ReadToEnd();
}
}
}
If your input String format is json, you can change content-type to "application/json" and try signing in after adding the setRequestProperty headers.

Verify OAuth1a signed request using Twitter joauth with RSA-SHA1?

I have a use case to authenticate OAuth1 request which is signed using RSA Private Key and verified at server end with RSA public key.
I found this library from Twitter which helps us authenticate/verify the Oauth signed requests. https://github.com/twitter/joauth
I want to leverage this library for verifying the request from Jersey or Spring MVC action method. The request from client would have been signed using private key. At my end I would use the public key of the client to verify the request. which means RSA-SHA1 algo.
Twitter joauth seem to be useful but I am missing the code that would transform HttpServletRequest to OAuthRequest
The library read-me file suggests this as facility but I could not find a code that does javax.servlet.http.HttpServletRequest --> com.twitter.joauth.OAuthRequest transformation.
The request verification happens in verify method which has following signature.
public VerifierResult verify(UnpackedRequest.OAuth1Request request, String tokenSecret, String consumerSecret);
Secondly I also want to know which is the most appropriate way to use/read RSA public key with twitter joauth when verify method takes String parameter ?
I have never used any library to authenticate users via Twitter. But I have just looked in the UnpackedRequest.OAuth1Request. You can create an instance of this class by filling all parameters. I have written Twitter OAuth Header creator, so you can just use it to fill those parameters or send POST requests directly without a library.
Here all classes what you need:
Signature - to generate an OAuth Signature.
public class Signature {
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
public static String calculateRFC2104HMAC(String data, String key)
throws java.security.SignatureException
{
String result;
try {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(data.getBytes());
result = new String(Base64.encodeBase64(rawHmac));
} catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
}
return result;
}
}
NvpComparator - to sort parameters you need in the header.
public class NvpComparator implements Comparator<NameValuePair> {
#Override
public int compare(NameValuePair arg0, NameValuePair arg1) {
String name0 = arg0.getName();
String name1 = arg1.getName();
return name0.compareTo(name1);
}
}
OAuth - for URL encode.
class OAuth{
...
public static String percentEncode(String s) {
return URLEncoder.encode(s, "UTF-8")
.replace("+", "%20").replace("*", "%2A")
.replace("%7E", "~");
}
...
}
HeaderCreator - to create all needed parameters and generate an OAuth header param.
public class HeaderCreator {
private String authorization = "OAuth ";
private String oAuthSignature;
private String oAuthNonce;
private String oAuthTimestamp;
private String oAuthConsumerSecret;
private String oAuthTokenSecret;
public String getAuthorization() {
return authorization;
}
public String getoAuthSignature() {
return oAuthSignature;
}
public String getoAuthNonce() {
return oAuthNonce;
}
public String getoAuthTimestamp() {
return oAuthTimestamp;
}
public HeaderCreator(){}
public HeaderCreator(String oAuthConsumerSecret){
this.oAuthConsumerSecret = oAuthConsumerSecret;
}
public HeaderCreator(String oAuthConsumerSecret, String oAuthTokenSecret){
this(oAuthConsumerSecret);
this.oAuthTokenSecret = oAuthTokenSecret;
}
public String getTwitterServerTime() throws IOException, ParseException {
HttpsURLConnection con = (HttpsURLConnection)
new URL("https://api.twitter.com/oauth/request_token").openConnection();
con.setRequestMethod("HEAD");
con.getResponseCode();
String twitterDate= con.getHeaderField("Date");
DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
Date date = formatter.parse(twitterDate);
return String.valueOf(date.getTime() / 1000L);
}
public String generatedSignature(String url, String method, List<NameValuePair> allParams,
boolean withToken) throws SignatureException {
oAuthNonce = String.valueOf(System.currentTimeMillis());
allParams.add(new BasicNameValuePair("oauth_nonce", oAuthNonce));
try {
oAuthTimestamp = getTwitterServerTime();
allParams.add(new BasicNameValuePair("oauth_timestamp", oAuthTimestamp));
}catch (Exception ex){
//TODO: Log!!
}
Collections.sort(allParams, new NvpComparator());
StringBuffer params = new StringBuffer();
for(int i=0;i<allParams.size();i++)
{
NameValuePair nvp = allParams.get(i);
if (i>0) {
params.append("&");
}
params.append(nvp.getName() + "=" + OAuth.percentEncode(nvp.getValue()));
}
String signatureBaseStringTemplate = "%s&%s&%s";
String signatureBaseString = String.format(signatureBaseStringTemplate,
OAuth.percentEncode(method),
OAuth.percentEncode(url),
OAuth.percentEncode(params.toString()));
String compositeKey = OAuth.percentEncode(oAuthConsumerSecret)+"&";
if(withToken) compositeKey+=OAuth.percentEncode(oAuthTokenSecret);
oAuthSignature = Signature.calculateRFC2104HMAC(signatureBaseString, compositeKey);
return oAuthSignature;
}
public String generatedAuthorization(List<NameValuePair> allParams){
authorization = "OAuth ";
Collections.sort(allParams, new NvpComparator());
for(NameValuePair nvm : allParams){
authorization+=nvm.getName()+"="+OAuth.percentEncode(nvm.getValue())+", ";
}
authorization=authorization.substring(0,authorization.length()-2);
return authorization;
}
}
Explain:
1. getTwitterServerTime
In oAuthTimestamp you need not your time of server but the time of a Twitter server. You can optimize it saving this param if you always send requests in the certain Twitter server.
2. HeaderCreator.generatedSignature(...)
url - logically url to twitter API
method - GET or POST. You must use always "POST"
allParams - Parameters which you know to generate signature ("param_name", "param_value");
withToken - if you know oAuthTokenSecret put true. Otherwise false.
3. HeaderCreator.generatedAuthorization(...)
Use this method after generatedSignature(...) to generate an OAuth header string.
allParams - it is parameters which you have used in generatedSignature(...) plus: nonce, signature, timestamp. Always use:
allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce()));
allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature()));
allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp()));
Now you can use it to fill UnpackedRequest.OAuth1Request in your library. Also here an example to authenticate user in SpringMVC without the library:
Requests - to send post requests.
public class Requests {
public static String sendPost(String url, String urlParameters, Map<String, String> prop) throws Exception {
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
if(prop!=null) {
for (Map.Entry<String, String> entry : prop.entrySet()) {
con.setRequestProperty(entry.getKey(), entry.getValue());
}
}
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
BufferedReader in;
if(responseCode==200) {
in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
}else{
in = new BufferedReader(
new InputStreamReader(con.getErrorStream()));
}
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
}
twAuth(...) - put it in your controller. Execute it when an user want to authenticate in your site via Twitter.
#RequestMapping(value = "/twauth", method = RequestMethod.GET)
#ResponseBody
public String twAuth(HttpServletResponse response) throws Exception{
try {
String url = "https://api.twitter.com/oauth/request_token";
List<NameValuePair> allParams = new ArrayList<NameValuePair>();
allParams.add(new BasicNameValuePair("oauth_callback", "http://127.0.0.1:8080/twlogin"));
allParams.add(new BasicNameValuePair("oauth_consumer_key", "2YhNLyum1VY10UrWBMqBnatiT"));
allParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1"));
allParams.add(new BasicNameValuePair("oauth_version", "1.0"));
HeaderCreator headerCreator = new HeaderCreator("RUesRE56vVWzN9VFcfA0jCBz9VkvkAmidXj8d1h2tS5EZDipSL");
headerCreator.generatedSignature(url,"POST",allParams,false);
allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce()));
allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature()));
allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp()));
Map<String, String> props = new HashMap<String, String>();
props.put("Authorization", headerCreator.generatedAuthorization(allParams));
String twitterResponse = Requests.sendPost(url,"",props);
Integer indOAuthToken = twitterResponse.indexOf("oauth_token");
String oAuthToken = twitterResponse.substring(indOAuthToken, twitterResponse.indexOf("&",indOAuthToken));
response.sendRedirect("https://api.twitter.com/oauth/authenticate?" + oAuthToken);
}catch (Exception ex){
//TODO: Log
throw new Exception();
}
return "main";
}
twLogin(...) - put it in your controller. It is callback from Twitter.
#RequestMapping(value = "/twlogin", method = RequestMethod.GET)
public String twLogin(#RequestParam("oauth_token") String oauthToken,
#RequestParam("oauth_verifier") String oauthVerifier,
Model model, HttpServletRequest request){
try {
if(oauthToken==null || oauthToken.equals("") ||
oauthVerifier==null || oauthVerifier.equals(""))
return "main";
String url = "https://api.twitter.com/oauth/access_token";
List<NameValuePair> allParams = new ArrayList<NameValuePair>();
allParams.add(new BasicNameValuePair("oauth_consumer_key", "2YhNLyum1VY10UrWBMqBnatiT"));
allParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1"));
allParams.add(new BasicNameValuePair("oauth_token", oauthToken));
allParams.add(new BasicNameValuePair("oauth_version", "1.0"));
NameValuePair oAuthVerifier = new BasicNameValuePair("oauth_verifier", oauthVerifier);
allParams.add(oAuthVerifier);
HeaderCreator headerCreator = new HeaderCreator("RUesRE56vVWzN9VFcfA0jCBz9VkvkAmidXj8d1h2tS5EZDipSL");
headerCreator.generatedSignature(url,"POST",allParams,false);
allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce()));
allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature()));
allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp()));
allParams.remove(oAuthVerifier);
Map<String, String> props = new HashMap<String, String>();
props.put("Authorization", headerCreator.generatedAuthorization(allParams));
String twitterResponse = Requests.sendPost(url,"oauth_verifier="+oauthVerifier,props);
//Get user id
Integer startIndexTmp = twitterResponse.indexOf("user_id")+8;
Integer endIndexTmp = twitterResponse.indexOf("&",startIndexTmp);
if(endIndexTmp<=0) endIndexTmp = twitterResponse.length()-1;
Long userId = Long.parseLong(twitterResponse.substring(startIndexTmp, endIndexTmp));
//Do what do you want...
}catch (Exception ex){
//TODO: Log
throw new Exception();
}
}

Post method in RestAssured throws java.net.ConnectException

I'm trying to Post a JSON to a Rest service using RestAssured and it throws java.net.ConnectException error.
Since my JSON message is complex, I've made it available within the txt file.
public class PPJson {
public static void main(String[] args) throws IOException, JSONException {
BufferedReader tempreader = new BufferedReader(new FileReader("/Users/RestService/Jsonfileinput.txt"));
StringBuilder sbuilder = new StringBuilder();
String line = tempreader.readLine();
while (line != null) {
sbuilder.append(line);
line = tempreader.readLine();
}
tempreader.close();
//Initializing Rest API's URL
String APIUrl = "http://api.sample.com/api/v3/parcel/collect?apiKey={Value}";
//Initializing payload or API body
String APIBody = sbuilder.toString();
// Building request using requestSpecBuilder
RequestSpecBuilder builder = new RequestSpecBuilder().setBody(APIBody).setContentType("application/json; charset=UTF-8");
RequestSpecification requestSpec = builder.build();
//Making post request with authentication
Response response = given().authentication().preemptive().basic("","").spec(requestSpec).when().post(APIUrl);
JSONObject JSONResponseBody = new JSONObject(response.body().asString());
//Fetching the desired value of a parameter
String result = JSONResponseBody.getString("status");
System.out.println(result);
}
}
#all, the issue has been fixed, removed the references to RequestSpecs and here's the code snippet
public class ParcelPointJson {
public static void main(String[] args) throws IOException, JSONException {
BufferedReader tempreader = new BufferedReader(new FileReader("/Users/srkrish/gitTrial/pim-automation/RestService/Jsonfileinput.txt"));
StringBuilder sbuilder = new StringBuilder();
String line = tempreader.readLine();
while (line != null) {
sbuilder.append(line);
line = tempreader.readLine();
}
tempreader.close();
//Initializing Rest API's URL
String APIUrl = "http://api.staging.wow.parcelpoint.com.au/api/v3/parcel/collect?apiKey=09BH1TXV";
//Initializing payload or API body
String APIBody = sbuilder.toString();
//Making post request with authentication
Response response = given().contentType("application/json; charset=UTF-8").body(APIBody).when().post(APIUrl);
JSONObject JSONResponseBody = new JSONObject(response.body().asString());
//Fetching the desired value of a parameter
String result = JSONResponseBody.getString("parcelId");
System.out.println(result);
//Assert.assertEquals(result, "200");
}
}

Gson - attempting to convert json string to custom object

Here is my Json returned from the server
{"ErrorCode":1005,"Message":"Username does not exist"}
Here is my class for an error
public class ErrorModel {
public int ErrorCode;
public String Message;
}
and here is my conversion code.
public static ErrorModel GetError(String json) {
Gson gson = new Gson();
try
{
ErrorModel err = gson.fromJson(json, ErrorModel.class);
return err;
}
catch(JsonSyntaxException ex)
{
return null;
}
}
It is always throwing a JsonSyntaxException. Any ideas what could be my problem here?
EDIT: As requested, here is further elaboration.
My backend is an ASP.NET MVC 2 application acting as a rest API. The backend isn't the problem here, as my actions (and even server errors) all return Json (using the built in JsonResult). Here's a sample.
[HttpPost]
public JsonResult Authenticate(AuthenticateRequest request)
{
var authResult = mobileService.Authenticate(request.Username, request.Password, request.AdminPassword);
switch (authResult.Result)
{
//logic omitted for clarity
default:
return ExceptionResult(ErrorCode.InvalidCredentials, "Invalid username/password");
break;
}
var user = authResult.User;
string token = SessionHelper.GenerateToken(user.UserId, user.Username);
var result = new AuthenticateResult()
{
Token = token
};
return Json(result, JsonRequestBehavior.DenyGet);
}
The basic logic is to auth the user cretentials and either return an ExceptionModel as json or an AuthenticationResult as json.
Here is my server side Exception Model
public class ExceptionModel
{
public int ErrorCode { get; set; }
public string Message { get; set; }
public ExceptionModel() : this(null)
{
}
public ExceptionModel(Exception exception)
{
ErrorCode = 500;
Message = "An unknown error ocurred";
if (exception != null)
{
if (exception is HttpException)
ErrorCode = ((HttpException)exception).ErrorCode;
Message = exception.Message;
}
}
public ExceptionModel(int errorCode, string message)
{
ErrorCode = errorCode;
Message = message;
}
}
When the above authentication is called with invalid credentials, the error result is returned as expected. The Json returned is the Json above in the question.
On the android side, I first build an object with my key-value pairs.
public static HashMap<String, String> GetAuthenticationModel(String username, String password, String adminPassword, String abbr)
{
HashMap<String, String> request = new HashMap<String, String>();
request.put("SiteAbbreviation", abbr);
request.put("Username", username);
request.put("Password", password);
request.put("AdminPassword", adminPassword);
return request;
}
Then, I send off an http post and return as a string whatever is sent back.
public static String Post(ServiceAction action, Map<String, String> values) throws IOException {
String serviceUrl = GetServiceUrl(action);
URL url = new URL(serviceUrl);
URLConnection connection = url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String data = GetPairsAsString(values);
DataOutputStream output = new DataOutputStream(connection.getOutputStream());
output.writeBytes(data);
output.flush();
output.close();
DataInputStream input = new DataInputStream(connection.getInputStream());
String line;
String result = "";
while (null != ((line = input.readLine())))
{
result += line;
}
input.close ();
return result;
}
private static String GetServiceUrl(ServiceAction action)
{
return "http://192.168.1.5:33333" + action.toString();
}
private static String GetPairsAsString(Map<String, String> values){
String result = "";
Iterator<Entry<String, String>> iter = values.entrySet().iterator();
while(iter.hasNext()){
Map.Entry<String, String> pairs = (Map.Entry<String, String>)iter.next();
result += "&" + pairs.getKey() + "=" + pairs.getValue();
}
//remove the first &
return result.substring(1);
}
Then I take that result and pass it into my parser to see if it is an error
public static ErrorModel GetError(String json) {
Gson gson = new Gson();
try
{
ErrorModel err = gson.fromJson(json, ErrorModel.class);
return err;
}
catch(JsonSyntaxException ex)
{
return null;
}
}
But, JsonSyntaxException is always thrown.
Might help to know more about the exception, but the same code sample works fine here. I suspect there's a piece of code you omitted that's causing the problem (perhaps the creation/retrieval of the JSON string). Here's a code sample that worked fine for me on Java 1.6 and Gson 1.6:
import com.google.gson.Gson;
public class ErrorModel {
public int ErrorCode;
public String Message;
public static void main(String[] args) {
String json = "{\"ErrorCode\":1005,\"Message\":\"Username does not exist\"}";
Gson gson = new Gson();
ErrorModel err = gson.fromJson(json, ErrorModel.class);
System.out.println(err.ErrorCode);
System.out.println(err.Message);
}
}

Categories