Pages

Sunday, February 15, 2009

FaceBook ADF Task Flow

This is an example of a Facebook Task Flow which you can use in every ADF 11G application. Just an little example how powerfull and reusable Task Flow are. I used for this example the facebook-java-api, which is an opensource project. Great work guys.

Here some screenshots of the facebook TF. First we have to authenticate on the facebook site. This is only necessary the first time after this it will use a cookie to authenticate. I use the af:inlineFrame component to open the special facebook url with my application id.Now we can open the second accordion page. This will update my panelbox with my photo and show my friends in an ADF table.

We can email some friends by selecting these in the adf table and go to the email accordion and send the email.


Here is the facebook backing bean where it all happens

package nl.whitehorses.tf.facebook.beans;

import com.google.code.facebookapi.FacebookException;
import com.google.code.facebookapi.FacebookJaxbRestClient;
import com.google.code.facebookapi.ProfileField;
import com.google.code.facebookapi.schema.FriendsGetResponse;

import com.google.code.facebookapi.schema.User;
import com.google.code.facebookapi.schema.UsersGetInfoResponse;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

import javax.faces.event.ActionEvent;

import oracle.adf.view.rich.component.rich.data.RichTable;
import oracle.adf.view.rich.component.rich.input.RichInputText;
import oracle.adf.view.rich.component.rich.layout.RichPanelBox;
import oracle.adf.view.rich.component.rich.layout.RichShowDetailItem;
import oracle.adf.view.rich.context.AdfFacesContext;

import org.apache.myfaces.trinidad.event.DisclosureEvent;
import org.apache.myfaces.trinidad.model.RowKeySet;


public class FaceBookBean {

private String APIKEY;
private String SECRET;

private List<User> modelFriends = null;
private int friendSize;

private String sessionID;
private String token;
private FacebookJaxbRestClient client;
private String facebookUser;
private String facebookUserImage;
private RichTable resultTable;
private RichPanelBox panelBox;
private String facebookLoginUrl;
private RichShowDetailItem loginTab;
private RichShowDetailItem resultTab;
private Long loggedUser;
private RichInputText emailSubject;
private RichInputText emailBody;

public FaceBookBean() {

}

private void refresh() {
try {
if ( sessionID==null){
sessionID = client.auth_getSession(token);
facebookLoginUrl = "http://www.facebook.com";
}
if (sessionID != null) {

loggedUser = client.users_getLoggedInUser();
List<Long> loggedUsers = new ArrayList<Long>(1);
loggedUsers.add(loggedUser);
client.users_getInfo(loggedUsers,
EnumSet.of( ProfileField.NAME
, ProfileField.PIC_SMALL));

UsersGetInfoResponse userResponse = (UsersGetInfoResponse)client.getResponsePOJO();
for (User user : userResponse.getUser()) {
facebookUser = user.getName();
facebookUserImage = user.getPicSmall();
}

FriendsGetResponse response =
(FriendsGetResponse)client.friends_get(loggedUser);
List<Long> friends = response.getUid();
client.users_getInfo(friends,
EnumSet.of( ProfileField.STATUS
, ProfileField.NAME
, ProfileField.BIRTHDAY
, ProfileField.PIC_SMALL));

userResponse =
(UsersGetInfoResponse)client.getResponsePOJO();

modelFriends = userResponse.getUser();
friendSize = modelFriends.size();

resultTable.setRows(friendSize);

// disable the login tab, if we are here we have a session object
loginTab.setDisabled(true);
loginTab.setVisible(false);

// refresh panelbox and the result table
AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
adfFacesContext.addPartialTarget(resultTable);
adfFacesContext.addPartialTarget(panelBox);
}
} catch (FacebookException ex) {
ex.printStackTrace();
}


}

public void sendEmail(ActionEvent actionEvent) {
try {
RowKeySet selection = resultTable.getSelectedRowKeys();
Object[] keys = selection.toArray();
List<Long> receivers = new ArrayList<Long>(keys.length);
for ( Object key : keys ) {
User user = this.modelFriends.get((Integer)key);
receivers.add(user.getUid());
}
Object succes = client.notifications_sendTextEmail( receivers
,(String)emailSubject.getValue()
,(String)emailBody.getValue());
System.out.println(succes.toString());
} catch (FacebookException e) {
e.printStackTrace();
}
}

public void afterFaceBookLogin(ActionEvent actionEvent) {
refresh();
}


public void resultTableDisclosure(DisclosureEvent disclosureEvent) {
refresh();
}

public String getFacebookUser() {
return facebookUser;
}

public String getFacebookUserImage() {
return facebookUserImage;
}

public void setModelFriends(List<User> modelFriends) {
this.modelFriends = modelFriends;
}

public List<User> getModelFriends() {
return modelFriends;
}


public void setResultTable(RichTable resultTable) {
this.resultTable = resultTable;
}

public RichTable getResultTable() {
return resultTable;
}

public void setPanelBox(RichPanelBox panelBox) {
this.panelBox = panelBox;
}

public RichPanelBox getPanelBox() {
return panelBox;
}

public String getFacebookLoginUrl() {
if (sessionID==null){
try {
client = new FacebookJaxbRestClient(APIKEY, SECRET);
token = client.auth_createToken();
facebookLoginUrl= "http://api.new.facebook.com/login.php?api_key=" + APIKEY + "&v=1.0&auth_token=" + token;
} catch (FacebookException ex) {
ex.printStackTrace();
}
}
return facebookLoginUrl;
}

public void setLoginTab(RichShowDetailItem loginTab) {
this.loginTab = loginTab;
}

public RichShowDetailItem getLoginTab() {
return loginTab;
}

public void setResultTab(RichShowDetailItem resultTab) {
this.resultTab = resultTab;
}

public RichShowDetailItem getResultTab() {
return resultTab;
}


public void setAPIKEY(String APIKEY) {
this.APIKEY = APIKEY;
}

public String getAPIKEY() {
return APIKEY;
}

public void setSECRET(String SECRET) {
this.SECRET = SECRET;
}

public String getSECRET() {
return SECRET;
}

public void setEmailSubject(RichInputText emailSubject) {
this.emailSubject = emailSubject;
}

public RichInputText getEmailSubject() {
return emailSubject;
}

public void setEmailBody(RichInputText emailBody) {
this.emailBody = emailBody;
}

public RichInputText getEmailBody() {
return emailBody;
}
}

Here is the code of my Facebook page fragment

<?xml version='1.0' encoding='windows-1252'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
xmlns:f="http://java.sun.com/jsf/core">
<af:panelBox text="Facebook Task Flow of #{FaceBook.facebookUser}"
icon="#{FaceBook.facebookUserImage}" id="box"
inlineStyle="height:500px; width:700px;"
binding="#{FaceBook.panelBox}">
<af:panelAccordion inlineStyle="height:480px; width:680px;">
<af:showDetailItem text="Facebook Login" binding="#{FaceBook.loginTab}">
<af:inlineFrame source="#{FaceBook.facebookLoginUrl}"
inlineStyle="width:99%; height:99%;"
shortDesc="Loginpage"/>
<f:facet name="toolbar"/>
</af:showDetailItem>
<af:showDetailItem text="Facebook Results" binding="#{FaceBook.resultTab}"
disclosureListener="#{FaceBook.resultTableDisclosure}">
<af:panelCollection id="col" inlineStyle="width:99%; height:98%;">
<f:facet name="toolbar">
<af:toolbar>
<af:commandToolbarButton text="Refresh"
actionListener="#{FaceBook.afterFaceBookLogin}"/>
</af:toolbar>
</f:facet>
<af:table value="#{FaceBook.modelFriends}" id="result" var="row"
rowSelection="multiple" emptyText="#{'No rows yet.'}"
binding="#{FaceBook.resultTable}" columnStretching="blank"
inlineStyle="height:97%; width:100%;">
<af:column sortable="false" headerText="Name" width="200">
<af:outputText value="#{row.name} "/>
</af:column>
<af:column sortable="false" headerText="Birthdate" width="100">
<af:outputText value="#{row.birthday}"/>
</af:column>
<af:column sortable="false" headerText="Image" width="60">
<af:image source="#{row.picSmall}"/>
</af:column>
<af:column sortable="false" headerText="Status" width="120"
noWrap="false">
<af:outputText value="#{row.status.message}"/>
</af:column>
<af:column sortable="false" headerText="Id" width="60">
<af:outputText value="#{row.uid}"/>
</af:column>
</af:table>
</af:panelCollection>
</af:showDetailItem>
<af:showDetailItem text="Email">
<af:panelFormLayout>
<af:inputText label="Subject" columns="52"
binding="#{FaceBook.emailSubject}"/>
<af:inputText label="Body" rows="3" columns="50" wrap="soft"
binding="#{FaceBook.emailBody}"/>
</af:panelFormLayout>
<f:facet name="toolbar">
<af:commandButton text="Send Email"
actionListener="#{FaceBook.sendEmail}"/>
</f:facet>
</af:showDetailItem>
</af:panelAccordion>
</af:panelBox>
</jsp:root>


When you drop this task flow on an page you have to fill the api and secret input parameters. I can't give you mine keys. You can do this in the pagedef of the page.

<?xml version="1.0" encoding="UTF-8" ?>
<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"
version="11.1.1.51.88" id="startPageDef" Package="pages">
<parameters/>
<executables>
<taskFlow id="facebooktaskflowdefinition1"
taskFlowId="/WEB-INF/facebook-task-flow-definition.xml#facebook-task-flow-definition"
xmlns="http://xmlns.oracle.com/adf/controller/binding">
<parameters>
<parameter id="API" xmlns="http://xmlns.oracle.com/adfm/uimodel"
value="'0eff-----------------1'"/>
<parameter id="SECRET" xmlns="http://xmlns.oracle.com/adfm/uimodel"
value="'e1cee430d8599bc3be2e42fc19fe9d68'"/>
</parameters>
</taskFlow>
</executables>
<bindings/>
</pageDefinition>

To use this Task Flow in your ADF application, we need to go to http://developers.facebook.com/get_started.php where you can register your own application. Now you will have your own applicationId and secret which you can use for the pagedef task flow parameters. And please fill in callback url to a website.



Here is the 11g workspace.

3 comments:

  1. Facebook doesn't allow login page to open in iframe.
    So this applcation is not able to run.
    SO wat else should i do now.

    I am unable to understand how facebook authorises without entering any token or anything

    ReplyDelete
    Replies
    1. Hi,

      indeed they changed it, you can use http://restfb.com/ and build a Facebook Application and use it to obtain OAuth tokens for your users.
      here you are some examples
      https://developers.facebook.com/docs/concepts/login/login-architecture/ (Client-side JavaScript SDK) or an overview https://developers.facebook.com/docs/concepts/login/

      Thanks

      Delete