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

Flex – improve search behavior in ComboBox components

The ComboBox component from Flex SDK does not perform a fancy search by default – for example if you press ‘A‘ it will go to the first element starting with ‘A‘, if you press ‘B‘ it will go the first element starting with ‘B‘ but if you press quickly ‘A‘ and ‘B‘ it will not display the first element starting with ‘AB‘ – instead if will display the first one starting with A and after that the one starting with ‘B’. I know that the HTML select control can do that and I’ve heard some people complaining because they are not able to do it in Flex so I planned to wrote the implementation.

There are two cases: the first one is when the drop down list is opened and the user is typing, the second one is when the drop down list is not opened but the focus is positioned on the ComboBox and the user is typing.

For the first case I extended the List component and I wrote a new findKey method. The dropdownFactory property of the ComboBox component will be set to the new class. The code is displayed below:

package com.test
{
    import mx.controls.List;
    public class ListSearch extends List    {
        private var previous:Number;
        private var current:Number;
        private var pressed:String=“”;
        protected override function findKey(eventCode:int):Boolean{
            current = new Date().time;
            if ((current-previous)>500){
                previous = current;
                pressed = String.fromCharCode(eventCode);
                return super.findKey(eventCode);
            }else{
                previous = current;
                pressed = pressed + String.fromCharCode(eventCode);
                return findString(pressed);
            }
        }
    }
}
<mx:ComboBox id=“combo” dropdownFactory=“com.test.ListSearch”>
   <mx:dataProvider>
      <mx:Array>
         <mx:String></mx:String>
         <mx:String>AAAAAAAA</mx:String>
         <mx:String>ABBBBBBB</mx:String>
         <mx:String>ACCCCCCC</mx:String>
         <mx:String>BBBBBBBB</mx:String>
         <mx:String>CCCCCCCC</mx:String>
       </mx:Array>
   </mx:dataProvider>
</mx:ComboBox>

The second case proved to be much difficult..I do not know if I will be able to do it without rewriting the entire ComboBox component – too many of methods and members have the private access modifier so extending is not a solution. I’m still wondering how to do it.

I’m curious if anyone experienced this problem when trying to modify the default behavior of the ComboBox component (or another Flex component).

LiveCycle Data Services 2.6 – new features (3)

Two new endpoints were introduced in LiveCycle Data Services 2.6: NIO AMF and NIO HTTP. With them now you have a viable alternative to RTMP.  RTMP offers the best performance for data push, with a direct duplex socket connection between the client and server and no need for a dedicated thread for every connection. It  does, however, uses a non-standard port (2038) so sometimes it is blocked by firewalls. If the firewall restriction could not be lifted the other options were 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 you 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 do not need to 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 latter 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 this situations will change in future – BlazeDS is open source so anyone can contribute to the source code. There seems to be several other free options including GraniteDS and WebORB, however I have not yet had time to test them.

Flex, Blaze DS and storing session data

One of the biggest difference between the classical web applications (HTML/JS) and the rich ones (Java applets, Flex, Silverlight) is how can you store the state of the application.

With HTML applications we are used to using different hacks to store the state – either appending all the necessary information to the requests or storing the data on the server (and using a cookie or a session id to link the user and the information). Some even use a “dirty hack” and keep a small window open where you can store/retrieve all this information by using Javascript (yes, I have seen this unusual approach in several applications).

With Flex applications (and also with the other technologies mentioned before) the things are much simpler. You do not have several pages which are loaded from the server, instead you have an application that is loaded in the browser and can store the data using its internal data structures. The application will make requests to the server but only to exchange data (and in some situations to load modules), not to load whole pages. To make an analogy – it’s like having a HTML application composed of only one page that uses AJAX and JavaScript to load and build other pages (This is doable, I have seen a project where the guys were using this approach because of some strange requests from the client, but it was a nightmare to maintain and develop the application).

So you are able to store user preferences, user actions (for example the products added to a shopping cart) and other data directly into the client – the Flex application. It is more natural (in my opinion) than storing the data on the server and it is also much cheaper than buying expensive hardware for the middleware – you are using the client machine to store data so you are not overloading the server (think about having 100000 connected clients and session replication and you will understand what I’m talking about).

However there are several situations when you have to store a minimal amount of information on the server – the user identifier for example. After a successfully login authentication I have to store the user ID into the server session. After that this ID is used to check all the requests and to filter data that is sent to the client. Below I show you how to do that in Flex and what things you need to take into account. I’m using Blaze DS  on the server side.

The FlexContext class can be used to access the FlexSession class which has several useful methods to set/get/remove attributes, to configure the timeout and session listeners, and so on. Here is some code that shows how to use them.

UserRoles userRoles = userHome.logIn(userName, passwd);
if (userRoles == null)
  throw LoginFailedException(“Invalid login”);
FlexContext.getFlexSession().setAttribute(“userId”, userRoles.getUserId());
public Collection fill(List fillArgs, int startIndex, int numItems){
    Integer userId = (Integer) FlexContext.getFlexSession().getAttribute(“userId”);
    if (userId==null)
        throw AuthenticationException(“No logged user”);
    ASObject map = (ASObject)fillArgs.get(1);
    Integer companyId = (Integer)map.get(“companyId”);
    return new CompanyService().findProducts(
            companyId,
            userId);
}

Note: this is just a simple example how to use FlexSession. For user authentication and securing destinations read the LCDS developer guide, specifically the chapter titled “Securing destination”.

Important things to take into account when working with session data (taken from the developer’s guide):

  • when using RTMP channel after a browser refresh the content of the FlexSession is lost; also the user will have to log in again
  • you will have different FlexSession objects for HTTP, RTMP and NIOHTTP channels – so consider working with only one type of channel
  • if you logged in using a RTMP channel you must log in again when switching to another type of channel
  • FlexSession is not cluster aware - if a client connects to a different server in the cluster, the client receives a new FlexSession and the client will have to login again

How to win a ticket to Flash on the Beach conference

The Flash on the Beach conference will take place between 28th September and 1st October in Brighton, UK. It is the most important Flash conference from Europe and this year some of the best developers and designers are presenting for three days. We have some free tickets for the conference (worth £499)– you can win one of them going to this link and submitting a picture. After that each one of the Adobe European evangelists (myself, Mihai Pricope, Mihai Corlan, Andrew Shorten, Enrique Duvos, Serge Jespers) will choose a winner.

If you are a Flash/Flex developer or designer do not miss this opportunity, you can learn new things, make a lot of connections and have a lot of fun

By the way when choosing the winners the most important thing is the creativity of the photo – just take a look at Serge picture…

LiveCycle Data Services 2.6 – new features (2)

This is the second post describing several new features in the 2.6 version of LiveCycle Data Services– I will present several features that are related to managed associations.

In the current version several new parameters were introduced: read-only, load-on-demand, page-size, paged-collection and paged-updates.

The first one should be used for bidirectional relationships and it has the same meaning as setting inverse=”true” for a Hibernate association (the assembler will use only the other side of the relation in order to take modifications into account).

The other ones are used to improve the performance of managed associations. In the previous version you could improve it in several cases by using the “lazy” parameter. When set to true and applied to a one-to-one, one-to-many, or many-to-many association the client, by default, will load by default only the ID of the objects - the whole object will be loaded only when it is accessed for the first time. This can improve performance, but if you have a large collection you will still have to load a lot of information from the database to obtain all the ID’s and send them to the client

The new parameters remove this limitation. When you set load-on-demand for an association no values are sent to the client until the first time the association is accessed (it has the same effect as the lazy parameter for Hibernate managed collection). The page-size and paged-collection parameters are used to implement page-by-page fetching from the database/server - very important for large sets. The last one, paged-updates, controls the way in which the modifications from the client are sent to the server. If the value is false the entire collection is sent when some objects are removed or added, if true only the ID’s of these objects are send to the server. This parameter is automatically set to true if also page-size is set to true.

The effect of these parameters can be noticed especially when working with large collection – I performed some tests with a collection that has about 50000 elements (loaded in a datagrid) and it worked smoothly.

LiveCycle Data Services 2.6 – new features

I plan to write some posts describing what’s new in LiveCycle Data Services 2.6 compared with the previous version (2.5.1) and also to provide some examples. There are some important new features that affect both productivity and performance

Today I will describe two of them: hibernate annotations and the automatic creation of associated destination

First, you can now use hibernate annotations because a new type of assembler was introduced – HibernateAnnotationsAssembler. This assembler extends HibernateAssembler and it has only one supplementary method – createHibernateConfiguration, which knows to create a Configuration class from the annotations.

In order to use the annotations the following steps should be followed:

a)Declare annotations for the persisted objects

b)Change Hibernate configuration files in order to use <mapping class=”class name”/> instead of <mapping resource=”resource name” />

c)Change the assembler for a destination from HibernateAssembler to HibernateAnnotationsAssembler

d)Add the following entry to the destination configuration:

<item-class>class name</item-class>

The second one: Now it is possible to create automatically associated destinations as long as the destinations you are directly using for are defined in the data-management-config.xml. Also you can skip the identity tag for a destination and then it will be automatically generated taking into account the corresponding annotations. The big advantage of this is that now you can create and manage your destinations faster. The disadvantage is that if you do not want to configure any metadata you can lose performance (for example if you do not specify load-on–demand for a large set).

Another important point is that you cannot use the automatically created destinations for fill operations – if you want to do that you will have to add an explicit destination declaration for them into data-management-config.xml.

Below is an example of data-management-config.xml which uses the new way of declaring destinations:

<?xml version=“1.0″ encoding=“UTF-8″?>
<service id=“data-service”
    class=“flex.data.DataService”>
    <adapters>
        <adapter-definition id=“java-dao” class=“flex.data.adapters.JavaAdapter” default=“true”/>
    </adapters>
    <default-channels>
        <channel ref=“my-rtmp” />
    </default-channels>
    <destination id=“test.Company” channels=“my-rtmp”>
        <properties>
            <source>flex.data.assemblers.HibernateAnnotationsAssembler</source>
            <scope>application</scope>
            <item-class>test.Company</item-class>
            <metadata>
                <one-to-many property=“products” destination=“test.Product” read-only=“true” page-size=“20″ paged-collection=“true” lazy=“false” />
            </metadata>
            <server>
                <hibernate-entity>test.Company</hibernate-entity>
            </server>
        </properties>
    </destination>
</service>

I do not declare the identity of the test.Company destination – also I do not declare the destination test.Product. The last one will be automatically generated taking into consideration the hibernate annotations.

Note: it is possible completely omit the metadata section but I wanted to configure several parameters (lazy, paged-collection) in order to improve performance.

Nested properties and DataGridColumn

Almost every project that I have been involved with shares the same problem: by default, the DataGrid component cannot render by default nested properties – it can display only the top level property. For example : if you have the object Product with the properties name and company (and company has other properties) you can have a column displaying “name” but you cannot have one displaying “company.name”. The classic way to solve this is to declare a function which knows how to extract the data and specify the labelFunction property for the grid column. Personally I dislike that approach – I can have almost one hundred grids in my application - I would like to write dataField=“company.name” in a column definition and that’s all.

I have found several solutions based on extending DataGridColumn or by creating a custom item renderer but these solutions are not aware of ItemPendingException – and when you use LCDS you can have a lot of managed associations with lazy=”true”. So I’ve decided to write a custom grid column which knows how to deal with that condition. Below is the code and a small sample that shows how to use it. Currently, the component knows only to work with nested data – maybe later I will extend it to also work with indexed properties.

By the way there is also an enhancement request on JIRA to make the DataGrid support nested data by default.

   1: public class DataGridColumnNested extends DataGridColumn{
   2:
   3:     override public function itemToLabel(data:Object):String{
   4:         var currentData:Object = data;
   5:         if (data==null)
   6:             return “”;
   7:         if (dataField.indexOf(“.”) != -1){
   8:
   9:             var fields:Array = dataField.split(“.”);
  10:
  11:             try{
  12:                 for each(var field:String in fields){
  13:                     currentData = currentData[field];
  14:                     if (currentData==null)
  15:                         break;
  16:                 }
  17:             }catch(ipe:ItemPendingError){
  18:                 ipe.addResponder(new ItemResponder(
  19:                     function (result:Object, token:Object=null){
  20:                         itemToLabel(result.body);
  21:                     },
  22:                     function (fault:Object, token:Object=null){
  23:                         trace(‘Error while loading’);
  24:                     }
  25:                 ));
  26:             }
  27:         }
  28:
  29:         return super.itemToLabel(currentData);
  30:     }
  31:
  32: }

Usage:

   1: <mx:DataGrid id=“companyGrid” width=“800″ dataProvider=“{productArray}” editable=“true”>
   2:     <mx:columns>
   3:         <mx:DataGridColumn dataField=“id”  headerText=“Id” editable=“false”/>
   4:         <mx:DataGridColumn dataField=“name”  headerText=“Product”/>
   5:         <c:DataGridColumnNested editable=“false” headerText=“Company name” dataField=“company.name”/>
   6:     </mx:columns>
   7: </mx:DataGrid>

AMF - Problems when serializing between Java and ActionScript

Below are some tips and tricks when dealing with serialization between Java and ActionScript. I’ve spent some time and encountered some frustrations (especially when I was too tired) trying to understand why the value is not properly sent over the wire so I decided to document all of my mistakes. Over the time I will edit this post to add new insights

  • if something seems wrong turn on debugging in services-config.xml
  • a property must have a public getter and setter in order to be serialized. I know that is strange (why should I have a setter when it’s not needed?) but that’s it. I do not like it all because sometimes it breaks encapsulation
  • you should take care to map the ActionScript class with the corresponding Java class using the metadata. For example [RemoteClass(alias="com.foo.model.MyClass")]
  • verify that the ActionScript object is included in the SWF file. If your project does not have a reference to the AS file then it will not be included in the resulting SWF so the Java class will be serialized to a generic object
  • you cannot serialize maps that have integers as keys See this bug
  • when serializing Hibernate entities be sure that all of them are initialized or use some kind of Open Session in View pattern - or better build a value object to contain only the data you really need.
  • a NULL number in Java is converted to 0 in ActionScript
  • a Long number from Java cannot be properly converted to Number in ActionScript - you will lose precision, so you should send it packed in a different way
  • take care on timezone when serializing dates because it can have different values on client and server. The date object does not contains information related to it so if you need the timezone you should send it separately