Sunday, May 13, 2012

Detecting emotions by using JSON and REST services in Oracle ADF

Developers using Oracle ADF to build applications most likely get in touch with ADF Business Components (exposed as Data Controls) first. The framework provides few other types of Data Controls out of the box , like URL Data Control, to facilitate an access to various data sources and services. There are plenty of services available on the Internet which are  based on REST protocol and JSON format  -  consuming them in ADF might be of interest.

The sample application consumes two external JSON+REST services in ADF by using URL Data Control.  It provides a Timeline of some twitter user visualized in ADF UI together with emotion, automatically detected in a message text:


The color and the sign  :)  stands for positive ,  :| for neutral,  :(  for negative emotion detected in a message text.

As one can see, the emotional state discovered in  tweets of twitter user named @ladygaga is quite versatile and shows user feelings changing during a day. Just to compare, the twitter user  @adf_emg seems to keep stable neutral emotional state for a longer period of time:


Let’s take a closer look at technical implementation of the sample. It is available to download and ready run in JDeveloper 11g R2.

Once executed  (Run home.jsf), it should display a page like this:


The response of REST+JSON services is displayed on the page. A panel on a right-side shows an output of TwitterTimlineService. The output of EmotionAnalyzerService for the current row (upon selection in a table) is displayed at a bottom of the page.

Of course, tweets of any public twitter user could be analyzed - just enter  a user name and press “show tweets” in case of interest.

Note: there is no special exception  handling in a sample app, so the results in case of network failure might not be pretty. In case of errors running it locally check your network settings (proxy settings in JDevleoper for example) and the name of twitter user entered - does it exists?

Using JSON+REST services as URL Data Controls

The sample consumes  two simple REST+JSON services as ADF URL Data Controls: Twitter TimelineService and FeelingAnalyzerService.

Readers interested  in Twitter API might find a test Console as good starting point to explore it. 

The FeelingAnalyzerService ,included  in a sample project, was kindly provided by Enrique López-Mañas. I came to his blog post "Flirting with sentimental analysis..."  by looking for some JSON-REST service suitable for ADF JSON-REST sample. Refer to Enrique in case you are interested in  “magic” which helps to turn computers to humans :) 

I proceed  with  description of this small “value added” solution showing how to integrate two REST + JSON services in ADF.

Three Data Controls are used in the sample:


POJO Data Control ShowTweetsPageAdapter,  built by doing a Right-Click -> Create Data Control in JDeveloper on ShowTweetsPageAdapter.java class, contains a method transformTwitterJSONString2Tweets:


The method  takes return value of TwitterTimelineService (tweets in JSON format), transforms the tweets from JSON format to domain model (TwitterTimeline POJO) and makes a call to FeelingsAnalyzerService (URL Data Control) in java for each Tweet to detect emotion in a message text.

The other two data controls, built by using Create URL Data Control wizard in Jdeveloper, provide one method called loadData,  which returns a single column (name Colum0 , type string) as a result:


URL Data Controls were configured to parse an output as CSV yet (JSON parsing support in ADF might come in a future release of ADF).

Let's take a look at the properties of TwitterTimelineService Data Control, which is built on a service statuses/user_timeline.json  creating  TwitterAPIConnection on a way by using Create URL Data Control wizard in JDeveloper.


Setting {tab} as Delimiter and Quotechar to {none} enables to get JSON output as single Column of type String.
The property Source points to a path of a service URL together with a query_string screenName. ##ScreenName## is a placeholder for  query value being supplied at run time.

TwitterApiConnection (created using JDeveloper Wizard together with URL Data Control) points to URL connection  in a Panel Application Resources (persisted in a file connections.xml):



The connection carries URL endpoint of Twitter API:

URL Data Control FeelingAnalyzer and URL connection FelinganalyzerApp  was created  in JDeveloper using the same technique.

Structure of the sample application


The application contains one default unbounded flow adfc-config with one page , called home.jsf as a container for  the bounded flow  tweets-task-flow-definition.xml, embedded as a region.
The flow tweets-taks-flow-definition.xml contains default view activity, named showTweets. A page fragment  showTweets.jsff carries a UI of the application and includes some EL expressions as inline-style to color it a little bit.

Three services (2 provided by URL Data Controls and one from Bean Data Control) are wired in a page definition of showTweets.jsff  declarative way.


Wiring service calls 

Readers familiar with ADF Bindings are already aware,  that a method Binding gets executed implicitly in case the return value of it is displayed on a page or consumed as an input value of some other method binding. Lets look at Bindings section of page fragment showTweets.jsff:





Column0 binds a return value of method loadData from TwitterTimelineService data control. It was created first by Draging a Column0 from Data Controls and dropping it to a page ( area on a right side in a sample application).

The second step was performed to transform a tweets from JSON string to a list of tweet domain objects. We continue with a D&D in order to display the list of Tweets on a page:



Drag&Drop a tweetList  on a page (ADF ReadOnly Table was chosen to display it). Editor Edit Action Binding shows up:



We need to provide a value for input parameter tweetsJsonString. So we can use a value of Column0 , which contains exactly what is needed here: tweets in JSON format as String.

Using Drag&Drop twice, both method calls (loadData of Twitter URL Data Control and transformTwitterJSONString2Twets of Bean Data Control) are wired declarative way to provide a list of Tweets on a page.

Emotions are still missing, so we  call a FeelingsAnalyzerService in order to detect them and enrich our tweets.

First, create a method binding by doing another D&D with  return value of FeelingsAnalyzerService service method loadData:


Drag the Column0  (selected in a picture) and drop it on a same page showTweets.jsff (bottom area in a sample application was chosen as a drop target). Edit Action Binding shows up. We provide a value for parameter of the method (it expects some text  in order to detect emotion in it):


The expression points to a currentRow of tweetListIterator.  The expression-part  dataProvider returns a POJO  behind a row, in our case it is an instance of java bean Tweet.java. The message is an attribute of the been, so this part of  EL resolves to method call tweet.getMessage() on instance of the been.

NOTE: because of ADF Table  “stamping” rows  into variable “row” (which is not available in bindings), this method is NOT executed  for each row when table is rendered. The current row points to the first row in iterator binding, the method gets executed  with a value of a message from a Tweet behind a first row.

The last step was therefore a preparation in order to call this method in java for each row (Tweet) and do it by using  method binding defined in a page definition.

Few lines of java code are used to achieve that. First we get an instance of method binding:

Second part is to provide an input value for a method call, execute it and retrieve the result:

The rest of the source code, included in  ShowTweetsPageAdapter.java, is basically used to deal with JSON parsing by leveraging the reference JSON parser implementation and to transform it to custom domain objects.

To finish the post, the summary provides a list of  ADF and JSF2 specific design features, used in the sample application.

Summary


  • “Twitter Timeline” designed as reusable component and implemented using ADF Faces bounded task flow with parameters.
  •  Functionality provided by ADF leveraged to consume two JSON+REST services a declarative way using ADF URL Data Control (CSV)  and Connections.xml
  • The functionality of JSON parsing, which is not (yet) available  as ADF Data Control , compensated  in  java (ShowTweetsPageController.java) by leveraging third party JSON parser.
  • The result of Twitter Timeline service enriched with emotions by calling a method binding of URL Data Control (which is based on external REST+JSON service) in java.
  • JSON output transformed to domain model and exposed to UI as a POJO Data Control.
  • A value stored in JSF2 @ViewScope used to provide an input to a task flow embedded as region.


The source code of it is available on github.

No comments:

Post a Comment