I’m a member of Adobe platform evangelism team located in Bucharest, Romania. Before I was software developer for a long time, mostly working on things related to J2EE world. Outside of work I enjoy traveling, going to the gym, reading and watching good movies Cornel is a DZone MVB and is not an employee of DZone and has posted 6 posts at DZone. View Full User Profile

Java exceptions and Flex

05.14.2010
| 13635 views |
  • submit to reddit

I’ve seen some articles about this subject but I have not found one dealing with all the cases (webservices, BlazeDS, BlazeDS and Spring, data management). Also the approach from BlazeDS is different than the one used by 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. We can expose this services as web services or as remote methods. Or we can use data management. The java methods can throw some errors and you want to display them in the Flex application.

For simplicity I will take a very short method. The method signature is :

public String returnResults() throws DatabaseDownException;

Below I’ll write the main use cases:

a)You have to write an webservice to return the result as an xml. Something like:

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

In this case you will need to enhance your xml to add some structures 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, as the exception type, severity etc. 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, BlazeDS is able to serialize automatically the thrown Exception and you can find the serialized exception in the FaultEvent object. Let's assume that we have the Java exception declared below. It is extending 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 ones are inherited from the Throwable object, the last one is declared in our exception. It is interesting to notice that you should not have a pair of set/get function in order to have your property serialized. The Throwable object is the only one where it is enough to have get methods in order to serialize the values (you can take a look in 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. Example of usage:

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

Probably you do not want to have an explicit dependence between your service layer and the BlazeDS libraries, and in this case you should build a delegate on top of it, which will act also 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 exception 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 the point c) applies here. Basically your assembler – which is going to invoke some service to obtain/create data – will take care to translate the exceptions into something meaningful for the client. I wrote some time a short post about that here.

References
Published at DZone with permission of Cornel Creanga, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)