BlazeDSの拡張ポイント -自由な型変換-


あまり書いている人も見かけないのでBlazeDSの拡張ポイントについて少し書いてみる。
S2Flex2のころは結構好き勝手に型変換のConverterみたいなのを差し込めたので
それがBlazeDSでも出来るかどうかが気になるところ。


結論から言えば、できるみたい。


まず設定例。services-config.xmlのpropertiesタグを使って各エンドポイントごとに設定するみたい。
設定項目とかのドキュメントが軽く調べただけだと見つからなかったので、ソースみた。
どこで設定項目を抽出しているかというと、flex..messaging.endpoints.endpoints.AbstractEndpointのinitializeメソッド。
(jarとしては、flex-messaging-core.jarかな)
ふむふむ、propertiesタグの中にserializationタグを作って、その中にtype-marshallerというところに
クラスをFQDNで書けとの仰せ。
#ちなみに ってのもあったみたいだけどもう使えないみたい。

設定はこんな感じになる。

		<channel-definition id="my-amf"
			class="mx.messaging.channels.AMFChannel">
			<endpoint
				uri="http://{server.name}:{server.port}/{context.root}/messagebroker/amf"
				class="flex.messaging.endpoints.AMFEndpoint">
			</endpoint>
			<properties>
					<serialization>
						<type-marshaller>TypeMarshallerの実装クラスを書く</type-marshaller>
					</serialization>
				<polling-enabled>false</polling-enabled>
			</properties>
		</channel-definition>


TypeMarshallerはflex.messaging.io.TypeMarshallerインタフェースのこと。
こいつがASとJavaの型変換の入り口の模様。
で、継承階層はこうなってる。

TypeMarshaller
+ASTranslator
+Java15TypeMarshaller


Java5以降なら、もちろんJava15TypeMarshallerを継承して作るがよろし。
で、実際にあとはTypeMarshaller.convertメソッド内で型をみて適切にDecoderを呼び出してる。
DecoderはActionScriptDecoderの子供のクラスで、DecoderFactoryにデフォルトのやつが
設定されてる。

public class DecoderFactory
{
    private static final NativeDecoder nativeDecoder = new NativeDecoder();

    // Special null transform, always returns null
    private static final NullDecoder nullDecoder = new NullDecoder();

    // Simple types (do not have the concept of a creating a placeholder or 'shell')
    private static final NumberDecoder numberDecoder = new NumberDecoder();
    private static final StringDecoder stringDecoder = new StringDecoder();
    private static final BooleanDecoder booleanDecoder = new BooleanDecoder();
    private static final CharacterDecoder characterDecoder = new CharacterDecoder();

    // Historically dates are simple types, but they are now considered complex
    // via AMF 3 (though they can not have empty placeholders or 'shells')
    private static final DateDecoder dateDecoder = new DateDecoder();
    private static final CalendarDecoder calendarDecoder = new CalendarDecoder();

    // Complex types (can also be used to create empty placeholders to be populated at decode time)
    private static final ArrayDecoder arrayDecoder = new ArrayDecoder();
    private static final MapDecoder mapDecoder = new MapDecoder();
    private static final CollectionDecoder collectionDecoder = new CollectionDecoder();
    private static final TypedObjectDecoder typedObjectDecoder = new TypedObjectDecoder();

    // If we require references to be tracked and restored, we use deep, recursive decoders
    // however these are very expensive in terms of processing time
    private static final ArrayDecoder deepArrayDecoder = new ReferenceAwareArrayDecoder();
    private static final MapDecoder deepMapDecoder = new ReferenceAwareMapDecoder();
    private static final CollectionDecoder deepCollectionDecoder = new ReferenceAwareCollectionDecoder();
    private static final TypedObjectDecoder deepTypedObjectDecoder = new ReferenceAwareTypedObjectDecoder();


自前TypeMarshallerで入り口をフックして、その後自前Decoderを作って親クラスのDecoderよりも先に
チェックすれば、型マッピングできるっぽい。