BlazeDS – message selectors vs subtopics

Let’s assume that in a Flex/BlazeDS application you have a destination and a number of producers and  consumers associated to that. All the messages created by the producers are received by the consumers, and sometimes you don’t want that – you need to send the message only to a specific consumer or to a specific subset. For example you may have a chat application, so you should be able to offer features like private messaging or the ability to send messages only to some selected users.

In order to implement that you can use message subtopics and message selectors. Both options are described in details in BlazeDS manual, however an important detail related to them is missing – what are the advantages and disadvantages in both cases. Below I’ll try to write the most significant one, related to performance.

The advantage of using selector is the fact that you can define complex expression in order to filter the clients – for example you can use SQL92 conditional expression syntax when testing the message header. The producer can add a string in the message header and every message will be scanned using Consumer selector. The disadvantage is related to performance – every message will be scanned using the consumer selector, and if you have a large number of consumers it can significantly hinder performance, so one should be be careful when using it.

The advantage of using a subtopic is related to performance. BlazeDS will build behind a HashMap per subtopic containing all the associated customers. When a message is produced it will be send to the customers from the corresponding map, without testing for a condition. If the number of consumers with the same subtopic is small compared with the total of consumers the performance difference between selectors and subtopics can be very large.

In conclusion try to stick with subtopics – in most of the cases you don’t need the selector flexibility.

LCDS, ManagedObjectProxy and some reserved keywords

Yesterday I struggled for several hours looking in the Livecycle Data Services code in order to investigate the following error message:TypeError: Error #1034: Type Coercion failed: cannot convert “ZGUID” to QName. It was not easy but in the end I understood that it is an issue related to property collision inside of the ManagedObjectProxy  class. The ManagedObjectProxy instance is adding all the properties from the serialized objects into it. However if the name of one of your properties already exists in the ManagedObjectProxy instance then this process will fail. The following properties already exist (inherited from ObjectProxy):

dispatcher : EventDispatcher
notifiers : Object
object : Object
propertyList : Array
proxyClass : Class
type : QName
uid:String

For the “type” property a fix was provided in Livecycle Data Services 3, but not for the others. So if you design your domain object and you plan to use Livecycle Data Services it’s a good idea to not use this reserved keywords as names for your properties.

The problem appears only if you like to use the proxy approach (not having the corresponding AS class included in the client SWF).

Flex Data Services, Hibernate and Eclipse – Mike Slinn book

A lot of books about Flash, Flex, ActionScript and Java are available on the market and some of them are really good. However there are still very few books related to Flex and Java integration – best practices, frameworks, performance issues, patterns and anti patterns. Mike’s book fills a gap here, in talking primarily about the two Adobe products: BlazeDS and LiveCycle Data Services. I’ve met few people who really know well these products well, and I think that this book can help people get a better understanding. Flex and the other RIA technologies should improve not only the user experience/interaction but also the developers life  – making it much easier with – increased productivity, no more hacks and no more stateless clients. For that you need a strong platform both on the client and server side and LiveCycle Data Services can fulfill that.

The book comes with a tool written in Flash that can help you edit configuration files visually. Personally I would like to see an Eclipse plugin also – but considering that the tools for integrating Flash Player with Eclipse already exist I guess it’s possible in future.

The book is in early release – it can be ordered here.

Tomcat and common loader

I spent twenty minutes last night trying to understand why the Tomcat delivered with the Livecycle Data Services installation works fine when the libraries for jotm are located in a subfolder of the common/lib. When I’ve installed a clean version of Tomcat and I copied the folder jotm into common/lib the classloader was not able to find them, and I did not had any explanation.

Finally I discovered that there is a parameter in catalina.properties denoted common.loader. By default the value is ${catalina.home}/lib,${catalina.home}/lib/*.jar, however in the first case it is  ${catalina.home}/lib,${catalina.home}/lib/*.jar,${catalina.home}/lib/activemq4.1.1/*.jar,${catalina.home}/lib/jotm2.0.10/*.jar,${catalina.home}/lib/lcds/*.jar . This parameter specifies all the paths for the common class loader.

BlazeDS, AMF and read only properties

A common scenario when building domain objects is to have read only objects properties. The serialization algorithm from BlazeDS/LCDS does not know how to serialize the read only properties – it needs both get and set methods (with one exception – the java.lang.Throwable class). So you have two options in this scenario if you do not want to build adapters over your domain object:

a)Build your own serialization/deserialization mechanism

In order to do that you need to implement the java.lang.Externalizable interface for the Java classes and flash.utils.IExternalizable for the ActionScript ones. The Java example is here and the AS here.

When using this approach you have the following advantages/disadvantages:

Advantages: the serialization/deserialization is much faster
Disadvantages: greater development time, and you lose some optimizations related to data compression (like string references and writing numbers in fewer bytes). Of course, you can build your own optimizations but again this means more development time

b)Patch the code from BlazeDS. You either add the includeReadOnly = true line in the BeanProxy constructor (this flag is used for Throwable serialization), or, better yet, take the modifications from the current BlazeDS branch where this feature was implemented.

Logging in BlazeDS and LCDS with Java Util

I created a small class to allow integration between the logging mechanism from BlazeDS and java.util.logging. As an example it’s useful if you plan to use BlazeDS or Livecycle Data Services inside Google App Engine – the former one uses java.util.logging.

In order to use it you should modify services-config.xml to use the newly created class (I created my class in the package flex.messaging.log):
<target class=”flex.messaging.log.JavaUtilLogTarget” level=”Debug”>

The source code is below:

import java.util.logging.Level;

public class JavaUtilLogTarget extends AbstractTarget{
public void logEvent(LogEvent event) {

  java.util.logging.Logger log =
    java.util.logging.Logger.getLogger(event.logger.getCategory());
  Level level;

  if (event.level >= LogEvent.ERROR)
    level = Level.SEVERE;
  else if (event.level >= LogEvent.WARN)
    level = Level.WARNING;
  else if (event.level >= LogEvent.INFO)
    level = Level.INFO;
  else if (event.level >= LogEvent.DEBUG)
    level = Level.FINE;
  else
    level = Level.FINEST;

  log.log(level,event.message,event.throwable);

  }
}

Some internals related to Flex and remoting

When I started working with Livecycle Data Services and Java remoting I was afraid of doing too many remote calls at one time because of the network latency – if the network latency is 100ms and you do ten remote calls in order to fill a panel with data you will lose (10/maximum no of parallel connection supported by the browse*0.1) seconds for requests  . At least this is what I thought, taking into account my experience with Ajax.

However I found that this is not the case when doing remoting using the AmfChannel (which is backed by flash.net.NetConnection). In this case all your remote calls are put in a queue, and then all this request are grouped in a single HTML post. So no ten calls, only one – you can check that using a proxy like Charles.

It is important to note that this happens only when you use channels backed by flash.net.NetConnection – if you use HttpChannel which is backed by flash.net.URLLoader you will have 10 different calls.

So I can conclude that you should not be worried that you have too many HTTP requests (listed as the first optimization by Yahoo -check this link) when using remoting.