Skip to content

Commit 3d5fa98

Browse files
committed
initial contribution using avro serializer
1 parent 84c172c commit 3d5fa98

27 files changed

+472
-143
lines changed

.java-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
21

pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<module>multitenancy</module>
2020
<module>reset-handler</module>
2121
<module>saga</module>
22+
<module>serialization-avro</module>
2223
<module>sequencing-policy</module>
2324
<module>set-based-validation</module>
2425
<module>set-based-validation-actor-model</module>
@@ -36,6 +37,7 @@
3637
<kotlin.compiler.jvmTarget>17</kotlin.compiler.jvmTarget>
3738
<kotlin.version>2.1.10</kotlin.version>
3839
<kotlin.maven.version>2.1.10</kotlin.maven.version>
40+
<maven.compiler.source>17</maven.compiler.source>
3941
<maven.compiler.target>17</maven.compiler.target>
4042
<!-- Axon -->
4143
<axon-bom.version>4.10.4</axon-bom.version>
@@ -182,6 +184,7 @@
182184
<configuration>
183185
<source>17</source>
184186
<target>17</target>
187+
<parameters>true</parameters>
185188
</configuration>
186189
</plugin>
187190
<plugin>

serialization-avro/.docker/config/axonserver.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
axoniq:
22
axonserver:
3-
name: axon-avro-server
3+
name: axonserver-serialization-avro
44
hostname: localhost
55
standalone: true
66
accesscontrol:

serialization-avro/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.docker
2+
!.docker/config
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
version: '3.3'
21
services:
32
axonserver:
43
image: axoniq/axonserver
5-
hostname: axonserver
4+
container_name: axonserver-serialization-avro
65
ports:
76
- '8024:8024'
87
- '8124:8124'
8+
volumes:
9+
- .docker/config:/axonserver/config:ro
10+
- .docker/data:/axonserver/data
11+
- .docker/events:/axonserver/events
12+
- .docker/log:/axonserver/log
13+
- .docker/plugins:/axonserver/plugins

serialization-avro/pom.xml

Lines changed: 141 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,107 @@
99
<version>0.0.2-SNAPSHOT</version>
1010
</parent>
1111

12-
<artifactId>snapshots</artifactId>
12+
<artifactId>serialization-avro</artifactId>
1313

14-
<name>Snapshotting</name>
15-
<description>Module explaining how to enable Snapshotting for Aggregates</description>
14+
<name>Serialization Avro</name>
15+
<description>Module demonstrating usage of Apache Avro as serialization format for messages and events</description>
16+
17+
<properties>
18+
<!-- FIXME: upgrade top level and remove here -->
19+
<axon.version>4.11.0-SNAPSHOT</axon.version>
20+
<avro.version>1.12.0</avro.version>
21+
</properties>
1622

1723
<dependencies>
1824
<!-- Axon -->
25+
<dependency>
26+
<groupId>org.axonframework</groupId>
27+
<artifactId>axon-spring</artifactId>
28+
<version>${axon.version}</version>
29+
</dependency>
30+
<dependency>
31+
<groupId>org.axonframework</groupId>
32+
<artifactId>axon-configuration</artifactId>
33+
<version>${axon.version}</version>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.axonframework</groupId>
37+
<artifactId>axon-modelling</artifactId>
38+
<version>${axon.version}</version>
39+
</dependency>
40+
<dependency>
41+
<groupId>org.axonframework</groupId>
42+
<artifactId>axon-eventsourcing</artifactId>
43+
<version>${axon.version}</version>
44+
</dependency>
1945
<dependency>
2046
<groupId>org.axonframework</groupId>
2147
<artifactId>axon-spring-boot-starter</artifactId>
48+
<version>${axon.version}</version>
49+
</dependency>
50+
<dependency>
51+
<groupId>org.axonframework</groupId>
52+
<artifactId>axon-server-connector</artifactId>
53+
<version>${axon.version}</version>
54+
</dependency>
55+
<dependency>
56+
<groupId>org.axonframework</groupId>
57+
<artifactId>axon-messaging</artifactId>
58+
<version>${axon.version}</version>
59+
</dependency>
60+
<dependency>
61+
<groupId>org.axonframework</groupId>
62+
<artifactId>axon-spring-boot-autoconfigure</artifactId>
63+
<version>${axon.version}</version>
2264
</dependency>
65+
66+
<!-- Apache Avro -->
67+
<dependency>
68+
<groupId>org.apache.avro</groupId>
69+
<artifactId>avro</artifactId>
70+
<version>${avro.version}</version>
71+
</dependency>
72+
73+
<!-- Jackson -->
74+
<dependency>
75+
<groupId>com.fasterxml.jackson.core</groupId>
76+
<artifactId>jackson-annotations</artifactId>
77+
</dependency>
78+
<dependency>
79+
<groupId>com.fasterxml.jackson.core</groupId>
80+
<artifactId>jackson-databind</artifactId>
81+
</dependency>
82+
<dependency>
83+
<groupId>com.fasterxml.jackson.datatype</groupId>
84+
<artifactId>jackson-datatype-jsr310</artifactId>
85+
</dependency>
86+
<dependency>
87+
<groupId>com.fasterxml.jackson.datatype</groupId>
88+
<artifactId>jackson-datatype-jdk8</artifactId>
89+
</dependency>
90+
<dependency>
91+
<groupId>com.fasterxml.jackson.dataformat</groupId>
92+
<artifactId>jackson-dataformat-yaml</artifactId>
93+
</dependency>
94+
<dependency>
95+
<groupId>com.fasterxml.jackson.dataformat</groupId>
96+
<artifactId>jackson-dataformat-cbor</artifactId>
97+
</dependency>
98+
<dependency>
99+
<groupId>com.fasterxml.jackson.module</groupId>
100+
<artifactId>jackson-module-kotlin</artifactId>
101+
</dependency>
102+
103+
23104
<!-- Spring -->
24105
<dependency>
25106
<groupId>org.springframework.boot</groupId>
26107
<artifactId>spring-boot-starter-web</artifactId>
27108
</dependency>
28109
<dependency>
29110
<groupId>org.springframework.boot</groupId>
30-
<artifactId>spring-boot-starter-webflux</artifactId>
31-
<scope>test</scope>
111+
<artifactId>spring-boot-docker-compose</artifactId>
112+
<version>${spring-boot.version}</version>
32113
</dependency>
33114
<!-- Testing -->
34115
<dependency>
@@ -42,4 +123,59 @@
42123
<scope>test</scope>
43124
</dependency>
44125
</dependencies>
126+
127+
<build>
128+
<pluginManagement>
129+
<plugins>
130+
<plugin>
131+
<groupId>org.codehaus.mojo</groupId>
132+
<artifactId>build-helper-maven-plugin</artifactId>
133+
<version>3.6.0</version>
134+
<executions>
135+
<execution>
136+
<id>add-source</id>
137+
<phase>generate-sources</phase>
138+
<goals>
139+
<goal>add-source</goal>
140+
</goals>
141+
<configuration>
142+
<sources>
143+
<source>${project.build.directory}/generated-sources/avro</source>
144+
</sources>
145+
</configuration>
146+
</execution>
147+
</executions>
148+
</plugin>
149+
<plugin>
150+
<groupId>org.apache.avro</groupId>
151+
<artifactId>avro-maven-plugin</artifactId>
152+
<version>${avro.version}</version>
153+
<executions>
154+
<execution>
155+
<id>generate-avro-classes</id>
156+
<phase>generate-sources</phase>
157+
<goals>
158+
<goal>schema</goal>
159+
</goals>
160+
<configuration>
161+
<sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
162+
<outputDirectory>${project.build.directory}/generated-sources/avro/</outputDirectory>
163+
<stringType>String</stringType>
164+
</configuration>
165+
</execution>
166+
</executions>
167+
</plugin>
168+
</plugins>
169+
</pluginManagement>
170+
<plugins>
171+
<plugin>
172+
<groupId>org.apache.avro</groupId>
173+
<artifactId>avro-maven-plugin</artifactId>
174+
</plugin>
175+
<plugin>
176+
<groupId>org.codehaus.mojo</groupId>
177+
<artifactId>build-helper-maven-plugin</artifactId>
178+
</plugin>
179+
</plugins>
180+
</build>
45181
</project>

serialization-avro/requests.http

Lines changed: 101 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,124 @@
11
### Create a new GiftCard with initial amount of 50. Response will contain the GiftCard (aggregate)\
22
### which will be used for later requests
33

4-
POST http://localhost:8080/giftcard
4+
POST http://localhost:8282/giftcard
55
Content-Type: application/json
66

77
{
88
"amount": 50
99
}
1010

11+
> {%
12+
13+
const expected = {
14+
status: 200,
15+
contentType: "text/plain;charset=UTF-8"
16+
};
17+
18+
client.test("Request executed with correct HTTP status", function () {
19+
client.assert(response.status === expected.status, `Response status is not ${expected.status}, but ${response.status}`);
20+
});
21+
client.test("Content-Type is correct", () => {
22+
const contentType = response.headers.valueOf("content-type");
23+
client.assert(contentType === expected.contentType, `Response Content-Type is not ${expected.contentType}, but ${contentType}`);
24+
client.global.set("cardId", response.body);
25+
});
26+
27+
%}
28+
1129
### Try to create a GiftCard with invalid (negative) amount. Will not work and will cause a domain exception.
1230

13-
POST http://localhost:8080/giftcard
31+
POST http://localhost:8282/giftcard
1432
Content-Type: application/json
1533

1634
{
1735
"amount": -5
1836
}
1937

20-
### Redeem amount of a given GiftCard. Domain exceptions can be caused by either redeeming more than the GiftCard
21-
### currently has, or by sending negative amount.
22-
### Infrastructure type error can be caused by referencing non existing GiftCard (by ID)
23-
### Change UUID to one returned by working POST (create GiftCard) call
38+
> {%
39+
40+
const expected = {
41+
status: 400,
42+
contentType: "text/plain;charset=UTF-8"
43+
};
44+
45+
client.test("Request executed with correct HTTP status", function () {
46+
client.assert(response.status === expected.status, `Response status is not ${expected.status}, but ${response.status}`);
47+
});
48+
client.test("Content-Type is correct", () => {
49+
const contentType = response.headers.valueOf("content-type");
50+
client.assert(contentType === expected.contentType, `Response Content-Type is not ${expected.contentType}, but ${contentType}`);
51+
});
2452

25-
PUT http://localhost:8080/giftcard/d8961637-2825-4b1b-ab14-f2a63d9ab1b5
53+
%}
54+
55+
### Redeem amount of a given GiftCard.
56+
# Domain exceptions can be caused by either redeeming more than the GiftCard currently has, or by sending negative amount.
57+
# Infrastructure type error can be caused by referencing non existing GiftCard (by ID)
58+
59+
PUT http://localhost:8282/giftcard/{{cardId}}
2660
Content-Type: application/json
2761

2862
{
2963
"amount": 1
3064
}
65+
66+
> {%
67+
68+
const expected = {
69+
status: 200,
70+
contentType: "text/plain;charset=UTF-8"
71+
};
72+
73+
client.test("Request executed with correct HTTP status", function () {
74+
client.assert(response.status === expected.status, `Response status is not ${expected.status}, but ${response.status}`);
75+
});
76+
client.test("Content-Type is correct", () => {
77+
const contentType = response.headers.valueOf("content-type");
78+
client.assert(contentType === expected.contentType, `Response Content-Type is not ${expected.contentType}, but ${contentType}`);
79+
});
80+
81+
%}
82+
83+
### Retrieve all cards
84+
85+
GET http://localhost:8282/inventory
86+
Accept: application/json
87+
88+
> {%
89+
90+
const expected = {
91+
status: 200,
92+
contentType: "application/json"
93+
};
94+
95+
client.test("Request executed with correct HTTP status", function () {
96+
client.assert(response.status === expected.status, `Response status is not ${expected.status}, but ${response.status}`);
97+
});
98+
client.test("Content-Type is correct", () => {
99+
const contentType = response.headers.valueOf("content-type");
100+
client.assert(contentType === expected.contentType, `Response Content-Type is not ${expected.contentType}, but ${contentType}`);
101+
});
102+
103+
%}
104+
105+
### Retrieve card by id
106+
107+
GET http://localhost:8282/inventory/{{cardId}}
108+
Accept: application/json
109+
110+
> {%
111+
112+
const expected = {
113+
status: 200,
114+
contentType: "application/json"
115+
};
116+
117+
client.test("Request executed with correct HTTP status", function () {
118+
client.assert(response.status === expected.status, `Response status is not ${expected.status}, but ${response.status}`);
119+
});
120+
client.test("Content-Type is correct", () => {
121+
const contentType = response.headers.valueOf("content-type");
122+
client.assert(contentType === expected.contentType, `Response Content-Type is not ${expected.contentType}, but ${contentType}`);
123+
});
124+
%}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"type": "record",
3+
"namespace": "io.axoniq.dev.samples.serializationavro.api",
4+
"name": "IssueCardCommand",
5+
"doc": "Issues a new gift card.",
6+
"revision": "1",
7+
"javaAnnotation": "org.axonframework.serialization.Revision(\"1\")",
8+
"fields": [
9+
{
10+
"name": "id",
11+
"type": "string",
12+
"javaAnnotation": "org.axonframework.modelling.command.TargetAggregateIdentifier"
13+
},
14+
{
15+
"name": "amount",
16+
"type": "int"
17+
}
18+
]
19+
}

serialization-avro/src/main/avro/giftcard.command.RedeemCard.avsc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
{
22
"type": "record",
33
"namespace": "io.axoniq.dev.samples.serializationavro.api",
4-
"name": "IssueCardCommand",
5-
"doc": "Issues a new gift card.",
4+
"name": "RedeemCardCommand",
5+
"doc": "Redeems existing gift card.",
66
"revision": "1",
7+
"javaAnnotation": "org.axonframework.serialization.Revision(\"1\")",
78
"fields": [
89
{
910
"name": "id",
10-
"type": "string"
11+
"type": "string",
12+
"javaAnnotation": "org.axonframework.modelling.command.TargetAggregateIdentifier"
1113
},
1214
{
1315
"name": "amount",

0 commit comments

Comments
 (0)