Marshalling personalizado de Java a Flex a través de BlazeDS
actionscript-3 jodatime (3)
Mi equipo está armando una aplicación Flex de prueba de concepto instalada sobre un servidor basado en Spring utilizando BlazeDS.
Hacemos una gran cantidad de cálculos de fechas, por lo que usamos Joda Time extensamente en todo el código y en nuestro modelo de dominio.
Ahora estamos tratando de descubrir cómo podemos seguir usando Joda Time en nuestros DTOs que se envían de ida y vuelta con la interfaz Flex a través de BlazeDS.
Nuestro objetivo es utilizar el tipo de datos Actionscript 3 Date
en el lado Flex y tener ese mapa para nuestro uso de los tipos LocalTime
LocalDate
, LocalDate
y LocalTime
LocalDate
de Joda time en el lado Java.
Podemos resolver el problema de convertir el tipo de Date
Actionscript 3 al llamar a Java con un contador de referencias personalizadas conectado a BlazeDS, pero parece que solo se invoca para la dirección Flex-> Java / BlazeDS y no para la dirección Java / BlazeDS-> Flex. .
Ahora estoy buscando implementaciones personalizadas de PropertyProxy
para BlazeDS, pero tampoco parece lo correcto.
La otra idea era implementar Externalizable
en nuestros Java DTOs, pero parece demasiado trabajo, especialmente cuando miro al rival GraniteDS de BlazeDS y eso muestra cómo conectar el soporte de Joda Time en su documentación con un convertidor de tipos simple.
Cualquier idea apreciada.
¿Has probado el enfoque personalizado de Marshallers descrito en este blog?
http://flexblog.faratasystems.com/index.php/custom-type-masrhaller-in-blazeds
OK - He encontrado la respuesta por mi cuenta. Esto implicó escribir mi propia clase de punto final AMF + clases de serialización relacionadas. Debo decir que los chicos de http://flexblog.faratasystems.com han sido una gran fuente de inspiración para hackear BlazeDS.
Este código realmente debería ser incorporado en BlazeDS mismo o en algún proyecto de extensión de código abierto, es muy básico.
Definición del canal
<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>
Punto final AMF personalizado
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();
}
}
Serializador personalizado
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);
}
}
Manejo personalizado 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);
}
}
Manejo personalizado de 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 para 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);
}
}
Para las aplicaciones Java que utilizan el proyecto de integración Spring-BlazeDS de SpringSource, hay una manera mucho más simple de manejar esto:
Escriba una implementación de GenericConverter que maneja la asignación de ReadableDateTime a / desde java.util.Date.
Cree una subclase de AbstractAmfConversionServiceConfigProcessor y anule configureConverters, agregando la implementación de su convertidor al registro.
Actualice su configuración de Spring creando una instancia de ConfigProcessor y conectándola:
XML:
<flex:message-broker>
<flex:config-processor ref="customConfigProcessor"/>
</flex:message-broker>
Más información aquí: