Bringing data into Flex applications – introduction
Posted by cornel | Filed under Flex, Java, LCDS/Blaze DS
This article will describe the most common ways to bring data into a Flex application and will present the advantages and disadvantages of each approach. It assumes that the reader has a basic understanding of the Flex language.
Unlike a classic web application (by classic I mean pre AJAX) where the pages are generated on the server the Flex application is loaded at startup and makes calls in order to load or to save data. Of course a Flex application can also make requests in order to load other Flex modules in the same way a Java application can dynamically load JAR libraries but that is a subject for a different article.
Some of the presented solutions are server agnostic – you can use anything on the backend – others assume that you have installed a Java application server where you can deploy various solutions including BlazeDS, Livecycle Data Services, GraniteDS, Cinnamon, WebORB etc.
a)Opening a socket connection between the Flex application and the backend.
A socket connection It is the most low-level solution and at the same time the one most flexible. You will have to define your own protocol and how to serialize data (or use the AMF/Hessian protocols). In most cases, you should use this solution only if you have a very specific business need and the existing solutions do not meet your requirements).
You can use Apache MINA if you intend to do that. For example Red5 Flash server was written using the MINA framework.
Bellow is a simple code snippet that shows how to create a socket and how to read or write data:
public function initConnection():void{
CursorManager.setBusyCursor();
Security.loadPolicyFile("xmlsocket://localhost:24");
socket = new Socket();
socket.addEventListener( Event.CONNECT, onConnect );
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketRead);
socket.addEventListener(ErrorEvent.ERROR, errorHandler);
socket.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorHandler);
socket.connect("localhost", 23);
}
public function socketWrite(event:Event){
socket.writeUTF(inputName.text);
socket.flush();
}
public function socketRead(eventrogressEvent){
while ( socket.bytesAvailable ) {
var data:String = socket.readUTF();
Alert.show(data);
}
}
You probably noticed the line Security.loadPolicyFile(“xmlsocket://localhost:24″); By default a Flex application can open connections only to the same domain from where it was loaded and on the same port. In order to be able to initiate connections to another domain a file named crossdomain.xml must exists on that server. This file specifies the what resources are available and for what domains. In our case the policy file will allow that the all the SWF loaded from any domain are allowed to connect to the port 23
<cross-domain-policy>
<allow-access-from domain="*" to-ports="23" />
</cross-domain-policy>
For more details regarding the policy files and Flash security, see this documentation.
b)Using REST and SOAP services (via HTTPService and WebServices components)
REST and SOAP services works with any type of server-side technology – also these technologies are standard and most of the biggest service providers(Yahoo, Amazon, Google, Flickr, eBay) expose their API through both of them . There is an endless debate on when to use REST and when to use SOAP but that is beyond the scope of this article. Instead I will present some samples on how to use them.
As with the sockets example, because the Flex application can initiate requests only to the same domain from where it was loaded you’ll need a crossdomain.xml file on the server where the services are located. Obvious you cannot put a policy files on every server so use the following approach: connect to the back-end server from where the Flex application was loaded and use that server to make the request – after that send the result back to the Flex application. For that you can use an existing product – BlazeDS or another solution.
Below is a sample code showing the two mxml tags used to call REST and SOAP services:
<mx:HTTPService id="resultHttpService"
url="http://www.sampledomain.com/query.jsp?quote=ADBE" />
<mx:WebService id="resultWebService"
wsdl="http://www.sampledomain.com/quotes?wsdl" />
In this case I am connecting directly to sampledomain so the first time the Flash Player will check for crossdomain.xml to see if the server allows the request.
In order to use the proxy approach (use the server to do the request) I will modify the code:
<mx:HTTPService id="resultHttpService" destination="HTTPDestination" useProxy="true" />
<mx:WebService id="resultWebServive" destination="WebServiceDestination" useProxy="true" />
and in proxy-config.xml I will add the destination definition:
<destination id="resultHttpService">
<properties>
<url>http://www.domain.com/query.jsp?quote=ADBE</url>
</properties>
</destination>
<destination id="ws-catalog">
<properties>
<wsdl>http://www.domain.com/quotes.wsdl</wsdl>
<soap>*</soap>
</properties>
<adapter ref="soap-proxy"/>
</destination>
In the REST example it is very important to notice that due to Flash Player limitations you are allowed to use only GET and POST methods, and any return code other than 200 will generate a fault. To overcome these limitations you can write your own proxy server, or better still, use one already written (BlazeDS for example).
c)Using remoting
Remoting technology allows developers to directly invoke methods on the backend server. Initially this was possible only with Java and Coldfusion but after that the format used to package data (AMF3) was made open source and different implementations have appeared for PHP, Python, Ruby and .Net.
Compared with Web Services one of the biggest advantage of using remoting is the bandwidth savings – data is compressed using a binary format which is much more compact then the plain text format. The most used format is created by Adobe and is called AMF3 but there is also another alternative called Hessian. Both formats are open source. The most important difference between them is that AMF3 serialization/deserialization is included in the Flash Player, while when using Hessian you will have to add some libraries to our Flex project.
Below I will present some examples for Java language, using BlazeDS and AMF.
The mxml tag from the Flex application looks the same as the ones used for calling webservices – the main attributes are the id and the destination
<mx:RemoteObject id="productService" destination="ProductService"/>
The destination is configured into the file remoting-config.xml:
<destination id="productService">
<properties>
<source>
com.test.services.ProductService
</source>
</properties>
<adapter ref="java-object" />
</destination>
The remote object allows you to call methods on the Java object associated with the corresponding destination. Everything else is transparent from the user’s point of view (including the conversion between ActionScript and the Java objects and the serialization mechanism that can handle complex objects graph). You will only need to declare the mapping between the ActionScript and the Java objects using the [RemoteClass] metadata:
package com.test.model{
[RemoteClass(alias="com.test.model.Product")]
public class Product{
public var id:int;
public var name:String;
}
}
Before you start to use remoting it’s a good idea to read this link describing data types conversion between Java and ActionScript.
It is important to notice that on every I/O operation also the remote method is invoked asynchronously so you will need to register handlers for the result and fault events.
d)Using messaging
There are currently several messaging solution on the market for the Flex applications: BlazeDS (and the commercial version Livecycle Data Services) , Granite Data Services and WebORB. All of them also have integration with JMS servers.
With messaging, a Flex application can connect to a message destination on the server (specified in messaging-config.xml) and can exchange messages with the server or with another clients (using the server as a proxy). You can use messaging to have the server push messages to the clients (for example, in an application that displays the latest stock prices) and you can use it for collaboration between clients (for example a chat application).
One of the most important things when working with messaging is choosing the proper communication channel in order to obtain real time messaging. BlazeDS server supports HTTP streaming and polling (short and long) over AMF and HTTP channels. HTTP streaming is the best way to obtain data in real time but because of the limitations from the servlet model it keeps one thread open per connection. The commercial version (Livecycle Data Services ES) overcomes this limitation with the help of NIO channels (RTMP and NIO HTTP).
Below is a code sample that shows the main tags used for messaging:
<mx:Producer id="producer" destination="chat"/>
<mx:Consumer id="consumer" destination="chat"/>
The destination chat is defined below:
<default-channels>
<channel ref="my-rtmp"/>
<channel ref="my-streaming-amf"/>
</default-channels>
<destination id="chat">
<properties>
<network>
<!--The session timeout for inactive HTTP sessions–>
<session-timeout>0</session-timeout>
</network>
</properties>
</destination>
Detailed information regarding messaging can be found in the Messaging Service chapter of the BlazeDS developer guide.
e)Using Data Management Service
Data Management Service is a feature provided (as of the writing of this article) both in Livecycle Data Services ES and WebORB. Both products offers a framework called Data Management however the architectures differ – in this article I will discuss only the Data Management framework provided by Livecycle Data Services. It operates at a much higher level than the messaging and RPC services. While it can be used for different types of applications it provides the most value for data intensive applications (especially where collaboration is very important). It is designed to solve several important challenges:
- synchronizing data on clients with the server without having to write CRUD methods
- automatic or manual data synchronization between clients
- conflict handling, paging data sets, working with offline applications and synchronizing the data when the application is online again
One can make a comparison between Data Management and Hibernate – both frameworks allow the developers to concentrate on defining the domain model and working with it without spending too much time on problems like how to persist, load, version and synchronize data. Hibernate deals with data persistence into database, Data Management with data persistence and synchronization between client applications and the server. There is also integration between these two frameworks and I’ve attached a fully working example showing that.
As with messaging,it is very important how to choose the correct communication channels (especially for automatic synchronization feature). The same choices described in the messaging example apply here.
Here is a simple example that shows how easy it is to create an application for editing a table:
The Flex code:
<?xml version="1.0" encoding="utf-8">
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init();" >
<mx:Script>
<![CDATA[
import test.*;
import mx.collections.ArrayCollection;
import mx.data.events.*;
import mx.events.*;
import mx.data.*;
var companyDataService = new DataService("test.Company");
[Bindable]
var companyArray:ArrayCollection = new ArrayCollection();
function addCompany():void{
var company:Company = new Company();
company.name="<new company>";
companyArray.addItem(company);
}
function deleteCompany():void{
var company:Company = companyGrid.selectedItem as Company;
if (company==null)
return;
companyDataService.deleteItem(companyGrid.selectedItem);
}
function save():void{
companyDataService.commit();
}
function revert():void{
companyDataService.revertChanges();
}
function init():void{
companyDataService.fill(companyArray,"mainFill",[]);
companyDataService.autoCommit=false;
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%" horizontalAlign="center" >
<mx:DataGrid id="companyGrid" width="40%" height="40%" dataProvider="{companyArray}" editable="true" textAlign="center">
<mx:columns>
<mx:DataGridColumn dataField="id" headerText="Id" editable="false"/>
<mx:DataGridColumn dataField="name" headerText="Company"/>
</mx:columns>
</mx:DataGrid>
<mx:HBox horizontalAlign="center" width="100%">
<mx:Button label="+" click="addCompany();"/>
<mx:Button label="-" click="deleteCompany();"/>
</mx:HBox>
<mx:HBox width="100%" horizontalAlign="center">
<mx:Button label="Save changes" click="save();"/>
<mx:Button label="Revert modifications" click="revert();"/>
</mx:HBox>
</mx:VBox>
</mx:Application>
The definition of the DataService object is located in the configuration file data-management-config.xml
<destination id="test.Company" channels="my-rtmp">
<properties>
<source>flex.data.assemblers.HibernateAnnotationsAssembler</source>
<scope>application</scope>
<item-class>test.Company</item-class>
<metadata>
<identity property="id" />
</metadata>
<server>
<hibernate-entity>test.Company</hibernate-entity>
</server>
</properties>
</destination>
As you can see there are no remoting calls – after the collection companyArray is filled with data you can manipulate the data by adding new elements, deleting or updating elements. You have the option to call save when you want to persist the modifications or revert if you decides to discard them.
It is possible to work with more complex domain models (associations between objects) and you can find one example of this attached.
Data Management is the most appealing approach for bringing data into a Flex application, but like Hibernate case it has a steep learning curve. Documentation related to it can be found in LCDS developer guide.
The following table summarizes the advantages and disadvantages for each solution:
| Pros | Cons | |
| Socket communication | The most flexible approach. Allows you to write your own server using whatever technology do you want obtaining the best performance. | It takes a lot of time and money to define your protocol and write your server. It can be useful if you intend to communicate with an already written server or for cases in which you need extremely high performance |
| REST/SOAP services | Well established standards, you can wrote them once and consume them from most of the systems, not just Flex applications. Also most of the companies expose their api through REST and SOAP services | The overhead of parsing data (especially for SOAP) can be substantial |
| Remoting | Little overhead compared with web services. The bandwith used is also much smaller. Automatic conversion between Action Script and the Java objects (or another language). Increased productivity (number of code lines is reduced, also the development time) | Sometimes the data exposed through services needs to be consumed by a variety of applications – this is possible using web services but not with remoting |
| Messaging | Ability to implement collaboration features. Integration with JMS | There are relatively few solutions that implements messaging. As the writing of this article only BlazeDS/LCDS from Adobe and GraniteDS (if your backend is Java) and WebORB (if your backend is Java, PHP, .NET) |
| Data Management (LCDS) | The time needed to implement a data driven application is reduced. It offers solutions for collaboration, conflict detection, dealing with complex domain objects, pagination and lazy loading. It also offers integration with Hibernate and Spring | There is only one commercial product for this solution – LCDS from Adobe. It has a relatively steep learning curve |
I have also attached an archive containing one Flex Builder project showing the data transfer using sockets and also a more advanced case of data management use. For the rest of the cases I recommend that you download the most recent version of BlazeDS (look in samples folder) or LCDS (look in the lcds-samples folder). If you want to use non Adobe products you can try WebORB (look in examples/flex folder) or GraniteDS (I was not able to find a folder with samples in this product).
November 18th, 2008 at 5:12 pm
Hi,
you have a very good blog…
i’ve a question about between java and actionscript serialization (i see it in the flex 3 developer manual)..
i’ve make a little example to see the serialization in action using blazeds, apache and a remote object…the sample works very well..but i would know if is possible to have the same serialization in a local environment (for example without apache and blazeds).
thanks
Lord
i hope that
November 18th, 2008 at 9:06 pm
Hi,
Not quite sure that I understood what is your intention..you intend to write your own server and you want to be able to use the serialization mechanism? Can you provide a little bit more details?
Cornel.
November 19th, 2008 at 12:37 pm
Hi Cornel
thanks for the reply…
i’ve this problem:
i would create a flex application, that trough a remote object, can invoke methods within a jar class or a jar file..java returns an object (correctly serialiazed)…at the end the flex appl reads the object and trough the object serialization displays it, for example, in a data grid…
so i would know if is possible to create a remote onbject without using blazeds and a web server to invoke methods on jar file..otherwise is it possible to do this with socket or others technologies?
i hope that
thanks again…
November 19th, 2008 at 5:29 pm
It is possible, but practically you will have to write your own server that will listen on some port and will do the work. I’m working at a customer now and I’m a little busy, after I will have more time I will tell you what jars should be used in order to perform the AMF serialization on the java objects.
However why don’t you like BlazeDS? It’s easy to install, you can integrate it with an existing application etc – it’s time expensive to write our own server.
November 20th, 2008 at 10:58 am
Hi Cornel,
thanks a lot..
i like BlazeDs but i would create my java classes and insert them in a local environment together with an adobe flex appl..and work with serializarion to pass object from actionscript to java and viceversa…
also is it possible to communicate between java and actionscript with sockets and pass my own objects?
thanks again
Regards
Lorenzo
November 25th, 2008 at 11:48 am
Hi,
Yes it is. I will try to give you more details, but I’m still very busy now. I hope to be able to do it until the end of this week
Cornel.
December 2nd, 2008 at 12:56 pm
Hi Cornel.
Thank for the great entry for “Flex middlewares”.
I have only one question. Does the WebOrb has Client Synchronization feature like LiveCycle Data Service ES?
December 2nd, 2008 at 2:09 pm
Hi Cornel,
. I’ll be waiting, like Lorenzo, for more details regarding communication between Java and Action Script with sockets ( to pass objects) when you have the time. I need this for an AIR offline application.
I like your article very much. I’ve searched a lot for something like this
Regards
Cornelia
December 2nd, 2008 at 10:49 pm
Hi Tanakorn,
Yes WebORB has this feature..check their blog http://www.themidnightcoders.com/blog/2007/02/rethinking-flex-data-management-part-3.html
December 2nd, 2008 at 11:00 pm
Hi Cornelia,
Thanks for your comments – I’m at Adobe Max Milan now…I will try to answer after it’s over.
December 3rd, 2008 at 6:45 am
Thank for your kindly reply.
Actually, I just examined for the client synchronization in WebORB with its application (weborb.war) in tomcat 6. It not work, and whenever I CREATE, UPDATE, REMOVE the record in database on client side, I have to press F5 in another browser (I open two browsers for the same page) to refresh entire page to see the change.
When I look into the feature that was added to the latest release of WebORB for Java (3.0). I found that this feature (client synchronization) was just added in product in last minute (in version 3.0 GA)
So, May I think this feature was not work find in version 3.0, am I right?
December 11th, 2008 at 8:23 am
So in order to comunicate between Flex and Java using sockets you have several options:
The first one is to define your own protocol but probably is too time expensive so it does not worth it.
So it would be logical to use AMF. In order to use AMF you will have to write the following code in order to do serialization and deserialization. I will present only one way (write from java, read from flex) – for the reverse way you will have to use AMF3Input and socket.writeObject
Java part:
SerializationContext serializationContext = new SerializationContext();
serializationContext.createASObjectForMissingType = true;
serializationContext.instantiateTypes = true;
Amf3Output amf3Output = new Amf3Output(serializationContext);
amf3Output.setOutputStream(out);
Message obj = new Message();//your object
amf3Output.writeObject(obj);
On the flex part you can read the object like this:
registerClassAlias(“test.Message”, Message);
var oo:Message= socket.readObject() as Message;
If it’s not clear enough let me know. You should include flex-messaging-common.jar and flex-messaging-core.jar (from blazeds distribution) into your java project (and check also the api)
The third option is simpler (if you are using an AIR application). There is a project at http://www.merapiproject.net which is doing that – you can take a look on their samples.
December 14th, 2008 at 12:31 pm
Hi Cornel,
Thanks for the informative post.
Your last Dec 11th, 2008 comment helped get me started, but there was one piece that
I wrangled with and might be worth commenting here.
From the Java code snippet from your comment…
amf3Output.setOutputStream(out);
I found that “out” had to be ByteArrayOutputStream, otherwise you’ll get a “Error: Error #2030: End of file was encountered.” on the Flash/Flex side when you issue a Socket.readObject()
So a Java ServerSocket code might look like this (for writing):
ServerSocket serverSocket = new ServerSocket(7777);
Socket curSock = null;
SerializationContext serializationContext = new SerializationContext();
serializationContext.createASObjectForMissingType = true;
serializationContext.instantiateTypes = true;
Amf3Output amf3Output = new Amf3Output(serializationContext);
while((curSock = serverSocket.accept()) != null){
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
amf3Output.setOutputStream(baos);
amf3Output.writeObject(new MyMessage());
curSock.getOutputStream().write(baos.toByteArray());
}
Hope this helps someone…
January 7th, 2009 at 10:47 am
Hi Peter,
Thanks for your comment, it is a good observation.
January 11th, 2009 at 7:33 pm
[...] Flex 2 Sample Application – forta.com Realtime, life Example of Flex application – justskins.com Bringing data into Flex applications – introduction – cornelcreanga.com Flex 3:Applications – labs.adobe.com Tour De Flex Application – insideria.com [...]
January 12th, 2009 at 3:27 pm
Just to digress a little into the security of the data
I’m writing a Flex application which needs to download some sensitive data from an (Oracle) server. How secure is the data in transit? Can it be easily encrypted? And indeed, can the data be somehow hacked into once in memory on the user’s PC – e.g. by some type of virus?
January 12th, 2009 at 6:09 pm
It’s the developer responsibility to take care about exchanging secure data – it implies using secure channels – https or rtmps. There is nothing special in Flex compared with HTML regarding sending secure data from this point of view. As a note Oracle SSO also works, Flash player will always send the cookies.
Regarding the possibility for another program to steal data from the memory allocated by the Flash Player: theoretically not, because of the CPU architecture and operating system one process cannot access memory allocated by another process, however a malicious program running with 0 priority can access all the memory. So yes a virus can do that theoretically. But this is true for any application including browsers.
So for your application I will recommend the following things (note that I’m note a security expert however):
use secure channels
use some form of authentication
do not rely on anything send from the client, all the requests should be checked taking into account the logged user, all the data validations should exists also on server (keep in mind that the client (the SWF) can be disassembled)
January 16th, 2009 at 7:27 am
HOW TO CALL THE POST METHOD ON A REST SERVICE THRU FLEX ????
———————————————————————————-
ONE
***
I am having nightmares in resolving the 2032 Stream error while trying to call a POST method on a REST web service.
I have my HTTPService as
Code:
Hi
I am calling the service as
Code:
httpRestService.send();
in one of the methods.
I am getting the fault error. The following is the event.toString in my Fault Handler method
Code:
FaultEvent fault=[RPC Fault faultString="HTTP request error" faultCode="Server.Error.Request" faultDetail="Error: [IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2032: Stream Error. URL: ...
The INTERESTING thing is that when I remove that
Code:
Hi
from my HTTPService definition
THEN the GET of the REST service gets called, even when I have specified POST as the service method!
* I have checked with the URL (its correct)
* I have checked the parameters (the rest POST service takes a string a
parameter). Have even tried with a string parameter inside the call to the
service's send method (httpRestService.send()).
* I even used a crossdomain xml.
Nothing works for me!
***********************************************************************************************
TWO
****
I tried using BlazeDS to use proxy while calling REST service from Flex. But, there also, it is giving me an
Code:
[RPC Fault faultString="HTTP/1.1 415 Unsupported Media Type" faultCode="Server.Proxy.Request.Failed" faultDetail="HTTP/1.1 415 Unsupported Media Type"] error, when I am trying the POST method.
The GET returns successfully (even in this case) as was with the case when I didn’t use BlaseDS and had useProxy attribute set to ‘no’ for the HTTPService.
******SO THE PROBLEM IS WITH POST! BOTH WHEN I USE BLAZEDS AND WHEN I DO NOT USE IT!*******
————————————
Anyone faced a similar situation? I badly need to get through…
thanks
Bhaskar
January 18th, 2009 at 11:27 pm
Hi Bhaskar,
If you can send me an archive with a use case in order to reproduce the issue I can take a look on it..otherwise is hard to see what is the problem.
March 31st, 2009 at 4:52 am
I’ve got a question about how you utilized apache mina with AMF3. I think I understand how to use the amf3 api in flex-messaging-common.jar and flex-messaging-core.jar. But, it’s not entirely clear to me how to use the flex messaging api w/ mina.
Did you use a CumulativeProtocolDecoder to get all the bytes off the socket before using Amf3Input.readObject()? If so, how did you know when all of the bytes of the amf3 message had been received?
I’m struggling to figure out how to use mina to get the bytes off the line and then using the blazeDS libs to deserialize my object. Any thoughts or helpful pointers in the right direction from your experience?
May 26th, 2009 at 11:20 am
Hi,
The posts are too good which you post. I tried to implement the blazeds and facing the below problem. Please let me know if you can help me out.
http://www.flexdeveloper.eu/forums/flex-builder-flash-builder-eclipse/flex-java-hibernate/
http://www.actionscript.org/forums/showthread.php3?t=207662
Thanks in advance
September 9th, 2009 at 9:22 am
Hi Cornel
It is a really nice blog. I want to use Remoting in my application. Are there any additional jars requierd for this apart from Flex SDK? Also, if you could clear my confusion. I was recently told by Adobe Support that I can use remoting using BlazeDS/LCDS but this blog suggests that Remoting is independant of the latter. Could you please clarify?
Thanks
Cheree
September 9th, 2009 at 12:50 pm
Thanks. If you want to use remoting you BlazeDS/LCDS are good options, but no the only ones. There are also another products as I wrote in the article: Pimento, GraniteDS, WebOrb and others.
If you use AMF for the remoting serialization you don;t need anything else, the Flash Player knows how to do it. If you plan to use Hessian serialization you will need a swc on the client side.
On the server side you need several jars, if will install BlazeDS you will find them in the blazeds.war file.
October 23rd, 2009 at 11:02 pm
Great!!! Great!!! Great!!! Great!!!!
Thanks Cornel!!!! It’s just all what I was searchin’!
Can I translate this post to Portuguese language? Send me one email, please!!!
Thanks
Regards
November 5th, 2009 at 8:21 am
[...] Bringing data into Flex applications – introduction – cornelcreanga.com [...]
December 25th, 2009 at 6:13 pm
[...] Bringing data into Flex applications – introduction – cornelcreanga.com [...]
January 16th, 2010 at 7:40 am
[...] Bringing data into Flex applications – introduction – cornelcreanga.com [...]