Настраиваемый расклад с Java на Flex через BlazeDS - PullRequest
6 голосов
/ 29 октября 2010

Моя команда вместе с BlazeDS создает тестовое Flex-приложение на базе сервера на базе Spring.

Мы выполняем довольно много вычислений дат, поэтому мы широко используем Joda Time в коде и в нашей модели предметной области.

Сейчас мы пытаемся выяснить, как мы можем продолжать использовать Joda Time в наших DTO, которые отправляются назад и вперед с помощью интерфейса Flex через BlazeDS.

Наша цель - использовать тип данных Actionscript 3 Date на стороне Flex и сопоставить его с используемыми нами типами Joda time DateTime, LocalDate и LocalTime на стороне Java.

Мы можем решить проблему преобразования типа ActionScript 3 Date при вызове Java с маршаллером нестандартного типа, подключенным к BlazeDS, но это, похоже, вызывается только для направления Flex-> Java / BlazeDS, а не для Java / BlazeDS-> направление Flex.

Сейчас я смотрю на пользовательские PropertyProxy реализации для BlazeDS, но это тоже не выглядит правильным.

Другая идея состояла в том, чтобы реализовать Externalizable в наших Java DTO, но это кажется слишком большой работой, особенно когда я смотрю на конкурента BlaiteDS GraniteDS, и это показывает включение поддержки Joda Time в их документацию с помощью простого конвертера типов. !

Любые идеи приветствуются.

Ответы [ 3 ]

15 голосов
/ 01 ноября 2010

ОК - я нашел ответ самостоятельно. Это включало написание моего собственного класса конечной точки AMF + связанные классы сериализации. Должен сказать, что парни из http://flexblog.faratasystems.com были отличным источником вдохновения для взлома BlazeDS.

Этот код действительно должен быть включен в сам BlazeDS или в какой-либо проект расширения с открытым исходным кодом - это так просто.

Определение канала

    <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

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

    }

Пользовательский сериализатор

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

Пользовательская обработка 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);
    }
}

Пользовательская обработка 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();
}   
}

Пользовательский маршаллер для 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);
}
}
1 голос
/ 01 июля 2011

Для приложений Java, использующих проект интеграции Spring-BlazeDS от SpringSource, есть гораздо более простой способ справиться с этим:

  • Напишите реализацию GenericConverter, которая обрабатывает отображение ReadableDateTime в / из java.util.Date.

  • Создайте подкласс класса AbstractAmfConversionServiceConfigProcessor и переопределите configureConverters, добавив реализацию вашего конвертера в реестр.

  • Обновите конфигурацию Spring, создав экземпляр вашего ConfigProcessor и подключив его:

XML:

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

Подробнее здесь:

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

0 голосов
/ 29 октября 2010

Пробовали ли вы использовать собственный подход маршаллеров, описанный в этом блоге:

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

...