Flex

July 19th, 2012

DataPush using Custom Java Adapter to Flex Apps

More articles by »
Written by: Nouman Naveed
Tags:
Login Chart with BlazeDS Datapush capabilities

Recently, I have been investigating on how to push data from BlazeDS using custom java adapter and found few interesting details to share with you all. If you are already working with BlazeDS / LCDS then you might be aware of configuration files available to you for exposing capabilities of Java through BlazeDS. It is important to understand that BlazeDS comes with many good features which is required by small to mid size organizations. Today BlazeDS is adapted by many organizations to expose Java capabilities to Flex applications. To understand this article you need to have knowledge about BlazeDS capabilities and necessary configurations needed to work with Flex. If you are new to BlazeDS please use this link http://www.adobe.com/devnet/flex/flex_java.html

My focus here is on creating custom Java adapters and use them with BlazeDS for data-push applications. Please don’t take me wrong if I say data-push which is not RTMP. We will be sending messages to Flex clients on regular intervals which is similar to polling capabilities already available in both BlazeDS / LCDS. If you are aware with messaging-config.xml & services-config.xml this article will be very easy for you. You also need good understanding on Java side for building your own adapter. I will be discussing here a sample application built with Flex & BlazeDS and how to use them with custom Java adapter for data push applications. This data-push applications could be any data which you want to update every few seconds and show it in Flex application. Examples of these types of applications could be stock quotes, dash boards, network monitoring applications etc.

With my previous experiences it is known that BlazeDS cannot be used for hug enterprise level applications because it restricts the amount of concurrent users connected to itself. This maximum concurrent connected number is not clearly mentioned in any place. But people who used it extensively claimed it be around 500 concurrent users. I recommend you to investigate properly before you decide your application built with BlazeDS. So coming back to our topic I will be building a sample application which sends number of failed & successful logins attempts by user. Java class will be generating random number of records and will send it to Flex clients.

Meanwhile, lets begin by adding entry inside services-config.xml which will look as follows:

<channel-definition id=”my-streaming-amf”>
<endpoint url=”https://{server.name}:{server.port}/{context.root}/messagebroker/amfsecure/streamingamf” />
<properties>
<idle-timeout-minutes>0</idle-timeout-minutes>
<max-streaming-clients>10</max-streaming-clients>
<server-to-client-heartbeat-millis>5000</server-to-client-heartbeat-millis>
<user-agent-settings>
<user-agent match-on=”MSIE” kickstart-bytes=”2048″ max-streaming-connections-per-session=”3″ />
<user-agent match-on=”Firefox” kickstart-bytes=”2048″ max-streaming-connections-per-session=”3″ />
</user-agent-settings>
</properties>
</channel-definition>

Above channel defines how data is directed to Flex clients and how often the data will be sent. Here we are going to refresh our application every 5 seconds  <server-to-client-heartbeat-millis>5000</server-to-client-heartbeat-millis>. And there are few other sittings related to number of maximum clients and browsers settings.

Before we move forward you will need to create Java project which uses flex-messaging-common.jar & flex-messaging-core.jar as external libraries. Please go and add them to your Java Build Path.

add external jar (using custom adapters with BlazeDS)

Adding External Jars to Java project

Once you are done with this we need to create our Java class to publish messages which will go through BlazeDS. Furthermore, we need to update messaging-config.xml once we are done with creating Java classes. Here we will be sending messages created randomly for successful and failed login attempts by some users. This mock adapter class will be using VO called LoginAttempt. Here is the logic of our VO LoginAttempt:

package com.flexatom;

public class LoginAttempt {
private Integer success;
private Integer failed;
private String user;

public LoginAttempt(Integer success, Integer failed, String user){
this.success = success;
this.failed = failed;
this.user = user;
}

public LoginAttempt(){}

public Integer getSuccess() {
return success;
}
public void setSuccess(Integer success) {
this.success = success;
}
public Integer getFailed() {
return failed;
}
public void setFailed(Integer failed) {
this.failed = failed;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}

Once the Java VO is created lets see what goes inside Java Adapter class:

package com.flexatom;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import flex.messaging.MessageBroker;
import flex.messaging.messages.AsyncMessage;
import flex.messaging.messages.Message;
import flex.messaging.services.MessageService;
import flex.messaging.services.ServiceAdapter;
import flex.messaging.util.UUIDUtils;

public class GetLoginAttemptsAdapter extends ServiceAdapter {
Random random;
LoginGenerator thread;
//public Integer Counts;

public GetLoginAttemptsAdapter(){
random = new Random();
System.out.println(“Adapter initilized”);
}

public void start(){
if(thread == null){
System.out.println(“Adapter started”);
thread = new LoginGenerator();
thread.start();
}
}

public void stop(){
System.out.println(“Adapter stopped”);
thread.running = false;
thread=null;
}

//    public void messageCount(Integer count){
//        System.out.println(“Adapter Count Called”);
//        Counts=count;
//    }

private List<LoginAttempt> generateLogins(){

List<LoginAttempt> arr = new ArrayList<LoginAttempt>();
Integer Counts = random.nextInt(100);
for (int x=0;x<Counts;x++){
LoginAttempt p = new LoginAttempt();
p.setSuccess(random.nextInt(100));
p.setFailed(random.nextInt(100));
p.setUser(“User”+x);
arr.add(p);
}
return arr;
}

public class LoginGenerator extends Thread {
public boolean running = true;
public void run(){
String clientId = UUIDUtils.createUUID();
MessageBroker msgBroker = MessageBroker.getMessageBroker(null);
while (running){
AsyncMessage msg = new AsyncMessage();
msg.setDestination(“LoginPush”);
msg.setClientId(clientId);
List <LoginAttempt>a= generateLogins();
msg.setMessageId(UUIDUtils.createUUID());
msg.setBody(a);
msgBroker.routeMessageToService(msg,null);

try{
Thread.sleep(5000);
}catch(InterruptedException e){
System.out.println(“Exception”);
e.printStackTrace();
}
}

}
}
@Override
public Object invoke(Message msg) {
if(msg.getBody().equals(“New”)){
System.out.println(“Login Adapter received client”);
return generateLogins();
}else{
System.out.println(“Login Adapter sending message”);
AsyncMessage newMessage = (AsyncMessage)msg;
MessageService msgService = (MessageService)getDestination().getService();
msgService.pushMessageToClients(newMessage, true);
}
return null;
}
}

ServiceAdapter is a base class which is used for publishing messages from BlazeDS and it includes a method called invoke() which should be overridden for packaging and sending our messages. The method generateLogins() is our custom method which will be generating mock data for us.  We also got run() method which is responsible for packaging the data with MessageID and body parts of our message.

After the creation of these classes you need to compile it and move the contents of your Java project bin folder to C:\blazeds\tomcat\webapps\blazeds\WEB-INF\classes directory. Next is to create an entry in messaging-config.xml for pointing to our custom adapter which is producing messages for us. The entries inside messaging-config.xml might look like this:

<?xml version=”1.0″ encoding=”UTF-8″?>
<service id=”message-service” >

<adapters>
<adapter-definition id=”actionscript”  class=”flex.messaging.services.messaging.adapters.ActionScriptAdapter” default=”true” />
<adapter-definition id=”LoginPushAdapter” class=”com.flexatom.GetLoginAttemptsAdapter”/>
</adapters>

<default-channels>
<channel ref=”my-polling-amf”/>
</default-channels>

<destination id=”LoginPush”>
<channels>
<channel ref=”my-streaming-amf” />
</channels>
<adapter ref=”LoginPushAdapter”/>
</destination>

</service>

In the above file we have created a destination called LoginPush which will be using newly created adapter and channel. The destination points for my-streaming-amf channel (created inside services-config.xml earlier) and LoginPushAdapter (created inside messaging-config.xml earlier).

Now its time to see client side logic for consuming the messages sent from this custom Java adapter. You will be creating a Flex project which uses BlazeDS. The configuration of my flex project is as follows:

blazeds-java-adapter-project (creating custom java adapter for blazeds)

Creating custom Java adapter for BlazeDS

When the project is created it will point to servers directory which allows application to run from tomcat. When its served from server the application will have access to resources of the server from which it is served. In our case its is served from http://localhost:8400/blazeds/BlazeMessaging-debug/. Following is the code goes inside your flex application file fro consume data from BlazeDS destination:

<?xml version=”1.0″ encoding=”utf-8″?>
<s:Application xmlns:fx=”http://ns.adobe.com/mxml/2009″
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”
minWidth=”955″ minHeight=”600″ creationComplete=”init()”>
<fx:Declarations>
<mx:Producer id=”producer” destination=”LoginPush”/>
<mx:Consumer id=”consumer” destination=”LoginPush” message=”onMsg(event)”/>
<!–<s:RemoteObject id=”changeCount” destination=”LoginAdapterRemote”/>–>
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.flexatom.dto.LoginAttempt;

import mx.charts.events.ChartItemEvent;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.messaging.events.MessageAckEvent;
import mx.messaging.events.MessageEvent;
import mx.messaging.messages.AsyncMessage;
import mx.messaging.messages.IMessage;

[Bindable]
public var myLoginData:ArrayCollection;

private function init():void{
var message:AsyncMessage = new AsyncMessage();
message.body = “New”;
producer.send(message);
consumer.subscribe();
}

private function onMsg(event:MessageEvent):void{
myLoginData= event.message.body as ArrayCollection;
}

private function pub():void            {
var message:AsyncMessage = new AsyncMessage();
message.body = “New”;
producer.send(message);
}

]]>
</fx:Script>

<s:Panel width=”80%” horizontalCenter=”0″ title=”Employee Login Details”>
<mx:ViewStack id=”LoginStack” creationPolicy=”all”>
<s:NavigatorContent label=”Login Chart”>
<mx:ColumnChart id=”mychart” y=”14″ width=”946″ dataProvider=”{myLoginData}” horizontalCenter=”0″
showDataTips=”true”>
<mx:series>
<mx:ColumnSeries yField=”success” displayName=”Success Login”/>
<mx:ColumnSeries yField=”failed” displayName=”Failed Login”/>
</mx:series>
<mx:horizontalAxis>
<mx:CategoryAxis categoryField=”user”/>
</mx:horizontalAxis>
</mx:ColumnChart>
</s:NavigatorContent>
<s:NavigatorContent id=”ldata” label=”Login Data”>
<s:DataGrid id=”myloginGrid” x=”10″ y=”10″ width=”381″ dataProvider=”{myLoginData}”>
<s:columns>
<s:ArrayList>
<s:GridColumn dataField=”success” headerText=”Success Logins”/>
<s:GridColumn dataField=”failed” headerText=”Failed Logins”/>
<s:GridColumn dataField=”user” headerText=”User LoggedIn”/>
</s:ArrayList>
</s:columns>
</s:DataGrid>
</s:NavigatorContent>
</mx:ViewStack>
<s:controlBarContent>
<mx:LinkBar dataProvider=”{LoginStack}”/>
</s:controlBarContent>
</s:Panel>

</s:Application>

If you are not familiar with Producer and Consumer classes of actionsript I recommend you to look on Adobe Help for samples. Here the consumer and producer are non-ui logic, so starting from Flex 4 we need to declare it inside <fx:Declarations>  tag block when using MXML approach. These Consumer and Producer components will be pointing for destination configured inside messaging-config.xml file which is LoginPush. This sample application is going to update the column chart whenever data received from BlazeDS. The chart will update every 5 seconds which is receiving data pushed from custom Java Adapter through destination.

Login Chart with BlazeDS Datapush capabilities

Login Chart with BlazeDS Datapush Capabilities

When you want to send / receive data you can optionally use client side VO for mapping to server side VO created earliest in this article. Following is the logic for client side value object pointing to Java VO:

package com.flexatom.dto
{
[Bindable]
[RemoteClass(alias=”com.flexatom.LoginAttempt”)]
public class LoginAttempt
{
private var _success:int;
private var _failed:int;
private var _user:String;

public function LoginAttempt(){
}

public function get Success():int{
return _success;
}
public function get Failed():int{
return _failed;
}
public function get user():String{
return _user;
}

public function set Success(success:int):void{
_success = success;
}
public function set Failed(failed:int):void{
_failed = failed;
}
public function set age(user:String):void{
_user = user;
}
}
}

To receive data on client side we used Consumer component which dispatches the message event. The handler function of message event allows us to extract the data from event object and assign it to ArrayCollection variable. This ArrayCollection variable can be used to populate visual controls, in our case its a ColumnChart which is using dataProvider property.


About the Author

Nouman Naveed
My name is Mohammed Nouman Naveed. I work and play with Flash Platform technologies and has experience of 11 years. Consulting and Training is part of my job. I am Adobe Certified Instructor, Adobe User Group Manager, Adobe Certified Expert and Adobe Community Champion.




 
 

 
CQ5
adobe aem56 dam logo

Setting Images in DAM

All images are loaded into the DAM (Digital Assets Management). To upload an image, you’ll need to use your Activator login. From the tree, click +Digital Assets Find the way to the tree to suitable folder (AAFP, images, ANN,...
by Nouman Naveed
0

 
 
 

Apache Flex 4.10.0 Available

Here comes Apache Flex 4.10. This project, the all-volunteer group of developers, and stakeholders in the development framework, today announced the release of Apache Flex 4.10.0. This release makes some important improvements ...
by Nouman Naveed
0

 
 
CQ5
aem 5.6.1 features pic

Many New Features in AEM 5.6.1

AEM 5.6.1 is a easy to use, unified experience management collection for marketers in the digital sphere to use in creating, managing, and delivering unique online experiences that are brand-entered and increase demand across d...
by Nouman Naveed
0

 

 
CQ5
Adobe CQ5 WEM, SOCO, Tagging, DAM

What’s New in CQ 5.6

1: It’s called AEM (Adobe Experience Manager) now Though I guess not that essential, it’s going to be exciting if the name is going to attach – there were other occasions where Adobe tried to rename this result and at the...
by Nouman Naveed
0

 
 
CQ5
content management for web and mobile

Content Management for Web & Mobile

Adobe CQ is a WCM and gives a better browser-based user interface. It is best suitable for business and IT for creating interactive, multimedia rich, multichannel consumer understanding to make an engaging digital existence, ma...
by Nouman Naveed
0

 




0 Comments


Be the first to comment!


Leave a Reply

Your email address will not be published. Required fields are marked *