NetBeans e lo sviluppo di applicazioni Java/JavaFX per Facebook
Agenda Goals Architecture Samples step by step References
Why JavaFX for Facebook Facebook as a world wide content manager: Photos and Videos the main assets No manipulation allowed, just a repository RIA apps everywhere
JavaFX vision JavaFX is the Platform for Creating and Delivering Rich Internet Applications Across Multiple Screens JavaFX is Powered by Java
JavaFX architecture JavaFX Applications and Services JavaFX Apps Framework JavaFX Desktop Runtime Desktop Extensions JavaFX Mobile Runtime JavaFX TV Runtime Mobile Extensions TV Extensions JavaFX Common Profile Authoring Tools Developer Tools (IDE Plug ins, RAD, Production Suite) Designer Tools (Authoring, Publishing, Media Encoding) Java Platform (Java Plug in)
Facebook developing model HTTP request HTML/HTTP HTTP request facebook Callback canvas URL FBML or iframe (html/http) Web application HTTP request facebook REST server XML or JSON Glassfish
Sample Architecture
Architecture details
Sequence diagram
First Facebook Web App Get Netbeans 6.8/6.7.1 with Glassfish 2.1/3 Create a FBSaas application Drag: usersgetloggedinuser New Web app application Into index.jsp drag the Facebook usersgetloggedinuser service Add in top JSP: <%! Add under //TODO: String sessionkey; %> sessionkey = FacebookSocialNetworkingServiceAuthenticator.getSessionKey(request, response); out.println("<br>the SaasService returned: " + result.getdataasstring()); out.println("<br>\nthe SaasService session returned: " + sessionkey);
Generated code: org.netbeans.saas.facebook.* <%@ page import="org.netbeans.saas.*, org.netbeans.saas.facebook.*" %> <% Try { String format = null; RestResponse result = FacebookSocialNetworkingService.usersGetLoggedInUser(request, response, format); I f (result1.getdataasobject(facebook.socialnetworkingservice.facebookresponse.usersgetloggedinuserresponse.class) instanceof facebook.socialnetworkingservice.facebookresponse.usersgetloggedinuserresponse) { facebook.socialnetworkingservice.facebookresponse.usersgetloggedinuserresponse result1obj = result1.getdataasobject(facebook.socialnetworkingservice.facebookresponse.usersgetloggedinuserresponse.class); els e if (result1.getdataasobject(facebook.socialnetworkingservice.facebookresponse.errorresponse.class) instanceof facebook.socialnetworkingservice.facebookresponse.errorresponse) { facebook.socialnetworkingservice.facebookresponse.errorresponse result1obj = result1.getdataasobject(facebook.socialnetworkingservice.facebookresponse.errorresponse.class); //TODO - Uncomment the print Statement below to print result. sessionkey=facebooksocialnetworkingserviceauthenticator.getsessionkey(request,response); out.println("<br>the SaasService returned: " + result1.getdataasstring()); out.println("<br>\nthe SaasService session returned: " + sessionkey); catch (Exception ex) { ex.printstacktrace(); %>
Netbeans Saas generated packages org.netbeans.saas RestConnection/RestResponse handler org.netbeans.saas.facebook FacebookSocialNetworkingServiceAuthenticator. sign() service in FacebookSocialNetworkingService: wrapper on REST function used in.jsp with drag&drop
setup application on FB http://www.facebook.com/developers/
setup api_key & secret Update facebooksocialnetworkingserviceauthenticator.properties:
First JavaFX app Create an FBapp as a JavaFX application Set in application properties:
Main.fx (1/2) In main.fx: package fbapp; import javafx.scene.scene; import javafx.scene.text.font; import javafx.scene.text.text; import javafx.stage.stage; import javafx.io.http.httprequest; import javafx.scene.paint.color; var apikey: String; var sessionkey: String; var sessionkeyjnlp: String; sessionkey = {FX.getArgument("sessionkey").toString(); sessionkeyjnlp = {FX.getArgument("sessionkeyjnlp").toString();
Main.fx (2/2) In main.fx: Stage { title: "FacebookClient" width: 500 height: 200 scene: Scene { fill: Color.GREEN content: [ Text { font : Font { size: 15 x: 10, y: 20 content: "SessionID:" ] Text{ content: bind sessionkeyjnlp translatex: 10 translatey: 40 font:font{ size: 15 Text { font : Font { size: 15 x: 10, y: 70 content: bind sessionkey
Setup arguments to pass JavaFX In FBapp.html of FBapp, with a copy&past from Fbapp project Tab: Files File: Fbapp.html:
Setup arguments to pass JavaFX Past in index.jsp of FBSaas, adding a line: <script src="http://dl.javafx.com/1.2/dtfx.js"></script> <script> javafx( { archive: "FBapp.jar", draggable: true, width: 500, height: 200, code: "fbapp.main", name: "FBapp", sessionkey: "<%=sessionkey%>" ); </script>
Setup arguments to pass JavaFX app Past in index.jsp of FBSaas, adding a line: <script src="http://dl.javafx.com/1.2/dtfx.js"></script> <script> javafx( { archive: "FBapp.jar", draggable: true, width: 500, height: 200, code: "fbapp.main", name: "FBapp", sessionkey: "<%=sessionkey%>" ); </script>
Add JavaFX app to FBSaas Build Fbapp and copy Fbapp.jar from
Add JavaFX app to FBSaas to:
Run On FBSaas project, right click to run: Click on Facebook Login
AuthO/AuthN Facebook
Result Page same sessionid available JavaFX applet
Create a Restful wrapper on: package Sign Service org.netbeans.saas.facebook FacebookSocialNetworkingServiceAuthenticator { static String sign(string[][] params) {... This package has been created with drag&drop Facebook services as mentioned before NOTE: Create a singleton RESTful resource class with GET and PUT methods using Java API for RESTful Web Service (JSR-311). This pattern is useful for creating a simple HelloWorld service and wrapper services for invoking WSDL-based web services.
Restful WS skeleton generated package org.fbsaas.fxhelper;... @Path("signer") public class Signer { @Context private UriInfo context; /** Creates a new instance of Signer */ public Signer() { /** * Retrieves representation of an instance of org.fbsaas.fxhelper.signer * @return an instance of java.lang.string */ @GET @Produces("application/xml") public String getxml() { //TODO return proper representation object throw new UnsupportedOperationException(); Substitute...
Implement RESTful service (1/2) package org.fbsaas.fxhelper; import... import org.netbeans.saas.facebook.facebooksocialnetworkingserviceauthenticator; @Path("signer") public class Signer { @Context private UriInfo context; public Signer() { @GET @Produces("application/xml") public String getsign( /*@DefaultValue("")*/ @QueryParam("api_key") String api_key, @QueryParam("session_key") String session_key, @QueryParam("call_id") String call_id, @QueryParam("v") String v, @QueryParam("format") String format, @QueryParam("flid") String flid, @QueryParam("method") String method, @QueryParam("fields") String fields, @QueryParam("uids") String uids) { //TODO return proper representation object
Implement RESTful service (2/2) //TODO return proper representation object String sig = new String("ERROR"); try { String[][] params = null; params = new String[9][2]; params[0][0] = "api_key"; params[0][1] = api_key; params[1][0] = "session_key"; params[1][1] = session_key; params[2][0] = "call_id"; params[2][1] = call_id; params[3][0] = "v"; params[3][1] = v; params[4][0] = "format"; params[4][1] = format; params[5][0] = "flid"; params[5][1] = flid; params[6][0] = "method"; params[6][1] = method; params[7][0] = "fields"; params[7][1] = fields; params[8][0] = "uids"; params[8][1] = uids; sig = new String(FacebookSocialNetworkingServiceAuthenticator.sign(params)); catch (java.io.ioexception e) { sig = new String("ERROR"); String result = new String("<sigs> <sig>" + sig + "</sig> </sigs>"); return result;
Test RESTful Web Services
Call Sign Service from JavaFX package fbapp; import javafx.data.pull.pullparser; import javafx.data.pull.event; public class SigPullParser { public function parse(input: java.io.inputstream ): String { var sig: String; // Parse the input data (Photo Metadata) and construct Photo instance def parser = PullParser { input: input onevent: function(event: Event) { println("event text: {event.text"); if (event.text.length()>30) { sig= event.text; parser.parse(); println("signature got: {sig"); return sig; PullParser class get in input an java.io.inputstream and generate Event parsing the input. Each Event may be intercepted implementing a callback function onevent
Facebook REST interface API The Facebook API REST server http://api.facebook.com/restserver.php API http://wiki.developers.facebook.com/index.php/api
GetFriend() friends.get mandatory fields: api_key call_id sig ( MD5 hash of the current request and your secret key) v version API Return example: <?xml version="1.0" encoding="utf-8"?> <friends_get_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true"> <uid>2327873</uid> <uid>748378</uid> </friends_get_response>
Call a Facebook REST API (1) call_id = String.valueOf(System.currentTimeMillis()); method = "facebook.friends.get"; var requestsign: HttpRequest = HttpRequest { location: "http://localhost:8080/fbsaas/resources/signer?api_key={apikey&session_key={sessionkey &call_id={call_id&v={v&format={format&flid={flid&method={method" method: HttpRequest.GET oninput: function(input: java.io.inputstream) { var parser = SigPullParser{; signature = (parser.parse(input)).tostring(); try { println("bytes of content available: {input.available()"); finally { input.close(); ondone: function() {... requestsign.start(); HttpRequest class enable an http connection to do REST call to signer services implemented before location determine url to call oninput define callback function it will be asyncronously called passing an java.io.inputstream to be parsed A SigPullParser instance of will parse the signature got calling REST service ondone will define callback function to be called on Http stream closed
Call a Facebook REST API (2)... ondone: function() { var requestfriend: HttpRequest = HttpRequest { location: "http://api.facebook.com/restserver.php?api_key={apikey&session_key= {sessionkey&sig={signature&call_id={call_id&v={v&format={format&method={method" method: HttpRequest.GET oninput: function(input: java.io.inputstream) { var parser = UsersPullParser{; friends = parser.parse(input); for (x in friends) {insert x.uid into friendsid; try { println("bytes of content available: {input.available()"); finally { input.close(); ondone : function(){ In ondone callback function it will be getphoto(friendsid); implemented the real Facebook API requestfriend.start(); call, using the signature got by server side implemented before UsersPullParser is another PullParser implementation in which a UserList it will be parsed
GetPhoto() users.getinfo mandatory fields: api_key call_id sig v uids: (array) List of user IDs. This is a comma-separated list of user IDs. fields: (array) List of desired fields in return. This is a commaseparated list of field strings. It will be specified as field pic_square : URL of a square section of the user profile picture, with width 50px and height 50px.
Final result: Face Mosaic
References Call Facebook rest services by netbeans web apps: http://www.netbeans.org/kb/61/websvc/facebook.html JavaFX applet reads arguments from html page http://forums.sun.com/thread.jspa?threadid=5387552 A JavaFX app as Facebook app: http://kaansoral.com/?p=133 Facebook apps setup: http://www.marketing-ninja.com/facebook-app/starting-your-first-facebook-app-demystifying-application-form-field-by-field/