Custom Marshalling from Java to Flex through BlazeDS

My team combines a Flex application with a conceptual design sitting on a Spring server using BlazeDS.

We spend quite a lot of settlement dates, so we widely use Joda Time throughout the code and in our domain model.

Now we are trying to figure out how we can continue to use Joda Time in our DTOs that are sent back and forth with the Flex interface through BlazeDS.

Our goal is to use the ActionScript 3 Date data type on the Flex side and use this map to use the Joda time DateTime , LocalDate and LocalTime time types on the Java side.

We can solve the ActionScript 3 Date type conversion problem when calling Java with a custom type marshaller connected to BlazeDS, but this seems to be called only for the Flex-> Java / BlazeDS direction, not for the Java / BlazeDS-> Flex direction.

Now I am looking at custom PropertyProxy implementations for BlazeDS, but that is not the case either.

Another idea was to implement Externalizable on our Java DTOs, but that seems like a lot of work, especially when I look at a competitor to BlazeDS GraniteDS and demonstrate connecting Joda Time support in my documentation with a simple type converter

Any ideas appreciated.

+6
java flex actionscript-3 jodatime blazeds
source share
3 answers

OK - I found the answer myself. This has to do with writing my own endpoint class AMF + related serialization classes. I have to say that the guys at http://flexblog.faratasystems.com were a great source of inspiration for hacking BlazeDS.

This code really needs to be included in BlazeDS itself or in an open source project - it's that simple.

Channel definition

  <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="ch.hedgesphere.core.blazeds.endpoint.AMFEndpoint"/> <properties> <serialization> <type-marshaller>ch.hedgesphere.core.blazeds.translator.HedgesphereASTranslator</type-marshaller> </serialization> </properties> </channel-definition> 

AMF User Endpoint

 package ch.hedgesphere.core.blazeds.endpoint; import ch.hedgesphere.core.blazeds.serialization.Serializer; public class AMFEndpoint extends flex.messaging.endpoints.AMFEndpoint { @Override protected String getSerializerClassName() { return Serializer.class.getName(); } } 

Custom serializer

 package ch.hedgesphere.core.blazeds.serialization; import java.io.OutputStream; import flex.messaging.io.MessageIOConstants; import flex.messaging.io.SerializationContext; import flex.messaging.io.amf.AmfMessageSerializer; import flex.messaging.io.amf.AmfTrace; public class Serializer extends AmfMessageSerializer { @Override public void initialize(SerializationContext context, OutputStream out, AmfTrace trace) { amfOut = new AMF0Output(context); amfOut.setOutputStream(out); amfOut.setAvmPlus(version >= MessageIOConstants.AMF3); debugTrace = trace; isDebug = trace != null; amfOut.setDebugTrace(debugTrace); } } 

Custom Processing AMF 0

 package ch.hedgesphere.core.blazeds.serialization; import flex.messaging.io.SerializationContext; public class AMF0Output extends flex.messaging.io.amf.Amf0Output { public AMF0Output(SerializationContext context) { super(context); } @Override protected void createAMF3Output() { avmPlusOutput = new AMF3Output(context); avmPlusOutput.setOutputStream(out); avmPlusOutput.setDebugTrace(trace); } } 

Custom Processing AMF 3

 package ch.hedgesphere.core.blazeds.serialization; import java.io.IOException; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalTime; import flex.messaging.io.SerializationContext; public class AMF3Output extends flex.messaging.io.amf.Amf3Output { public AMF3Output(SerializationContext context) { super(context); } @Override public void writeObject(Object value) throws IOException { if(value instanceof DateTime) { value = convertToDate((DateTime)value); } if(value instanceof LocalDate) { value = convertToDate((LocalDate)value); } if(value instanceof LocalTime) { value = convertToDate((LocalTime)value); } super.writeObject(value); } private Object convertToDate(LocalTime time) { return time.toDateTimeToday().toDate(); } private Object convertToDate(LocalDate date) { return date.toDateMidnight().toDate(); } private Object convertToDate(DateTime dateTime) { return dateTime.toDate(); } } 

Custom Marshaller for Flex-> Java Calling

 package ch.hedgesphere.core.blazeds.translator; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalTime; import flex.messaging.io.amf.translator.ASTranslator; public class HedgesphereASTranslator extends ASTranslator { @SuppressWarnings({"rawtypes"}) @Override public Object convert(Object originalValue, Class type) { if( type.equals(DateTime.class)) { return convertToDateTime(originalValue); } if( type.equals(LocalDate.class)) { return convertToLocalDate(originalValue); } if( type.equals(LocalTime.class)) { return convertToLocalTime(originalValue); } return super.convert(originalValue, type); } private Object convertToLocalTime(Object originalValue) { return originalValue == null ? null : new LocalTime(originalValue); } private Object convertToLocalDate(Object originalValue) { return originalValue == null ? null : new LocalDate(originalValue); } private Object convertToDateTime(Object originalValue) { return originalValue == null ? null : new DateTime(originalValue); } @SuppressWarnings({"rawtypes"}) @Override public Object createInstance(Object source, Class type) { return super.createInstance(source, type); } } 
+15
source share

For Java applications using the Spring -BlazeDS integration project from SpringSource, there is a much simpler way:

  • Write a GenericConverter implementation that handles the mapping of ReadableDateTime to / from java.util.Date.

  • Subclass AbstractAmfConversionServiceConfigProcessor and override configureConverters by adding your converter implementation to the registry.

  • Update your Spring configuration by instantiating your ConfigProcessor and plugging it in:

XML:

 <flex:message-broker> <flex:config-processor ref="customConfigProcessor"/> </flex:message-broker> 

More details here:

http://static.springsource.org/spring-flex/docs/1.5.x/reference/html/index.html#amf-custom-converters

+1
source share

You tried the custom marshaller approach described in this blog:

http://flexblog.faratasystems.com/index.php/custom-type-masrhaller-in-blazeds

0
source share

All Articles