Skip to content

Commit

Permalink
walkthrough documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
JohT committed Dec 18, 2021
1 parent 8578298 commit d13d117
Showing 1 changed file with 56 additions and 2 deletions.
58 changes: 56 additions & 2 deletions showcase-quarkus-eventsourcing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ $GRAALVM_HOME/bin/java -agentlib:native-image-agent=trace-output=native-image/tr

As described in [Using GraalVM native-image-agent][UsingNativeImageAgent] it is very helpful to use integration tests and run them [against the running application][QuarkusIntegrationTestsAgainstRunningApplication], that was started by one of the commands above with the native image agent activated. This is much easier than clicking through the application manually.


## Features
* MicroProfile Standard
* "Reactive" example using server sent events (tested with safari & chrome browser) and axon subscription query
Expand All @@ -76,12 +75,55 @@ As described in [Using GraalVM native-image-agent][UsingNativeImageAgent] it is
* Full-Stack Build configuration including JavaScript Unit Tests with Jasmine, JavaScript minify, ...
* Continuous Integration using [GitHub Actions][GitHubActions] for a fully automated build including Java and JavaScript Unit Tests, Web Packaging, native image and integration-tests.

## Notes
### Notes
* Code comments containing the marker ```Note:``` describes thoughts, background information, documented decisions and hints to problems.
* ```ArchitectureRulesTest``` defines rules to assure low coupling between the business core, axon and microprofile features.
* These rules might seem a bit extreme. Some may even find them to be impractical. After all, this examples shows that it can be done.
* This is just a simple show case, not an full application.

## Walkthrough

### Connecting Context and Dependency Injection (CDI) to AxonFramework

[Axon Framework CDI Support][AxonFrameworkCDI] already provides a CDI integration by providing a [CDI Portable Extension][CDIExtension].
Unfortunately, this doesn't work for Quarkus, since [Quarkus CDI][QuarkusCDI]
only implements a subset of the CDI specification and doesn't support [CDI Portable Extensions][CDIExtension].

#### Bean Discovery

To most important part is the discovery of all building blocks (beans) of AxonFramework. This includes for example finding all aggregates, event handlers, command handlers, query handlers, ...

This is done inside [AxonComponentDiscovery.java](./src/main/java/io/github/joht/showcase/quarkuseventsourcing/messaging/infrastructure/axon/inject/cdi/AxonComponentDiscovery.java), whereas the most important line is probably the following:

```java
Set<Bean<?>> beans = beanManager.getBeans(Object.class, AnnotationLiteralAny.ANY);
```

This line seems to work for pretty any CDI implementation including [Quarkus CDI][QuarkusCDI]
and returns all beans (of any type) that CDI can discover (in respect of its configuration).

#### Axon Configuration

[AxonConfiguration.java](./src/main/java/io/github/joht/showcase/quarkuseventsourcing/messaging/infrastructure/axon/AxonConfiguration.java) takes all discovered beans and registers them accordingly. It also wires up custom settings (e.g. database schema) and global settings (e.g. bean validation).

#### Application startup

Axon configuration is all done the first time it is used. The disadvantage of it is, that the application might benefit from a warm up. The advantage is, that this can be done strongly within CDI standard. Even if `@Observes @Initialized(ApplicationScope.class)` is standard and could be used to call a method on server start, Quarkus would run this e.g. in native mode during build. For details see [Quarkus Application Initialization and Termination][QuarkusLivecycle].

### Connecting JTA Transaction to AxonFramework

[Jakarta Transactions (JTA)][JakartaTransaction] are connected with
[JtaTransactionManager.java](./src/main/java/io/github/joht/showcase/quarkuseventsourcing/messaging/infrastructure/axon/transaction/jta/JtaTransactionManager.java), which is then configured as transaction manager for axon in [AxonConfiguration.java](./src/main/java/io/github/joht/showcase/quarkuseventsourcing/messaging/infrastructure/axon/AxonConfiguration.java).

This is pretty similar to [AxonFramework/cdi JtaTransactionManager.java](https://github.com/AxonFramework/cdi/blob/master/extension/src/main/java/org/axonframework/cdi/transaction/JtaTransactionManager.java).

### Connection JSON Binding to AxonFramework

[JsonbSerializer.java](./src/main/java/io/github/joht/showcase/quarkuseventsourcing/messaging/infrastructure/axon/serializer/jsonb/axon/JsonbSerializer.java) implements [JSON Binding][JSONBinding] as Serializer for AxonFramework. As an alternative, Jackson could also be used with Quarkus and AxonFramework. [JSON Binding][JSONBinding] had be chosen here to be fully compliant to the MicroProfile Standard.

AxonFramework has build-in support for Jackson JSON serializer. Some of its internal serializable data types need to be adapted to be used with [JSON Binding][JSONBinding].
The ones needed here are internally registered in [JsonbAxonAdapterRegister.java](./src/main/java/io/github/joht/showcase/quarkuseventsourcing/messaging/infrastructure/axon/serializer/jsonb/axon/adapter/JsonbAxonAdapterRegister.java). Except for the generic [JsonbMetaDataAdapter.java](./src/main/java/io/github/joht/showcase/quarkuseventsourcing/messaging/infrastructure/axon/serializer/jsonb/axon/adapter/JsonbMetaDataAdapter.java) and [JsonbReplayTokenAdapter.java](./src/main/java/io/github/joht/showcase/quarkuseventsourcing/messaging/infrastructure/axon/serializer/jsonb/axon/adapter/JsonbReplayTokenAdapter.java) they shouldn't be needed any more since [AxonFramework PullRequest #1163](https://github.com/AxonFramework/AxonFramework/pull/1163).

## What is [AxonFramework][AxonFramework]?

> Open source framework for event-driven microservices and domain-driven design
Expand All @@ -105,29 +147,41 @@ For more details please visit [Quarkus][Quarkus].
* [ArchUnit][ArchUnit]
* [Assisted Configuration with Tracing Agent][NativeImageAssistedConfiguration]
* [AxonFramework][AxonFramework]
* [Axon Framework CDI Support][AxonFrameworkCDI]
* [Building a native executable][QuarkusNativeExecutable]
* [CDI Portable Extension][CDIExtension]
* [CDI - Jakarta Contexts and Dependency Injection][CDI]
* [Eclipse MicroProfile][MicroProfile]
* [EqualsVerifier][EqualsVerifier]
* [Flyway Version control for your database][Flyway]
* [GitHub Actions][GitHubActions]
* [GraalVM][GraalVM]
* [Jakarta JSON Binding][JSONBinding]
* [Jakarta Transactions (JTA)][JakartaTransaction]
* [Quarkus][Quarkus]
* [Quarkus Context and Dependency Injection (CDI)][QuarkusCDI]
* [Quarkus Integrationtest - Executing against a running application][QuarkusIntegrationTestsAgainstRunningApplication]
* [Quarkus Application Initialization and Termination][QuarkusLivecycle]
* [Testing all equals and hashCode methods][TestingEqualsHashcode]
* [Using GraalVM native-image-agent when porting a library to Quarkus][UsingNativeImageAgent]

[ArchUnit]: https://www.archunit.org
[AxonFramework]: https://axoniq.io/product-overview/axon-framework
[AxonFrameworkCDI]: https://github.com/AxonFramework/extension-cdi
[CDI]: https://jakarta.ee/specifications/cdi
[CDIExtension]: https://docs.jboss.org/weld/reference/latest/en-US/html/extend.html
[EqualsVerifier]: https://jqno.nl/equalsverifier
[Flyway]: https://flywaydb.org
[GitHubActions]: https://docs.github.com/en/actions
[GraalVM]: https://www.graalvm.org
[JakartaTransaction]: https://jakarta.ee/specifications/transactions/
[JSONBinding]: https://jakarta.ee/specifications/jsonb/2.0/jakarta-jsonb-spec-2.0.html
[MicroProfile]: https://projects.eclipse.org/projects/technology.microprofile
[NativeImageAssistedConfiguration]: https://www.graalvm.org/reference-manual/native-image/Agent
[Quarkus]: https://quarkus.io
[QuarkusCDI]: https://quarkus.io/guides/cdi-reference
[QuarkusNativeExecutable]: https://quarkus.io/guides/building-native-image-guide
[QuarkusIntegrationTestsAgainstRunningApplication]: https://quarkus.io/guides/getting-started-testing#executing-against-a-running-application
[QuarkusLivecycle]: https://quarkus.io/guides/lifecycle
[TestingEqualsHashcode]: https://joht.github.io/johtizen/testing/2020/03/08/test-all-equal-and-hashcode-methods.html
[UsingNativeImageAgent]: https://peter.palaga.org/2021/01/31/using-native-image-agent-when-porting-a-lib-to-quarkus.html

0 comments on commit d13d117

Please sign in to comment.