This repository has been archived by the owner on Nov 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
59 changed files
with
821 additions
and
319 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
changelog: | ||
sections: | ||
- title: ":rocket: Enhancements & Features" | ||
labels: [ "Type: enhancement", "Type: documentation", "Type: example" ] | ||
- title: ":bug: Bug Fixes" | ||
labels: [ "Type: bug" ] | ||
- title: ":hammer_and_wrench: Chore" | ||
labels: [ "Type: dependencies" ] | ||
issues: | ||
exclude: | ||
labels: [ "Type: question" ] | ||
contributors: | ||
exclude: | ||
names: [ "dependabot[bot]" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Trigger the workflow on milestone events | ||
on: | ||
milestone: | ||
types: [closed] | ||
name: Milestone Closure | ||
jobs: | ||
create-release-notes: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@master | ||
- name: Create Release Notes Markdown | ||
uses: docker://decathlon/release-notes-generator-action:3.1.5 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token | ||
OUTPUT_FOLDER: temp_release_notes | ||
USE_MILESTONE_TITLE: "true" | ||
- name: Get the name of the created Release Notes file and extract Version | ||
run: | | ||
RELEASE_NOTES_FILE=$(ls temp_release_notes/*.md | head -n 1) | ||
echo "RELEASE_NOTES_FILE=$RELEASE_NOTES_FILE" >> $GITHUB_ENV | ||
VERSION=$(echo ${{ github.event.milestone.title }} | cut -d' ' -f2) | ||
echo "VERSION=$VERSION" >> $GITHUB_ENV | ||
- name: Create a Draft Release Notes on GitHub | ||
id: create_release | ||
uses: actions/create-release@v1 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token | ||
with: | ||
tag_name: ${{ env.VERSION }} | ||
release_name: ${{ env.VERSION }} | ||
body_path: ${{ env.RELEASE_NOTES_FILE }} | ||
draft: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,35 @@ | ||
# axon-avro-serializer | ||
|
||
[![incubating](https://img.shields.io/badge/lifecycle-INCUBATING-orange.svg)](https://github.com/holisticon#open-source-lifecycle) | ||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/e5518754d4fd4eea80ef02a95be59486)](https://app.codacy.com/gh/holixon/axon-avro-serializer?utm_source=github.com&utm_medium=referral&utm_content=holixon/axon-avro-serializer&utm_campaign=Badge_Grade_Settings) | ||
[![Build Status](https://github.com/holixon/axon-avro-serializer/workflows/Development%20branches/badge.svg)](https://github.com/holixon/axon-avro-serializer/actions) | ||
[![sponsored](https://img.shields.io/badge/sponsoredBy-Holisticon-RED.svg)](https://holisticon.de/) | ||
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.holixon.axon.avro/axon-avro-serializer/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.holixon.axon.avro/axon-avro-serializer) | ||
[![codecov](https://codecov.io/gh/holixon/axon-avro-serializer/branch/develop/graph/badge.svg?token=ZKDNW1QJ1Y)](https://codecov.io/gh/holixon/axon-avro-serializer) | ||
|
||
__DISCLAIMER__: early draft, heavy development, *everything* might still change | ||
This extension to the [Axon Framework](https://docs.axoniq.io/reference-guide/) aims to provide support for serialization of Axon events | ||
with the [Apache Avro](https://avro.apache.org/docs/current/) data format. | ||
|
||
This extension to the [Axon Framework](https://docs.axoniq.io/reference-guide/) aims to provide support for serialization of Axon messages (commands, events, queries) with the [Apache Avro](https://avro.apache.org/docs/current/) data format. | ||
Avro is a schema-based data format that can be serialized to JSON or byte sequence, which is useful to minimize the disk space needed for | ||
your Axon event store and bandwidth used for transport. Messages can be validated against a schema version and Avro supports schema | ||
evolution by automatically determining [compatibility modes](https://docs.confluent.io/platform/current/schema-registry/avro.html) between | ||
different revisions. | ||
|
||
Avro is a schema-based data format that can be serialized to JSON or byte sequence, which is useful to minimize | ||
the disk space needed for your Axon event store and bandwidth used for transport. | ||
Messages can be validated against a schema version and avro supports schema evolution by automatically determining | ||
[compatibility modes](https://docs.confluent.io/platform/current/schema-registry/avro.html) between different revisions. | ||
Please check our [official documentation](https://www.holixon.io/axon-avro-serializer/snapshot/) for more details. | ||
|
||
see on [component overview](file:/notes/README.md) | ||
|
||
## Links | ||
## Developers | ||
|
||
* [Avro Registry Adapter](https://github.com/holixon/avro-registry-adapter) - used to abstract from concrete schema registry | ||
* <https://hub.docker.com/r/axoniq/axonserver> | ||
* [Jan Galinski](https://github.com/jangalinski) | ||
* [Simon Zambrovski](https://github.com/zambrovski) | ||
|
||
## Notes | ||
## License | ||
|
||
* <https://github.com/sksamuel/avro4k> | ||
* <https://www.baeldung.com/java-apache-avro> | ||
* <https://avro.apache.org/docs/current/gettingstartedjava.html> | ||
* <http://bigdatums.net/2016/01/20/simple-apache-avro-example-using-java/> | ||
* <http://www.soutier.de/blog/2017/03/07/daten-modellieren-avro/> | ||
This library is developed under | ||
|
||
### great | ||
[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://www.holunda.io/camunda-bpm-taskpool/license) | ||
|
||
## Sponsors and Customers | ||
|
||
[![sponsored](https://img.shields.io/badge/sponsoredBy-Holisticon-red.svg)](https://holisticon.de/) | ||
|
||
* <https://blog.cloudera.com/robust-message-serialization-in-apache-kafka-using-apache-avro-part-1/> | ||
* <https://github.com/cloudera/kafka-examples> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
In order to work with the Axon Framework, we need to have Java (or Kotlin) classes representing the events defined in the schema to be | ||
available. This class is generated from the schema using Avro generator. In order to do so, the build environment must have access to the | ||
schema (registry) and use a build system plugin (Maven or Gradle) to generate java/kt source files Please see example in | ||
the [reference guide](../reference/index.md#event-generation) for more details. | ||
|
||
!!! note | ||
The class FQN will suffice to identity the published schema, but for the Axon default upcasters to work, a `@Revision` annotation | ||
on the class file is needed. For this purpose, a special SchemaBasedRevisionResolver is implemented and configured in the Avro serializer. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Apache Avro is a data serialization system based on **schemas**, defined in JSON. A schema is required to write data and to read data. In | ||
particular, this means that Apache Avro is using a so-called schema-first approach. First, a schema is created and distributed, then it is | ||
used to serialize the message and used again to deserialize the message back. | ||
|
||
In general, the presence of the schema is sufficient to read and write data, but for statically-typed languages like Java or Kotlin, it is | ||
common to generate static classes using Avro Code Generator. | ||
|
||
Avro is flexible in where to get this schema from, so we defined | ||
a [Schema Registry API](https://github.com/holixon/avro-registry-adapter/blob/develop/extension/api/src/main/kotlin/AvroSchemaRegistry.kt) | ||
to de-couple the user from the implementation of the schema registry. This allowed us to define multiple interchangeable implementation of | ||
the [registry adapters](../reference/registry-adapters.md). | ||
|
||
The following figure demonstrates this approach: | ||
|
||
![Overview](../assets/img/axon-serializer.png) | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
Based on the business requirements for the events of the bounded context, an Avro Schema definition is created. It describes all properties | ||
of the event and is defined using JSON. | ||
|
||
Most Important: | ||
|
||
* event namespace (in which context is this event relevant? could be context's name prefixed by the domain, | ||
example: `example.bankaccount.event`) | ||
* event name (describing what happened in a simple past tense. Meaningful in context, example: `BankAccountCreated`) | ||
* event revision (when we later modify the event content, which is the revision we relate to, example: `1`) | ||
* event reference identifier (business aggregate identifier this event relates to, example: `bankAccountId`) | ||
|
||
The schema can be identified by the URL of `namespace.name`, which will later also be the FQN of the generated classes, used for handling | ||
the event instances. | ||
|
||
!!! important | ||
We consider that the namespace of the business context and the name of an event should not change over time when they are | ||
modelled properly in advance. So it might be a good option not to force a typical java-package pattern on them, which would require renaming | ||
when refactorings are done. | ||
|
||
The revision should be defined as a metadata of the schema, not a property inside. | ||
|
||
Here is an example: | ||
|
||
```json | ||
{ | ||
"type": "record", | ||
"namespace": "example.bankaccount.event", | ||
"name": "BankAccountCreatedEvent", | ||
"fields": [ | ||
{ | ||
"name": "bankAccountId", | ||
"type": "string" | ||
}, | ||
{ | ||
"name": "initialBalance", | ||
"type": "int" | ||
} | ||
], | ||
"revision": "1" | ||
} | ||
|
||
``` | ||
|
||
For more details, please consult the [Avro Specification](https://avro.apache.org/docs/current/spec.html#schemas). | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Once we are happy with our [schema design](schema-design.md), we publish it to a schema registry. | ||
|
||
* This extension is not enforcing usage of a particular registry but instead provide | ||
flexible [registry adapters](../reference/registry-adapters.md). | ||
* The registry must be available at build and runtime because we need it for code generation and runtime validation/migration. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
**Schema registry** is a central concept introduced to decouple storage and management of schemas from the usage of schemas for | ||
serialization and deserialization. In order to decouple from concrete implementation, we defined an API to work with registries in the | ||
sister project [Avro Registry Adapter](https://github.com/holixon/avro-registry-adapter). There are several registry adapters available, | ||
which can be used in your implementation. Currently, they are: | ||
|
||
* In-Memory registry for a transient registry | ||
* Apicurio Registry Adapter to connect to [apicur.io Registry](https://www.apicur.io/registry/) | ||
|
||
The following registries will be available shortly: | ||
|
||
* JPA registry for storing schemas in RDBMS | ||
* Confluent registry adapter to work with [Confluent Schema Registry](https://docs.confluent.io/platform/current/schema-registry/index.html) | ||
|
||
Using one of those adapters you can reuse the existing registry. Every registry adapter needs its specific configuration to operate | ||
properly. In the [Registry Adapters](../reference/registry-adapters.md) section, the examples of configuration is provided. For more | ||
details, please consult the documentation of the [Avro Registry Adapter](https://github.com/holixon/avro-registry-adapter) project. | ||
|
||
## Registry Performance | ||
|
||
Since the Schema registry is required for any serialization and deserialization process, performance of the schema resolution is vital. To | ||
address this requirement, we provide a mechanism of a **Composite Registry**, effectively building a chain of registries. It might be a good | ||
idea to have an in-memory registry as the main registry used in the application, backed by a remote schema registry connected via selected | ||
registry adapter. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
Upcasting is the process of matching the structure of the event intermediate representation of an event to the target type of the event. It | ||
is required if the structure of the event of the writer side is not matching the structure of the event of the reader side. In general, we | ||
speak about event evolution, which is described in the context of Avro with the concept of Schema Evolution. Luckily, Avro provides a | ||
foundation of detection of schema changes and allows for a classification of those changes - some of those changes are non-breaking and some | ||
are breaking. The task for the upcaster is to overcome the breaking changes. | ||
|
||
In order to upcast a Avro-serialized message, the intermediate representation is constructed. Since it is not easily possible to upcast | ||
binary data directly, we provide a converter of binary data into | ||
a [Generic Record format](https://avro.apache.org/docs/1.7.6/api/java/org/apache/avro/generic/GenericRecord.html) which is essentially | ||
a `Map<String, Object>` structure. An upcaster may modify this map to match the target event type. In addition, it needs to change the | ||
schema information (schema namespace, name, revision) of the `Generic Record` to match the reader schema. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
## Design decisions | ||
|
||
We decided to create a sister project [Avro Registry Adapter](https://github.com/holixon/avro-registry-adapter) which eases the work with | ||
Apache Avro and defines the API and implementations for [Schema Registry](concepts/schema-registry.md). In doing so, we provide a maximum | ||
independence of the serialization process from the used registry. | ||
|
||
The extension itself is implemented in Kotlin only, since we need to work with JVM and Axon Framework and Kotlin is more fun. | ||
|
||
The extension is usable from Kotlin and Java, although the API might have advantages when using Kotlin. | ||
|
||
## References | ||
|
||
There are some resources on the Internet, which might be helpful to understand the design decisions and implementation. Here is a short | ||
collection of links: | ||
|
||
### Notes | ||
|
||
* <https://github.com/sksamuel/avro4k> | ||
* <https://www.baeldung.com/java-apache-avro> | ||
* <https://avro.apache.org/docs/current/gettingstartedjava.html> | ||
* <http://bigdatums.net/2016/01/20/simple-apache-avro-example-using-java/> | ||
* <http://www.soutier.de/blog/2017/03/07/daten-modellieren-avro/> | ||
|
||
### Great to read | ||
|
||
* <https://blog.cloudera.com/robust-message-serialization-in-apache-kafka-using-apache-avro-part-1/> | ||
* <https://github.com/cloudera/kafka-examples> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
Put the serializer library and one of the [registry adapters](reference/registry-adapters.md) on the class path of you project: | ||
|
||
```xml | ||
|
||
<dependency> | ||
<groupId>io.holixon.axon.avro</groupId> | ||
<artifactId>axon-avro-serializer-spring</artifactId> | ||
<version>${axon-avro-serializer.version}</version> | ||
</dependency> | ||
``` | ||
|
||
```xml | ||
|
||
<dependency> | ||
<groupId>io.holixon.avro</groupId> | ||
<artifactId>avro-registry-adapter-apicurio</artifactId> | ||
<version>${avro-registry.version}</version> | ||
</dependency> | ||
``` | ||
|
||
Activate the used registry adapter and the serializer in your configuration: | ||
|
||
```kotlin | ||
@EnableAxonAvroSerializer | ||
class MyConfiguration { | ||
|
||
@Bean | ||
fun avroSchemaRegistry(): AvroSchemaRegistry { | ||
return ... | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
## Why should I use it? | ||
|
||
We believe that serialization of events for messaging and storage purpose is done best | ||
using [Apache Avro](https://avro.apache.org/docs/current/) data serialization system. For this purpose we designed and implemented an **Avro | ||
Serializer** for [Axon Framework](https://docs.axoniq.io/reference-guide/) **to foster** usage of Apache Avro as | ||
a [serialization format for events](https://docs.axoniq.io/reference-guide/axon-framework/events/event-serialization), instead of XML or | ||
JSON. | ||
|
||
### Why? | ||
|
||
* Avro is schema based | ||
* Avro Schema allows detection of incompatibilities during Schema Evolution | ||
* Avro supports binary encoding which saves space | ||
|
||
## Interested? | ||
|
||
You can get more details if you start understanding [Concepts](concepts/index.md). For further details, please check | ||
our [reference guide](reference/index.md). We also provide | ||
some [Examples](https://github.com/holixon/axon-avro-serializer/tree/develop/examples) demonstrating the usage of the extension in a simple | ||
Axon Bank Scenario. | ||
|
||
[![Slack](https://img.shields.io/badge/slack-@holixon/avroserializer-green.svg?logo=slack")](https://holixon.slack.com/messages/avro-serializer/) | ||
[![Github Issues](https://img.shields.io/github/issues/holixon/axon-avro-serializer)](https://github.com/holixon/axon-avro-serializer/issues) | ||
|
||
|
||
|
Oops, something went wrong.