Remoting, XML, AMF, Hessian and Deflate algorithm

I’m a big fan of using remote calling whenever possible to bring the data from a Java server into a Flex application, not only for performance reasons but also because the code is much cleaner. Yesterday, I implemented a quick benchmark to test both approaches (remote versus a service returning xml) – results are bellow.  You can also download the project here (it’s created in Intellij, and you will also need Java persistence libraries). It’s a quick benchmark and not a benchmark framework so the code is no production quality. I’ve tried to eliminate the time spent by the garbage collector and the times for the benchmark are taken into consideration only after the Hotspot optimizations of the code.

Some details about my benchmark: I have three objects (Company objects havea bidirectional 1-n relation with an Employee objects and the Employee has a n-1 relation with a Town object). I read the data from a MySql database using Hibernate(I have about 3 Companies, 1000 Employees, and 5 Towns).

For the XML case I’m doing a conversion from the Java objects to XML, and optionally I have also included a ZIP compression. For the remote case I tested both AMF3 compression and Hessian. I tested only the algorithms (not the time spent the data from the application server) because I think that’s the most important thing.

The results are interesting, the most time is spent in XML conversion (using DOM4J). I will try to use also another XML library, maybe that time can be reduced a little . The results prove again that the binary formats (AMF3 and Hessian) are a very good option when sending data to the Flex client…note that even the compressed XML is not much smaller than the binary format.

Results table below. My system is a Lenovo laptop, CORE 2 Duo, 2.4Ghz

Avg Time (microseconds) Data size (kbytes)
AMF3 9945 28
Hessian 4675 29
XML 22064 158
XML+Deflate 27336 18

Note: the difference between AMF and Hessian depends a lot on the input data. For example if you have more repetitive data then AMF tends to be more efficient than Hessian on data size. I will try in the future to create a mini benchmark framework with different sets of data.

How to prevent memory leaks when reloading web applications

During my career as a software engineer I had to fix some nasty memory leaks that appeared only when trying to reload the current web application (one bug is described here). Most of the time the PermGen space was completely filled with class definition and the following error message was returned: “java.lang.OutOfMemoryError: PermGen space” (on older JVM it is possible to receive just “java.lang.OutOfMemoryError”)

PermGen is a region of memory allocated by the JVM for class definitions and for the constant pool. At first glance you might will be tempted to increase its size (the default value is 64MB) using the -XX:MaxPermSize parameter, however this solution will only allow you maybe just to reload your application perhaps several times more. The better solution is to identify the memory leak (and this post will describe several possible causes) and after that to fix it .

I will also write about the classloader architecture of an application server and what happens when the application server tries to unload a deployed application but I will not go into much detail, since there are better articles or books describing these things.

a)Classloader arhitecture for an applications server.

Classloaders are organized in parent child relationship, and a class can be visible only if it is visible from the current classloader or any of its parents – it cannot go down in hierarchy. Every classloader keeps a list of references to the loaded classes (take a look in java.lang.ClassLoader).

The following diagram (inspired from Tomcat documentation) describes the simplified classloader hierarchy used by an application server :

                       Bootstrap
                          |
                       System
                          |
                       Common
                      /      \
                 Webapp1   Webapp2 ...

If you are curious to see the whole hierarchy of classloaders for your class and server you can use the following code:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
while(classLoader != null) {
    System.out.println(classLoader);
    classLoader = classLoader.getParent();
}

The application server uses this hierarchy of classloaders in order to keep the applications isolated. For example if a class is loaded by the classloader Webapp1 it will be not visible from a class loaded by the classloader Webapp2. However a class loaded by the classloader Common is visible from the classloader Webapp2. As an analogy all the libraries from the Tomcat lib folder are visible for all deployed applications, but one application cannot see the libraries from the lib folder located inside another application.

b)Deploying and restarting your application

When you deploy and start your own application the server will a create a new classloader – let’s call it WEBCLOADER1, which will be used to load the classes from your application. When you redeploy your application it will set the reference of WEBCLOADER1 to null and it will create a new classloader used again to load your application. When you undeploy your application it will destroy WEBCLOADER1 and it will try to delete the application.

This process works well if the classes from your application are referenced only from WEBCLOADER1 or any other children classloaders created from WEBCLOADER1. If not, for example if one of your classes is referenced from the System classloader then your deployed application cannot be garbage collected and eventually you will receive the dreaded OutOfMemoryError.

How is it possible to have this situation? Is too simple unfortunately, just use something like this:

private static final ThreadLocal cache = new ThreadLocal();
cache.set(someObject);

In this case the current thread (one of the threads created by the application servers) has a reference to your object. The thread was created by the application server using a higher level classloader so it does not matter that WEBCLOADER1 is null, your application cannot be garbage collected.

The problem also arises when you use methods from the java.beans.Introspector class without calling flushCaches because it uses a static cache in order to make the introspection faster, so again your classes are going to be referenced from a classloader other than WEBCLOADER1.

c)How do I identify a memory leak related to the multiple classloader problem?

Use a good profiler. I was using YourKit profiler, it was one of the few able to help me two years ago (today there maybe be other choices). Using YourKit you can take a memory snapshot, undeploy your application, take another snapshot and use the compare snapshots features. If you will see objects belonging to your application it means that you have memory leaks. You can use the “Find paths from GC roots” option to see who’s keeping references to your class. That’s the easier part, after that you will have to locate the problem in your application – or in other third-party libraries used by your application. Bellow I will wrote some tips related to common problems.

Use a ServletContextListener to intercept when the context is destroyed; this is the place where you should have your clean up code. Or you can use the destroy() method from a dedicated servlet. Bellow are some tips for some common problems:

  • if you use commons-logging then call this method from the clean up method
  • LogFactory.release(Thread.currentThread().getContextClassLoader());
  • call Introspector.flushCaches() from the clean up method (or use a framework such as Spring which does that);
  • if you use any jdbc drivers you have two options: You can load them with a global classloader (for Tomcat copy the drivers in common/lib folder) or you can unregister them manually in the clean up method by calling
  • DriverManager.deregisterDriver(yourDriverClass);
  • the usage of static members does NOT prevent your application from being garbage collected
  • use ThreadLocal with caution and if you are using them be sure to clean the values. A safe practice is to use a filter or some kind of interceptor to do that.

BlazeDS, LCDS and integration with existing application

UPDATE: Well, I just published my post and I received the following message on YM: You forgot to write that you have to pay money in order to use these products.
I do not want to write a half a page now on licensing so I will be brief (please check the Adobe site for exact information):
BlazeDS is free and opensource. You do not have to pay anything to use it. If you want to buy Adobe support that’s fine, if not you can find books, articles and samples related to this product. LCDS it is a commercial product but it is free if you are using it for one processor, so you can evaluate it and decide if it’s ok for you or not.

Some time ago, after a discussion with several Java developers I realized that they thought  that BlazeDS and Livecycle Data Services were some kind of special servers that should be installed separately from the application server – something like Lightstreamer. They also thought that in this case they would have to write additional code in order to do the integration between servers. And one week ago I even met some guys using webservices in order to retrieve data from the Java backend because they did not want “to depend on some Adobe server”. There is nothing wrong with using webservices in Flex, in some cases it is your only option (for example if you want to use Amazon search API), but it is much slower than using BlazeDS remoting. So if you need to connect your Flex application to your java backend I strongly recommend using remoting or the data management feature provided by LCDS.

So I’ve decided to write two posts, one describing how to integrate BlazeDS or LCDS into your existing application, the second one on how to integrate or expose the existing Java code in order to be used in remote calls or for data synchronization. I will also try to cover the aspect of integrating Hibernate and Spring.

Both BlazeDS and LCDS are packaged as WAR applications, they are just simple Java applications that can be deployed in any application server. The procedure to install them is described in so many places so I don’t want to insist on that – take a look, for example, at my colleague’s post. Instead I will write what to do when you already have an application packaged as a WAR and you intend to do the integration with BlazeDS/LCDS.

For BlazeDS there are three steps:

a)Copy the folder called “flex” from blazeds.war\WEB-INF into your WEB-INF folder. This folder contains the configuration files needed by BlazeDS. Of course you can copy in other location if you want but for the sake of simplicity leave them under WEB-INF

b)Take a look at the folder named “lib” at blazeds.war\WEB-INF\lib . It contains all the jar files needed by BlazeDS:

backport-util-concurrent.jar
cfgatewayadapter.jar – you don’t need this it if you do not use ColdFusion
commons-codec-1.3.jar
commons-httpclient-3.0.1.jar – used by the proxy services, if you use only remoting it’s optional
commons-logging.jar
concurrent.jar
flex-messaging-common.jar
flex-messaging-core.jar
flex-messaging-opt.jar
flex-messaging-proxy.jar
flex-messaging-remoting.jar
xalan.jar

You should copy these libraries into your WEB-INF\lib folder. If you already use some of them (Jakarta libraries for example) you should keep the latest version (you can check the version by looking in the manifest.mf file.

c)Add the following entries into your web.xml file (taken from BlazeDS web.xml file):

<!– Http Flex Session attribute and binding listener support –>
<listener>
<listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>

<!– MessageBroker Servlet –>
<servlet>
<servlet-name>MessageBrokerServlet</servlet-name>
<display-name>MessageBrokerServlet</display-name>
<servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
<init-param>
<param-name>services.configuration.file</param-name>
<param-value>/WEB-INF/flex/services-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>MessageBrokerServlet</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>

The same steps are valid also for LCDS with several small differences:

a)The same folder flex should be copied but for LCDS it also contains some SWC libraries and one more configuration file

b)The libraries shipped with LCDS are:

acrobat-core.jar – you don’t need this if you plan to use only data management and remoting
acrobat-core-charset.jar – you don’t need this if you plan to use only data management and remoting
backport-util-concurrent.jar
cfdataservicesadapter.jar – you don’t need this if you do not use ColdFusion
cfgatewayadapter.jar – you don’t need this if you do not use ColdFusion
commons-codec-1.3.jar
commons-httpclient-3.0.1.jar – used by the proxy services, if you use only remoting it’s optional
commons-logging.jar
concurrent.jar
flex-acrobat
flex-messaging-common.jar
flex-messaging-core.jar
flex-messaging-data.jar
flex-messaging-data-req.jar
flex-messaging-opt.jar
flex-messaging-proxy.jar
flex-messaging-remoting.jar

c)This step is identical for both BlazeDS and LCDS.

In the second post on this subject I will show how to integrate your existing Java code so it can be invoked remotely or used with the data management feature.

AMF3 and zlib compression

Yesterday I was reading the Exadel documentation and in the chapter describing AMF format I’ve read the following things: “AMF objects are of a very small volume due to the fact that they are compressed using zlib”. I sent them an email regarding that and explaining that the DEFLATE algorithm is not used in AMF serialization, so there is no zlib connection). They told me that they took the information from web, and I see what the mean – if you will search for “AMF objects are compressed using zlib”  you will find a lot of references.

Peter Farland (lead engineer for the SDK team) has already posted several comments on blogs and on the Zend Framework wiki regarding that and I will write it again here: there is no connection between the zlib algorithm and AMF format. Yes the serialization uses some kind of compression (for instance writing references for identical strings) but not zlib.

However the developer is free to compress all HTTP responses using zlib (when supported) so the serialized AMF data will be compressed also. Or you can choose to apply DEFLATE only on some data (like big strings) – you can read here my post related to that.

Bringing data into Flex applications – introduction

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(event :P rogressEvent){
  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).

Transylvania JUG – Flex presentation

Last week I made two presentations (Introduction to Flex and Integration between Flex and Java) for Transylvania JUG , the first Java user group established in Romania, in the middle of Transylvania. There were about 60-70 developers asking a lot of questions. I knew that some of them knew Flex but I was surprised to see that some of them also have knowledge of LCDS and BlazeDS. The user group was founded only a few months ago but they succeeded to organize several meeting related to Flex, Groovy, TestNG.

I hope that in future this kind of meetings will become a regular thing in Romania and more active user groups will be founded. Romania has one of the largest developers communities in Eastern Europe – and meetings like this help people share information, establish new connections, and improve their applications.

A picture from the conference room:

IMG_8637

And the user group logo:

logo_jug.gif

Connecting Java applications with Blaze DS

A new feature was added to Blaze DS (currently only in the nightly builds) – the ability to connect to a Blaze DS server from a Java client. It’s a useful feature if you have to do integration between some legacy Java application and a Blaze DS server and you don’t want to write your own serialization mechanism or if you plan to write some tools for testing.

The specification can be found here and I’ve also created a Hello world project which can be downloaded from this location. On my local computer I was able to do about 3000 calls per second – impressive compared with a WebService call.

On the client I wrote four lines of code in order to invoke the method from the server:

AMFConnection amfConnection = new AMFConnection();
amfConnection.connect(http://localhost:8080/blaze/messagebroker/amf);
Message message = (Message)amfConnection.call(“HelloService.sayHello”, new Message(cornel));
amfConnection.close();

And the method signature is:

public class HelloService {
    public Message sayHello(Message message){
        return new Message(“hello “+message.getText());
    }
}

On the client you need to use two jar files from Blaze DS distribution (flex-messaging-common.jar and flex-messaging-core.jar).

LiveCycle Data Services 2.6 – new features (4)

Support for offline synchronization was improved in LiveCycle Data Services 2.6 – the Flex applications deployed on the AIR runtime will use a cache base on SQLite database instead of a Local Shared Objects cache.

There are several resources describing in details this feature in detail and providing some samples – Cristophe Coenraets blog, an article on Inside RIA and the developer guide.

Of course, you can synchronize your application without using LiveCycle Data Services and use whatever suits you best (SQLite or LSO), in fact I know several developers who have been doing this for the Flex applications they deploy on browser for a long time. There are, however, advantages to using the LiveCycle Data Services solution for the offline/online synchronization are:

  • you do not have to write additional code to deal with synchronization so you can save a lot of time
  • you can use the already implemented conflict resolution model

LiveCycle Data Services and Hibernate one-to-many association

I’ve noticed that several peoples have problems implementing one-to-many associations so I decided to write a simple example (using HibernateAnnotationsAssembler). It contains several use cases of working with this kind of association (more than the samples provided with LCDS distribution):

  • you can modify (update, add, delete) a parent or a child and see the synchronization between several clients. Note that when deleting the parent I have to programmatically delete the children’s – cascade on delete does not work yet automatically
  • you can create a parent and a child in the same transaction (no need to create the parent and save it before adding the children)
  • you can revert your modifications
  • conflict management should work both for parents and children
  • you can check the generated SQL in the server console (I’ve tested with MySQL database) and see the effect of the load-on-demand and page-size attributes).
  • you can check what happens when cache-items is set to true and when it is set to false

Note: I’ve mapped the one-to-many association as bidirectional (The parent has a list of children and a child has a reference to the parent). However if you have a large number of children associated with a parent, then from a performance point of view it is better to drop the list from the parent)

Also because the association is bidirectional I had to add the read-only attribute for the list of children (to notify the dataservice that it should look for updates only at the other end). If you will set the value to “false” you will see some strange SQL commands.

I’ve used Java 1.5 and Hibernate annotations so there is really not much code. You can download it from here (it’s an archive containing a Flex project and a readme.txt).

LiveCycle Data Services 2.6 – new features (3)

Two new endpoints were introduced in LiveCycle Data Services 2.6: NIO AMF and NIO HTTP and with them one can have now a viable alternative to RTMP. While RTMP offers best performance for data push – offers a direct duplex socket connection between the client and server and does not need a dedicated thread for every connection it uses a non-standard port (2038) so sometimes it is blocked by firewalls. If the firewall restriction cannot be lifted the other options was to use servlet-based AMF and HTTP endpoints and use long polling or HTTP streaming to emulate real time communication. The scalability was very low compared with RTMP (maybe several hundreds/thousands compared with tens of thousand) because of the dedicated thread per connection.

With the new endpoints this problem was solved – by building a NIO server based on the JAVA NIO api this limitation was removed– now it is possible to handle the connections asynchronously. And you do not have firewall issues because they are using the HTTP port.

From the client point of view the NIO AMF and HTTP endpoints are equivalent to the old endpoints (AMF and HTTP) so you should not modify the existing applications (but you cannot share the FlexSession between channels using NIO HTTP endpoints and the ones using HTTP). After you download the Livecycle Data Services 2.6 you can find several examples of how to configure them in the services-config.xml file.

It is important to mention that these new endpoints were introduced only for LiveCycle Data Services and not for Blaze DS – so if you are using the last one you still have to deal with the limitations of the current servlet API (one thread per connection) – at least at the moment of writing this post. Probably the situations will change in future – Blaze is open source so anyone can contribute to the source code. There seems to be other several free options – GraniteDS and WebORB however I did not had yet time to test them.