はじめに
Axon Framework(以降、Axonと記述)では、イベントデータを永続化する際、デフォルトではXMLにSerializeされます。
XMLの代わりにJSONでSerializeする方法を確認しました。
なお、確認する際に使用したアプリケーションについては、以下の記事でセットアップしたものを使用しているので、詳細はそちらをご参照ください
デフォルトの状態
デフォルトでは、domain_event_entry
テーブルのmeta_data
とpayload
のカラムには、XMLでSerializeされた値が保存されました。
<meta-data>
<entry>
<string>traceId</string>
<string>3ca00886-597e-455d-b0cf-172a288a9e1f</string>
</entry>
<entry>
<string>correlationId</string>
<string>3ca00886-597e-455d-b0cf-172a288a9e1f</string>
</entry>
</meta-data>
<org.example.axonkafkatrial.producer.service.DocCreated>
<docId>cb7234ff-e787-40f7-acdf-163f7630b20f</docId>
<body>test</body>
</org.example.axonkafkatrial.producer.service.DocCreated>
また、Kafkaにイベントデータを送信する場合、Kafkaメッセージのvalueも上記のpayload
と同じXMLとなっていました。
JSONでSerializeするように変更
application.ymlにSerializerの設定を追加します。
axon:
axonserver:
enabled: false
kafka:
bootstrap-servers: localhost:9094
# 以下を追加
serializer:
events: jackson
なお、JSONへの変換にはjacksonを使用しますが、jacksonについては、上述のセットアップの記事内で、APIリクエストのJSONパースのために、以下の依存を追加済の状態です。
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.1")
これで、domain_event_entry
テーブルのmeta_data
とpayload
のカラムの値が、以下のようなJSONになりました。
{
"traceId": "6baee93e-80c1-414b-8f7e-92c0f4744cb4",
"correlationId": "6baee93e-80c1-414b-8f7e-92c0f4744cb4"
}
{
"docId": "020081d9-8915-4608-8749-6f8d7bd1eb2e",
"body": "test"
}
Kafkaに送信されたメッセージのvalueもJSONになりました。
Serializerの適用範囲
Axonのドキュメントの以下を見ると、serilalizerで設定する項目として、general
、events
、messages
の3種類があるようです
# Possible values for these keys are `default`, `xstream`, `java`, and `jackson`.
axon:
serializer:
general:
events:
messages:
試しに、以下のようにapplication.ymlの設定を変えてみました。
axon:
axonserver:
enabled: false
kafka:
bootstrap-servers: localhost:9094
serializer:
# events: jackson
general: jackson # eventsでなくgeneralに変えてみる
axon:
axonserver:
enabled: false
kafka:
bootstrap-servers: localhost:9094
serializer:
# events: jackson
# general: jackson
messages: jackson # messagesに変えてみる
結果として、どの設定でも、domain_event_entry
テーブルおよびKafkaメッセージの値は、同様にJSONになりました。
そこで、改めてドキュメントをよく読んでみます。
Axon uses the
XStreamSerializer
by default, which uses XStream to serialize into and deserialize from XML.
デフォルトだとXStreamSerializer
が使われてXMLになるのは、確認したとおりです。
Additionally, Axon provides the
JacksonSerializer
. ThisSerializer
implementation uses Jackson to serialize objects into and deserialize from JSON.
JacksonSerializer
を指定すればJSONになります。これも確認したとおりです。
You may also implement your own serializer simply by creating a class that implements
Serializer
and setting it within Axon’s configuration for the desired infrastructure components.
また、独自のSerializerも作成可能なようなので、例えばKafka連携するうえでAvroを使いたい等であれば、自分で実装することになりそうです。
- The Event
Serializer
is in charge of (de)serializing event message payload and metadata. Events are typically stored in an event store for a long period of time. This is the main driver for choosing the event serializer implementation.- The Message
Serializer
is in charge of (de)serializing the command and query message payload and metadata (used in a distributed application setup). Messages are shared between nodes and typically need to be interoperable and/or compact. Take this into account when choosing the message serializer implementation.- The default
Serializer
is in charge of (de)serializing the remainder, being the messages (except the payload and metadata), tokens, snapshots, deadlines and sagas. These objects are generally not shared between different applications, and most of these classes aren’t expected to have some of the getters and setters that are, for example, typically required by Jackson based serializers. For example, aQueryMessage
consists of a payload andResponseType
, which will respectively be (de)serialized using themessage
and thedefault
serializer, the query request and response payload will be (de)serialized using themessage
serializer. A flexible, general-purpose serializer like XStream is ideal for this purpose.
Serializerには、Event用、Message用、default用の3種類あり、それぞれのSerializerは以下で使用されるようです。
- Event用:イベントデータのmeta_dataとpayload
- Message用:commandとquery
- default用:その他のmessageや、token、snapshots、deadlines、sagas
Spring Bootのappication.ymlに設定する値とは微妙にキーワード表記が異なりますが、以下の対応関係になると推測します。
- events:Event用
- messages:Message用
- general:default用
There is an implicit ordering between the configurable serializer. If no event
Serializer
is configured, the event de-/serialization will be performed by the messageSerializer
. In turn, if no messageSerializer
is configured, the defaultSerializer
will take that role.
Serializerの利用には優先順位があるようです。
イベントデータのmeta_dataとpayloadは
-
events: jackson
ならJSONになる -
events
の設定がなくてもmessages: jackson
ならJSONになる -
messages
の設定がなくてもgeneral: jackson
ならJSONになる
ということなのかと思います。
今回の目的である、イベントデータをJSONでSerializeするためだけであれば、events: jackson
を設定すればよい、ということになりそうです。
他のデータもJSONにしたい、データごとにSerialize方法を使い分けたい、という場合には、general、messagesに変更したり併用することになると思われます。
まとめ
Spring Bootを使用している場合は、application.ymlでaxon.serializer
の設定を行うことでJSONでSerializeするように変更できました。
axon.serializer
の設定においては、指定したSerializerを適用したいデータの種類に応じて、events
、messages
、general
の3種類を使い分けたり併用する必要があることがわかりました。