Archive for the ‘Java’ Category

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.

Java exceptions and Flex

I’ve seen some articles on this subject but I have not found one dealing with all cases (webservices, BlazeDS, BlazeDS and Spring, data management). Also the approach for BlazeDS is different than the one used with Spring/BlazeDS integration, and this thing can be a little bit confusing for a beginner.

Let’s assume that you have a layer of services that should be invoked from your Flex application. You can expose these services as web services or as remote methods. Or you can use data management. The Java methods may throw errors and you want to display them in the Flex application.

For simplicity I will use a very short method as an example. The method signature is :

public String returnResults() throws DatabaseDownException;

There are four main use cases:

a)You have to write a webservice to return the result as XML. For example:

<?xml version="1.0" encoding="UTF-8"?>
<data>
<result>
</result>
</data>

In this case you will need to enhance your XML to add a structure for keeping error messages – like this:

<?xml version="1.0" encoding="UTF-8"?>
<data>
<result>
</result>
<error>
</error>
</data>

When building the XML the <error> body is going to envelope the exception message. Of course more information can be added, including exception type, severity, and so on. The same approach should be used also when working with SOAP services

b)You plan to use BlazeDS and Java remoting

In this case things are going to be easier,  because BlazeDS is able to automatically serialize the thrown exception and you can find the serialized exception in the FaultEvent object. Assume that you have the Java exception declared below. It extends the RuntimeException and it has a getter method for a custom field.

public class DatabaseDownException extends RuntimeException{
private String customField;
public String getCustomField(){
return customField;
}
}

The Flex code declares a remote object and registers a handler (which is also included) for failure.

<mx:RemoteObject id="test" destination="testDestination" result="resultHandler(event)" fault="faultHandler(event)"/>
private function faultHandler(event:FaultEvent):void{
var exception:Object = event.fault.rootCause;
Alert.show(exception.cause);
Alert.show(exception.localizedMessage);
Alert.show(exception.message);
Alert.show(exception.customField);
}

There are four fields in the serialized exception. The first three are inherited from the Throwable object, the last one is declared in your exception. It is interesting to note that you need not have a pair of set/get function in order to have your property serialized. The Throwable object is the only object in which  it is enough to have get methods in order to serialize the values (you can take a look at flex.messaging.io.ThrowableProxy to check that).

The only drawback is that you are working with untyped objects..if you don’t like that you can throw instead instances of flex.messaging.MessageException. This Java class is part of the BlazeDS and it will be deserialized using the class mx.messaging.messages.ErrorMessage (obtained from the event.message property).

You can add your custom data in the MessageException class using the extended property. For example:

MessageException messageException = new MessageException();
HashMap<String,String> map = new HashMap<String,String>();
map.put("clientName", "JOHN");
map.put("clientSurname", "MASTER");
messageException.setExtendedData(map);
messageException.setCode("ACCOUNT_DISABLED");
throw messageException;

And on the Flex side:

private function faultHandler(event:FaultEvent):void{
var errorMessage:ErrorMessage = event.message as ErrorMessage;
trace(errorMessage.extendedData.clientName);
trace(errorMessage.extendedData.clientSurname);
trace(errorMessage.faultCode);
}

You probably do not want to have an explicit dependence between your service layer and the BlazeDS libraries, so in this case you should build a delegate on top of it, which will also act as an exception translator.

c)Using Spring BlazeDS Integration

You have several benefits when using Spring BlazeDS integration, and if your middle tier is already using Spring it’s a must. The benefit related to exception handling is the exception translator mechanism. This translator will catch all the exceptions thrown from the services invoked from Flex and you can translate them into something more meaningful for the client.

First you need to declare the exception translator:

<bean id="exceptionTranslator" class="com.test.exception.ExceptionTranslatorImpl" />
<flex:message-broker services-config-path="/WEB-INF/flex/services-config.xml">
........
<flex:exception-translator ref="exceptionTranslator" />
</flex:message-broker>

The exception translator is below:

public class ExceptionTranslatorImpl implements ExceptionTranslator{
//handles all
public boolean handles(final Class<?> clazz){
return true;
}
public MessageException translate(final Throwable throwable){
if (throwable instanceof DatabaseDownException){
MessageException exception = new MessageException();
exception.setCode("FATAL_DB_DOWN");
return exception;
}
if ...........//check another things
}
}

Note that in the current version of Spring/BlazeDS integration it is mandatory to have an exception translator, otherwise the original error is going to be swallowed and you will receive some generic error.

d)Using data management

The same approach from point c) applies here. Basically your assembler – which is going to invoke some service to obtain/create data – will take care of translating the exceptions into something meaningful for the client. I wrote some time ago a short post about that here.

Note: this article was translated also in Belorussian (thanks Patricia), you can find it here.

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.

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);

  }
}

Java serialization versus AMF/Hessian serialization

Update: I added also compression. The result is the same, Hessian is the clear winner. Not quite sure why deflate takes so much time when applied to AMF output, but I was able to reproduce this result with different inputs.

Two months ago I was asked by several guys from JUG Gothenburg to do a comparison between AMF and classic Java serialization. I was not able to answer at the moment, because I had never thought about it nor had I performed any tests. Now I extended my mini-benchmark from my previous post and I also serialized the objects using Java serialization. The results are below, and you can see from the results that the size of compressed data is much larger for Java serialization (I used Java 1.6). Without looking at the code from ObjectOutputStream I assume that there are no techniques like detecting duplicate values and writing references or writing small number on fewer bytes.

My suggestion is to use AMF/Hessian rather than Java serialization whenever you can – you will be able to save a lot of bandwidth.

The result table is below, and you can download the source code from here.

Avg Time (microseconds) Data size (kbytes)
AMF3 9945 28
Hessian 4675 29
Java serialization 6400 60
AMF3+Deflate 34479 14.5
Hessian+Deflate 6076 14
Java serialization+Deflate 19193 22
XML 22064 158
XML+Deflate 27336 18

Using AMF and Web Services

You can pack and send your data using AMF even if you don’t use the remoting services. In this post I will show several ways to do that using HTTP services. Why would you want to do that ? There are organizations or departments that expose only REST and SOAP services and it can be hard to persuade them to add the remoting services. In this case, when using web services, you have two solutions: you can create XML from your object graph (and for that you’ll have to write extra code) and apply a compression algorithm on it, or you can apply AMF serialization on the object graph, add the resulting byte code in the service body, and deserialize the AMF format on the client side.

Below is a sample how to do that. First, the Java code on the server:

    public void service(ServletRequest arg0, ServletResponse response)
            throws ServletException, IOException {

        Product product = new Product("name","description");        

        SerializationContext context = new SerializationContext();
        context.instantiateTypes = true;

        ByteArrayOutputStream baos = new ByteArrayOutputStream(64*1024);
        Amf3Output amf3Output = new Amf3Output(context);
        amf3Output.setOutputStream(baos);

        amf3Output.writeObject(product);
        amf3Output.flush();

        response.getOutputStream().write(baos.toByteArray());
    }

On the client you have two options. The easier one is to use an URLLoader.

        private function loaderCompleteHandler(event:Event):void {
            //rebuild the object                            
            var product:Product = loader.data.readObject();
        }

        function sendData(event:Event){
            var request:URLRequest = new URLRequest("/test/loaddata/");
            loader = new URLLoader();
            loader.dataFormat = URLLoaderDataFormat.BINARY;
            loader.load(request);
            loader.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
            loader.addEventListener(Event.COMPLETE, loaderCompleteHandler);
        }

If you want to use an HTTPService you have a problem, because by default it does not handle binary data. However it’s easy to extend the class and to add binary support.

    public class HTTPServiceExt extends HTTPService{
        protected static var binaryChannel:Channel;
        protected static var binaryChannelSet:ChannelSet;
        public var binaryData:Boolean;

        public function HTTPServiceExt(){
        }
        override public function send(parameters:Object = null):AsyncToken{
            if (( useProxy == false ) && (binaryData)){
                if ( binaryChannelSet == null ){
                    var dcs:ChannelSet = new ChannelSet();
                    binaryChannel =
                    new DirectHTTPBinaryChannel("directhttpbinarychannel");
                    dcs.addChannel(binaryChannel);
                    channelSet = dcs;
                    binaryChannelSet = dcs;
                }
                else if ( channelSet != binaryChannelSet ){
                    channelSet = binaryChannelSet;
                }
            }
            return super.send(parameters);
        }
    }

The class DirectHTTPBinaryChannel is taken from Anirudh Sasikumar’s blog. It extends DirectHTTPChannel and it configures the internal URLoader to work with binary data.

Now you have an HTTPService class that knows how to receive binary data also. In order to use it you have to add the binaryData parameter:

    function resultCall(event:ResultEvent):void{
       var product:Product = event.result.readObject();
    }
    <local:HTTPServiceExt binaryData="true" id="srv"
        url="/test/loaddata/"
        result="resultCall(event)"
        fault="faultCall(event)"/>

That’s all. You can refine the code; for example you may want to create only one URL for all the resources and to pass parameters, or you can use SOAP services and add the AMF binary format as an attachment.

I also uploaded a Flex/WTP project here containing all the source code.

BlazeDS bootcamp – resources

Adobe Developer Day is over and I made an archive containing a project with samples related to remoting and messaging (BlazeDS bootcamp). You can download it from this link.

Taking into account that we received good feedback will start again a new session of bootcamps.

Using Hessian and Flash player

I created my first application using Hessian last week and I thought I’d write about the main differences between using AMF and the Hessian protocol for remoting. You can also download my sample project here – it’s the same Hello World sample with PureMVC from a previous post modified to work with Hessian.

In comparing AMF and Hessian I’ll start with the server side.

a)Server side libraries and configuration

If you plan to use AMF you will need to use BlazeDS, LiveCycle Data Services  or another product (GraniteDS, WebOrb etc). If you only need remoting you can strip out most of the jars, but you will still need more than 800 kbytes. For Hessian you need only one jar – about 300 kbytes. Also for AMF you will need to declare a servlet (MessageBroker) in the web.xml file.

b)Exposing your Java methods

When using BlazeDS any object with a public constructor can be a remoting point, and you will have to write an entry in a configuration file:

<destination id=”HelloService”>
<channels>
<channel ref=”my-amf”/>
</channels>
<properties>
<source>
org.puremvc.server.java.helloworld.services.HelloService
</source>
<scope>application</scope>
</properties>
<adapter ref=”java-object” />
</destination>

You will also have to define the channel – to specify how you intend to communicate between the client and server. For remoting the AMF channel is the preferred solution

<channel-definition id=”my-amf” class=”mx.messaging.channels.AMFChannel”>
<endpoint url=

http://{server.name}:{server.port}/hellopuremvc_blaze/messagebroker/amf

class=”flex.messaging.endpoints.AMFEndpoint”/>
</channel-definition>

For Hessian you have to write a class extending HessianServlet containing all the methods which can be invoked. After that you add this servlet in web.xml

<servlet>
<servlet-name>model</servlet-name>
<servlet-class>HessianSerializeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>model</servlet-name>
<url-pattern>/model/*</url-pattern>
</servlet-mapping>

Another difference is that in the Hessian case all the Java objects used as value objects should implement the Serializable interface

c)Client side invocation

For AMF you do not need any external libraries because the serialization and deserialization is done natively in Flash Player. However for Hessian you will need a library and latest version (3.2) is about 500 kbytes.

From a programming point of view is the biggest difference is that for Hessian case you will need to have the AS class and the Java class in the same location (package +name) if you want to have automatic serialization/deserialization. You can use the “RemoteClass” tag also for Hessian, but it works only in one direction (from Flex to Java), at least this is what I noticed. Otherwise the call looks the same:

AMF:

service = new RemoteObject();
service.destination = “HelloService”;
service.requestTimeout = 3;
var call:Object = service.sayHello(name);

Hessian

service = new HessianService();
service.destination = “/hellopuremvc_hessian/services/”;
service.requestTimeout = 3;
var call:Object = service.sayHello(name);

The destination definition is a little bit tricky – for AMF it should be the same as the one defined in services.xml, for Hessian it should be the same as the servlet mapping from web.xml

<servlet>
<servlet-name>services</servlet-name>
<servlet-class>org.puremvc.server.java.helloworld.servlet.HelloServiceServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>services</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>

d)Performance and other considerations

As I wrote in a previous post Hessian serialization from the server side is faster than AMF one, and the compressed data almost has the same size. However on the client side the AMF is the clear winner because of the native support provided by Flash Player. Also the Hessian library for the client is quite big.

Below are the links describing the mapping between ActionScript and Java types:
AMF
Hessian