0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Axon FrameworkでイベントデータをJSONでSerializeする [Kotlin,SpringBoot]

Posted at

はじめに

Axon Framework(以降、Axonと記述)では、イベントデータを永続化する際、デフォルトではXMLにSerializeされます。

XMLの代わりにJSONでSerializeする方法を確認しました。

なお、確認する際に使用したアプリケーションについては、以下の記事でセットアップしたものを使用しているので、詳細はそちらをご参照ください

デフォルトの状態

デフォルトでは、domain_event_entryテーブルのmeta_datapayloadのカラムには、XMLでSerializeされた値が保存されました。

meta_data
<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>
payload
<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の設定を追加します。

src/main/resources/application.yml
axon:
  axonserver:
    enabled: false
  kafka:
    bootstrap-servers: localhost:9094
  # 以下を追加
  serializer:
    events: jackson

なお、JSONへの変換にはjacksonを使用しますが、jacksonについては、上述のセットアップの記事内で、APIリクエストのJSONパースのために、以下の依存を追加済の状態です。

build.gradle.kts
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.1")

これで、domain_event_entryテーブルのmeta_datapayloadのカラムの値が、以下のようなJSONになりました。

meta_data
{
  "traceId": "6baee93e-80c1-414b-8f7e-92c0f4744cb4",
  "correlationId": "6baee93e-80c1-414b-8f7e-92c0f4744cb4"
}
payload!
{
  "docId": "020081d9-8915-4608-8749-6f8d7bd1eb2e",
  "body": "test"
}

Kafkaに送信されたメッセージのvalueもJSONになりました。

serialize-to-json.png

Serializerの適用範囲

Axonのドキュメントの以下を見ると、serilalizerで設定する項目として、generaleventsmessagesの3種類があるようです

# Possible values for these keys are `default`, `xstream`, `java`, and `jackson`.
axon:
    serializer:
        general:
        events:
        messages:

試しに、以下のようにapplication.ymlの設定を変えてみました。

src/main/resources/application.yml
axon:
  axonserver:
    enabled: false
  kafka:
    bootstrap-servers: localhost:9094
  serializer:
#    events: jackson
    general: jackson # eventsでなくgeneralに変えてみる
src/main/resources/application.yml
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. This Serializer 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 Serializerand 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, a QueryMessage consists of a payload and ResponseType, which will respectively be (de)serialized using the message and the default serializer, the query request and response payload will be (de)serialized using themessageserializer. 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 message Serializer. In turn, if no message Serializer is configured, the default Serializer will take that role.

Serializerの利用には優先順位があるようです。
イベントデータのmeta_dataとpayloadは

  1. events: jacksonならJSONになる
  2. eventsの設定がなくてもmessages: jacksonならJSONになる
  3. messagesの設定がなくてもgeneral: jacksonならJSONになる

ということなのかと思います。

今回の目的である、イベントデータをJSONでSerializeするためだけであれば、events: jacksonを設定すればよい、ということになりそうです。

他のデータもJSONにしたい、データごとにSerialize方法を使い分けたい、という場合には、general、messagesに変更したり併用することになると思われます。

まとめ

Spring Bootを使用している場合は、application.ymlでaxon.serializerの設定を行うことでJSONでSerializeするように変更できました。

axon.serializerの設定においては、指定したSerializerを適用したいデータの種類に応じて、eventsmessagesgeneralの3種類を使い分けたり併用する必要があることがわかりました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?