ファイヤープロジェクト
カスタムシリアライザとカスタムデシリアライザの作成(AXIS 1.2)
2005-10-11T23:30+09:00   matsu
シリアライザとデシリアライザは,自作することもできるらしいので,試しに作ってみた.
シリアライズ,デシリアライズ処理は,大抵の場合はBeanSerializerとBeanDeserializerで事足りると思う. またAXISでは,他にBase64Serializer,Base64DeserializerやHexSerializer,HexDeserializerなどのシリアライザ,デシリアライザもあり,これらもBean...と同様の手順で使用可能である. こうした状況なので,稀なケースかもしれないが,場合によっては独自のシリアライズ,デシリアライズを行うカスタムシリアライザとカスタムデシリアライザを作成することもできる. カスタムシリアライザとカスタムデシリアライザを使用するための作業には以下がある.
  • カスタムシリアライザの作成
  • カスタムデシリアライザの作成
  • カスタムシリアライザファクトリの作成
  • カスタムデシリアライザファクトリの作成
  • クライアントの作成
  • デプロイ
本頁ではこれらの作業を通してカスタムシリアライザとカスタムデシリアライザのサンプルを作成してみた.
以下にシリアライズ,デシリアライズする対象となるクラスHogeのコードを示す.
Beanなので,BeanSerializer,Deserializerでも処理できるのだが,今回は要件として,HogeのメンバsecretValueの値はそのままの形では送受信してはならないというものを想定した. そこで,secretValueは,シリアライズの際には暗号化し,デシリアライズの際には復号するよう(※),カスタムシリアライザとデシリアライザを作成する.
※ 暗号化,復号はここでの本題ではないので,文字列を単に逆順にするだけ.
以下にサンプルのカスタムシリアライザ,HogeSerializerを示す.
上記は,BeanSerializerのソースやAXISのJavaDocを参照して,私なりに試行錯誤しつつ作成した. ポイントはどうやら以下のようだ.
javax.xml.rpc.encoding.Serializerとorg.apache.axis.encoding.Serializerを実装する.
どうも両方実装しないとコンパイルが通らないとかClassCastExceptionなどの問題が生じる.
getMechanismTypeメソッドの実装
多分ほとんどorg.apache.axis.Constants.AXIS_SAXを返していればよい.
serializeメソッドの実装
カスタムシリアライザ作成のメイン.
  • シリアライズ対象を表す要素の開始と終了は
    context.startElement(name, attributes);
    
    context.endElement();
    
    を自分で呼び出す.
  • 上記メソッド呼び出しの間に子要素出力処理を記述.
  • 子要素出力処理は,基本的に
    org.apache.axis.encoding.SerializationContext#serializer
    
    の呼び出しに持ち込む. あとはSerializationContextがやってくれる.
  • 上記serializeメソッド呼び出し用のorg.xml.sax.Attributesオブジェクトは,新規に作成. Serializer#serializeの引数のものは,シリアライズ対象の要素のものなので,使用しない. また,SerializationContext#serializerがいろいろしてくれるので,作成した新規のAttributesは基本的に空でよい.
とにかくユーティリティであるSerializationContextをうまくつかうことがポイントである. また,writeSchemaメソッドの実装はごまかしている. このメソッドはたぶんWSDL生成の際に使用されると思うのだが,今回は呼び出されないので,これでよい. シリアライザができたら,そのファクトリも作成する.
汎用性あるいは拡張性を考慮した設計らしいが,対象を限定するなら,この程度の実装でよい.
以下にサンプルのカスタムデシリアライザ,HogeDeserializerを示す.
カスタムデシリアライザは
org.apache.axis.encoding.DeserializerImpl
を拡張して実装する. ポイントは以下である.
コールバックメソッドの実装
基本的な仕組みは,SAXを発展させたようなものである. デシリアライズ処理内容に応じて,コールバックを実装する.
メンバvalueの作成
上位は,Deserializerによる処理結果をgetValueを通して出力する. すなわち,各種コールバックは,基本的にメンバvalueを生成,設定,操作してデシリアライズ処理の結果を出力する.
startElement
startElementメソッドは,デシリアライズ対象ノードの開始タグで呼び出される.
onStartChild
onstartchildメソッドは,デシリアライズ対象ノードの子要素の開始タグ毎に呼び出される.
org.apache.axis.encoding.DeserializationContext
SerializationContextと同様,DeserializationContextはデシリアライズ時のユーティリティである. 難しい処理,面倒臭い処理は,こいつが面倒見てくれるので,うまく活用する.
カスタムデシリアライザの作成も,割と苦労した. わからないなりにデプロイして作成したカスタムシリアライザでどんな電文ができるのかを調べながらの作業だった. カスタムシリアライザと同様,カスタムデシリアライザもファクトリを作成する.
以下にサンプルのクライアントを示す.
ポイントは,
	    call.registerTypeMapping(Hoge.class,
				     qn,
				     HogeSerializerFactory.class,
				     HogeDeserializerFactory.class);
における,カスタムシリアライザとカスタムデシリアライザのファクトリ指定である. サーバ側では,wsddを記述する.
シリアライザ,デシリアライザの指定にはtypeMapping要素を記述する.
<typeMapping
    xmlns:axissample="http://www.fireproject.jp/ns/axissample/hoge"
    qname="axissample:hoge"
    languageSpecificType="java:org.fireproject.axissample.Hoge"
    serializer="org.fireproject.axissample.HogeSerializerFactory"
    deserializer="org.fireproject.axissample.HogeDeserializerFactory"
    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
各属性の説明を以下に示す.
qname
デシリアライズ対象の要素のqnqme.
languageSpecificType
シリアライズ対象の言語とクラス. typeMappingは,qnameとlanguageSpecificTypeのマッピングである.
serializerとdeserializer
それぞれのファクトリクラス. シリアライザ,デシリアライザそのものではなく,ファクトリである点に注意.
encodingStyle
よくわからない. 多分
"http://schemas.xmlsoap.org/soap/encoding/"
でよい.
BeanSerializer,BeanDeserializerの場合は,beanMappinng要素の記述であった. これは実は,BeanSerializer,BeanDeserializerの場合のみ使用できる,typeMapping要素の簡略記法らしい.
jwsなので,デプロイ後一度はjwsに要求して,コンパイルしてもらう必要がある.
$> java -jar axissample.jar http://localhost:8180/fireproject/HogeFactory.jws
decrypt [.eulaVterces si sihT]
org.fireproject.axissample.Hoge@1fe88d
  [updated = false; updateMessage = null; secretValue = This is secretValue.; ]
encrypt[This is secretValue.]
decrypt [.eulaVterces si sihT]
org.fireproject.axissample.Hoge@178460d
  [updated = true; updateMessage = HogeFactory updated this hoge.; secretValue = This is secretValue.; ]

$> java -jar axissample.jar http://localhost:8180/fireproject/services/Hoge
decrypt [.eulaVterces si sihT]
org.fireproject.axissample.Hoge@1fe88d
  [updated = false; updateMessage = null; secretValue = This is secretValue.; ]
encrypt[This is secretValue.]
decrypt [.eulaVterces si sihT]
org.fireproject.axissample.Hoge@178460d
  [updated = true; updateMessage = HogeFactory updated this hoge.; secretValue = This is secretValue.; ]
encrypt,decryptメソッドのパラメータから,うまくカスタムシリアライザ,デシリアライザが機能していることが分かる. また,送受信電文では,HogeオブジェクトのsecretValueの値が逆順で記述されていた.
matsu(C)
Since 2002
Mail to matsu