I'm using GWT and I want to make a JSONP request, which invokes a GWT method of mine when it returns.
However, I'm having trouble figuring out how to specify the GWT method to invoke on callback. Can anyone help? Here's my example code:
private native void fetchUserData(String accessToken) /*-{
var callback = "com.company.example.FacebookApi::handleUser";
var url = "https://graph.facebook.com/me?access_token="+accessToken+"&callback=" + callback;
// use jsonp to call the graph
var script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
}-*/;
public void handleUser(Object o) {
Window.alert("Received object with class: " + o.getClass().getName())
}
This code is ported from this example: Facebook Without SDK.
Alternatively, I just discovered there's a GWT JsonpRequestBuilder which I haven't had a chance to use yet, but if anyone can give an example without using any native code... then all the better.
Thanks!
Figured it out, thanks in large part to these examples:
Cross Domain Requests with Gwt, Jsonp
Cross site referenceing in GWT
Here's the updated code, per the comments (no callback specified, using Javascript Overlay Type)
private void fetchDataUsingGwt() {
String url = "https://graph.facebook.com/me?access_token=" + accessToken;
JsonpRequestBuilder requestBuilder = new JsonpRequestBuilder();
requestBuilder.requestObject(url, new AsyncCallback<FbUser>() {
@Override
public void onFailure(Throwable caught) {
Window.alert(caught.getMessage());
}
@Override
public void onSuccess(FbUser fbUser) {
if (fbUser.isError()) {
StringBuilder builder = new StringBuilder();
builder.append("Fb error: ");
builder.append(fbUser.getError().getMessage() + ", ");
builder.append(fbUser.getError().getCode());
String message = builder.toString();
Window.alert(message);
return;
}
StringBuilder builder = new StringBuilder();
builder.append("Fetched user: " + fbUser.getFirstName() + " " + fbUser.getLastName());
builder.append(" from " + fbUser.getHometown().getName());
builder.append(" born on " + fbUser.getBirthday());
builder.append(" with id " + fbUser.getId() + " and email " + fbUser.getEmail());
builder.toString();
String details = builder.toString();
Window.alert("Got: " + details);
}
});
}
And the response is automatically wrapped using JSO like so:
public class FbError extends JavaScriptObject {
protected FbError() {
}
public final native String getMessage() /*-{
return this.message;
}-*/;
public final native String getType() /*-{
return this.type;
}-*/;
public final native String getCode() /*-{
return this.code;
}-*/;
public final native String getSubCode() /*-{
return this.error_subcode;
}-*/;
}
public class Hometown extends JavaScriptObject {
protected Hometown() {
}
public final native String getName() /*-{
return this.name;
}-*/;
public final native String getId() /*-{
return this.id;
}-*/;
}
public class ErrorableJso extends JavaScriptObject {
public boolean isError() {
return getError() != null;
}
public final native FbError getError() /*-{
return this.error;
}-*/;
}
public class FbUser extends ErrorableJso {
// TODO: Separate call needed to retrieve profile pic
protected FbUser() {
}
public final native String getFirstName() /*-{
return this.first_name;
}-*/;
public final native String getLastName() /*-{
return this.last_name;
}-*/;
public final native String getId() /*-{
return this.id;
}-*/;
public final native String getBirthday() /*-{
return this.birthday;
}-*/;
public final native String getEmail() /*-{
return this.email;
}-*/;
public final native Hometown getHometown() /*-{
return this.hometown;
}-*/;
}
For completeness, this is the raw JSON response the JSO wraps. Because of the inheritance, the same FbUser
object is used if there's either an error like so:
{
"error": {
"message": "Error validating access token: Session has expired at unix time 1342044000. The current unix time is 1342050026.",
"type": "OAuthException",
"code": 190,
"error_subcode": 463
}
}
Or the expected User object:
{
"id": "23232323",
"name": "Andrew Cuga",
"first_name": "Andrew",
"last_name": "Cuga",
"link": "http://www.facebook.com/TheAndy",
"username": "TheAndy",
"birthday": "02/20/2011",
"hometown": {
"id": "108530542504412",
"name": "Newark, Delaware"
} // ... etc
}
Note the error
and hometown
fields in the JSON response are easily wrapped into JavaScriptObjects.