Getting the relevant error message using .net SDK - facebook

I'm using Facebook ads api SDK for .net (http://www.nuget.org/packages/Facebook/6.4.2) and when I catch an error, the message is always the same general error in the exception message object:
(FacebookApiException - #100) Invalid parameter
It happens since I moved to the versioned calls (v2.2) - before that I used the unversioned calls and it was fine. For example, this is how I get the error (using regular try catch in c#):
try
{
FacebookClient facebookClient = new FacebookClient();
facebookClient.AccessToken = "<YOUR_ACCESS_TOKEN>"
Dictionary<string, object> parameters = new Dictionary<string, object>();
string name = Guid.NewGuid().ToString();
parameters.Add("name", name);
parameters.Add("conversion_specs", "");
parameters.Add("campaign_id", "6024570447800");
parameters.Add("creative", "{\"creative_id\":\"6024570452200\"}");
parameters.Add("redownload", "false");
parameters.Add("tracking_specs", "");
parameters.Add("view_tags", "[]");
var result = facebookClient.Post("v2.2/act_107893676040337/adgroups", parameters) as IDictionary<string, object>;
}
catch (Exception ex)
{
FacebookApiException fbEx = ex as FacebookApiException;
string errorMsg = fbEx.Message;
}
It happens because Facebook changed the return error object and added 2 new fields: error_user_title, error_user_msg.
Is there a way to access these fields in the FacebookApiException object ?
How can I extract the relevant error message?

I dived into this issue and it's not a Facebook problem. The problem is in the third party SDK.
I contacted the development team, they aware of this issue and fixed it in the last beta version.

Related

Notification message sent thru pinpoint does not reach the Mobile

Based on the link I tried tried working and here is the code I tried out
public static void SendNotification2(String appid, String pinpointEndpointId){
try {
GetEndpointRequest getEndpointRequest = new GetEndpointRequest()
.withApplicationId(appid)
.withEndpointId(pinpointEndpointId);
AmazonPinpoint pinpoint = AmazonPinpointClientBuilder.standard().withRegion(Regions.US_EAST_1).build();
GetEndpointResult endpointResult = pinpoint.getEndpoint(getEndpointRequest);
EndpointResponse endpointResponse = endpointResult.getEndpointResponse();
Map<String, String> data = new HashMap<String, String>();
data.put("message", "test");
DirectMessageConfiguration directMessageConfiguration =
new DirectMessageConfiguration().withGCMMessage(new GCMMessage().withData(data).withSilentPush(true));
AddressConfiguration addressConfiguration = new AddressConfiguration().withChannelType(ChannelType.GCM);
MessageRequest messageRequest = new MessageRequest().withMessageConfiguration(directMessageConfiguration)
.addAddressesEntry(endpointResponse.getAddress(), addressConfiguration);
SendMessagesRequest sendMessagesRequest = new SendMessagesRequest()
.withApplicationId(appid)
.withMessageRequest(messageRequest);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The code executes successfully without any error/exception but i do not see the notification.
However when i post the message from "Direct Messaging" section of pinpoint with the Endpoint Id I am able to see the notification in mobile.
Also using Amazon CLI the Notification message is delivered:
aws --region="us-east-1" pinpoint send-messages --application-id 1fd19ca6fa944a79bdd91beddb4b4f7e --message-request "{\"Context\":{},\"MessageConfiguration\":{\"DefaultMessage\":{\"Body\":\"Test from default message\",\"Substitutions\":{}},\"DefaultPushNotificationMessage\":{},\"APNSMessage\":{},\"GCMMessage\":{\"Data\":{\"message\":\"test\"},\"SilentPush\":true},\"BaiduMessage\":{},\"ADMMessage\":{},\"SMSMessage\":{}},\"Addresses\":{\"cltaa5owuOU:APA91bFOBUB5YRi_Ac6teNmuu19aoFDAByOeoVbqLmY1Yp6cZEp_aueunDU1ZPB6H50GKBfuxu300z-El_sEjxo72crYKnklI-wboxXDk180JICrif0c7R-fR4xFOm5WsQOGUJZPFLG6\":{\"ChannelType\":\"GCM\"}},\"Endpoints\":{}}
Any help will be appreciated.
Thanks

I am trying to update status to twitter using twitter4j but it does not work

I succeeded to get every credentials(Oauth_token,Oauth_verifier).
With it, I tried to post a text to twitter account, but it always fail with error message "No authentication challenges found"
I found some solution like
"Check the time zone automatically",
"import latest twitter4j library" etc..
but after check it, still not work.
Is there anyone can show me the way.
code is like below
public static void updateStatus(final String pOauth_token,final String pOauth_verifier) {
new Thread() {
public void run() {
Looper.prepare();
try {
TwitterFactory factory = new TwitterFactory();
AccessToken accessToken = new AccessToken(pOauth_token,pOauth_verifier);
Twitter twitter = factory.getInstance();
twitter.setOAuthConsumer(Cdef.consumerKey, Cdef.consumerSecret);
twitter.setOAuthAccessToken(accessToken);
if (twitter.getAuthorization().isEnabled()) {
Log.e("btnTwSend","인증값을 셋팅하였고 API를 호출합니다.");
Status status = twitter.updateStatus(Cdef.sendText + " #" + String.valueOf(System.currentTimeMillis()));
Log.e("btnTwSend","status:" + status.getText());
}
} catch (Exception e) {
Log.e("btnTwSend",e.toString());
}
};
}.start();
}
"No authentication challenges found"
I think you are missing Access token secret in your code. That is why you are getting this exception.
Try following :
ConfigurationBuilder configurationBuilder;
Configuration configuration;
// Set the proper configuration parameters
configurationBuilder = new ConfigurationBuilder();
configurationBuilder
.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
configurationBuilder
.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
// Access token
configurationBuilder.setOAuthAccessToken(ACCESS_TOKEN);
// Access token secret
configurationBuilder
.setOAuthAccessTokenSecret(ACCESS_TOKEN_SECRET);
// Get the configuration object based on the params
configuration = configurationBuilder.build();
// Pass it to twitter factory to get the proprt twitter instance.
twitterFactory = new TwitterFactory(configuration);
twitter = twitterFactory.getInstance();
// use this instance to update
twitter.updateStatus("Your status");
I finally found the reason.
I thought parameter named 'oauth_token' , 'oauth_verifier' is member of accesstoken,
but it was not true.
I just had to pass one more way to get correct key.
and this way needs 'oauth_token' , 'oauth_verifier' to get accesstoken.
This code must add one more code below:
mAccessToken = mTwitter.getOAuthAccessToken(REQUEST_TOKEN,OAUTH_VERIFIER);

Spring RestTemplate Parse Custom Error Response

Given a REST service call
http://acme.com/app/widget/123
returns:
<widget>
<id>123</id>
<name>Foo</name>
<manufacturer>Acme</manufacturer>
</widget>
This client code works:
RestTemplate restTemplate = new RestTemplate();
XStreamMarshaller xStreamMarshaller = new XStreamMarshaller();
xStreamMarshaller.getXStream().processAnnotations(
new Class[] {
Widget.class,
ErrorMessage.class
});
HttpMessageConverter<?> marshallingConverter = new MarshallingHttpMessageConverter(
xStreamMarshaller, xStreamMarshaller);
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(marshallingConverter);
restTemplate.setMessageConverters(converters);
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 123L);
However, calling http://acme.com/app/widget/456 returns:
<error>
<message>Widget 456 does not exist</message>
<timestamp>Wed, 12 Mar 2014 10:34:37 GMT</timestamp>
</error>
but this client code throws an Exception:
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 456L);
org.springframework.web.client.HttpClientErrorException: 404 Not Found
I tried:
try {
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 456L);
}
catch (HttpClientErrorException e) {
ErrorMessage errorMessage = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", ErrorMessage.class, 456L);
// etc...
}
The second invocation just threw another HttpClientErrorException, plus it does not feel right calling the service twice.
Is there a way to call the service once and parse the response into a Widget on success and an ErrorMessage when not found?
Following from my comment, I checked the HttpClientErrorException JavaDoc and it does support both setting/getting the statusText as well as the responseBody. However they are optional and RestTemplate may not populate them - you'll need to try something like:
try {
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 456L);
}
catch (HttpClientErrorException e) {
String responseBody = e.getResponseBodyAsString();
String statusText = e.getStatusText();
// log or process either of these...
// you'll probably have to unmarshall the XML manually (only 2 fields so easy)
}
If they are both empty/null then you may have to extend the RestTemplate class involved and populate those fields yourself and/or raise a Jira issue on the Spring site.
You can also create an object from Error response body if you like:
ObjectMapper om = new ObjectMapper();
String errorResponse = ex.getResponseBodyAsString();
MyClass obj = om.readValue(errorResponse, MyClass.class);
As you already catch the HttpClientErrorException object, it should allows you to easily extract useful information about the error and pass that to the caller.
For example:
try{
<call to rest endpoint using RestTemplate>
} catch(HttpClientErrorException e){
HttpStatus statusCode = e.getStatusCode();
String body = e.getResponseBodyAsString();
}
IMO if one needs to further de-serialize the error message body into some relevant object, that can be handled somewhere outside of the catch statement scope.
I too have found this a disturbing change in the Spring library. You used to be able to throw a ResponseStatusException and pass it the HttpStatus code and a custom message and then catch the HttpClientErrorException and simply print getMessage() to see the custom error. This no longer works. In order for me to print the custom error, I had to capture the ResponseBody as a String, getResponseBodyAsString on the HttpClientErrorException. Then I needed to parse this as a String doing some pretty hokey substring manipulation. Doing this strips out the information from the ResponseBody and gives the message sent by my server. The code to do this follows:
String message = hce.getResponseBodyAsString();
int start, end;
start = message.lastIndexOf(":", message.lastIndexOf(",")-1) + 2;
end = message.lastIndexOf(",") -1;
message = message.substring(start, end);
System.out.println(message);
When I test this using ARC or Postman, they can display the correct message after I add server.error.include-message=always to my application.properties file on the server. I am not sure what method they are using to extract the message but that would be nice to know.

Update records using Salesforce REST API - Patch method not working

I'm trying to update a record residing in salesforce table. Im using the Java HttpClient REST API to do the same. Getting an error when we use PATCH to update a record in Salesforce.
PostMethod post = new PostMethod(
instanceUrl + "/services/data/v20.0/sobjects/" +
objectName + "/" + Id + "?_HttpMethod=PATCH"
);
[{"message":"HTTP Method 'PATCH' not allowed. Allowed are HEAD,GET,POST","errorCode":"METHOD_NOT_ALLOWED"}]
Also tried doing the following:
PostMethod post = new PostMethod(
instanceUrl + "/services/data/v20.0/sobjects/" + objectName + "/" + Id)
{
public String getName() { return "PATCH";
}
};
This also returns the same error. We are using apache tomcat with commons-httpclient-3.1.jar library. Please advise on how this can be done.
Please check if you you're using the right implementation of PATCH method, see: Insert or Update (Upsert) a Record Using an External ID.
Also check if your REST URL is correct, probably your objectId is not passed in correctly from Javascript.
The ObjectName is the Name of an Salesforce table i.e. 'Contact'. And Id is the Id of a specific record you want to update in the table.
Similar:
Can I update without an ID?
for Drupal: How to deal with SalesforceException: HTTP Method 'PATCH' not allowed. Allowed are HEAD,GET,POST
As I think you're aware, commons httpclient 3.1 does not have the PATCH method, and the library has been end-of-lifed. In your code above, you're trying to add the HTTP method as a query parameter, which doesn't really make sense.
As seen on SalesForce Developer Board, you can do something like this instead:
HttpClient httpclient = new HttpClient();
PostMethod patch = new PostMethod(url) {
#Override
public String getName() {
return "PATCH";
}
};
ObjectMapper mapper = new ObjectMapper();
StringRequestEntity sre = new StringRequestEntity(mapper.writeValueAsString(data), "application/json", "UTF-8");
patch.setRequestEntity(sre);
httpclient.executeMethod(patch);
This allows you to PATCH without switching out your httpclient library.
I created this method to send the patch request via the Java HttpClient class.
I am using JDK V.13
private static VarHandle Modifiers; // This method and var handler are for patch method
private static void allowMethods(){
// This is the setup for patch method
System.out.println("Ignore following warnings, they showed up cause we are changing some basic variables.");
try {
var lookUp = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
Modifiers = lookUp.findVarHandle(Field.class, "modifiers", int.class);
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
try {
Field methodField = HttpURLConnection.class.getDeclaredField("methods");
methodField.setAccessible(true);
int mods = methodField.getModifiers();
if (Modifier.isFinal(mods)) {
Modifiers.set(methodField, mods & ~Modifier.FINAL);
}
String[] oldMethods = (String[])methodField.get(null);
Set<String> methodsSet = new LinkedHashSet<String>(Arrays.asList(oldMethods));
methodsSet.addAll(Collections.singletonList("PATCH"));
String[] newMethods = methodsSet.toArray(new String[0]);
methodField.set(null, newMethods);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}

How do I handle/fix "Error getting response stream (ReadDone2): ReceiveFailure" when using MonoTouch?

I am using MonoTouch to build an iPhone app. In the app I am making Web Requests to pull back information from the web services running on our server.
This is my method to build the request:
public static HttpWebRequest CreateRequest(string serviceUrl, string methodName, JsonObject methodArgs)
{
string body = "";
body = methodArgs.ToString();
HttpWebRequest request = WebRequest.Create(serviceUrl) as HttpWebRequest;
request.ContentLength = body.Length; // Set type to POST
request.Method = "POST";
request.ContentType = "text/json";
request.Headers.Add("X-JSON-RPC", methodName);
StreamWriter strm = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
strm.Write(body);
strm.Close();
return request;
}
Then I call it like this:
var request = CreateRequest(URL, METHOD_NAME, args);
request.BeginGetResponse (new AsyncCallback(ProcessResponse), request);
And ProcessResponse looks like this:
private void ProcessResponse(IAsyncResult result)
{
try
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result)) // this is where the exception gets thrown
{
using (StreamReader strm = new System.IO.StreamReader(response.GetResponseStream()))
{
JsonValue value = JsonObject.Load(strm);
// do stuff...
strm.Close();
} // using
response.Close();
} // using
Busy = false;
}
catch(Exception e)
{
Console.Error.WriteLine (e.Message);
}
}
There is another question about this issue for Monodroid and the answer there suggested explicitly closing the output stream. I tried this but it doesn't solve the problem. I am still getting a lot of ReadDone2 errors occurring.
My workaround at the moment involves just re-submitting the Web Request if an error occurs and the second attempt seems to work in most cases. These errors only happen when I am testing on the phone itself and never occur when using the Simulator.
Whenever possible try to use WebClient since it will deal automatically with a lot of details (including streams). It also makes it easier to make your request async which is often helpful for not blocking the UI.
E.g. WebClient.UploadDataAsync looks like a good replacement for the above. You will get the data, when received from the UploadDataCompleted event (sample here).
Also are you sure your request is always and only using System.Text.Encoding.ASCII ? using System.Text.Encoding.UTF8 is often usedm, by default, since it will represent more characters.
UPDATE: If you send or receive large amount to byte[] (or string) then you should look at using OpenWriteAsync method and OpenWriteCompleted event.
This is a bug in Mono, please see https://bugzilla.xamarin.com/show_bug.cgi?id=19673