A CDI Extension that helps Axon Framework and CDI integration. You only need to @Produces some required instances and annotate them with @Autoconfigure, in order to get Axon Framework up and running in a CDI environment.
- Write your command handlers, event handlers, sagas and aggregate roots.
- Write producer methods for CommandBus, EventBus, EventStore and SagaRepository.
- Annotate producer methods whith @AutoConfigure
- Optionally you can write producer for Snapshotter and SnapshotterTrigger
- An instance of EventSourcingRepository for every aggregate root
- An instance of SagaManager
- Every command handler registered with command bus
- Every event listenerr registered with event bus
- Every saga registered with saga manager
- If you don't provide a SagaFactory, a CdiSagaFactory will be used
- If a SnapshotterTrigger is provided, it will be registered with repositories
- If a Snapshotter is provided, aggregate factories will be registered with snapshotter
You can checkout the Quickstart project for a full working example.
Annotate your command bus, event bus and snapshotter producers with @AutoConfigure
. Aggregate roots and sagas don't need to be annotated.
As result you get:
- An AggregateRepository for every aggregate root created, configured with EventStore, SnapshotterTrigger, ConflictResolver and registered with event bus
- Aggregate roots registered with command bus
- Event handlers registered with event bus
- Command handlers registered with command bus
- Aggregate factories registered with snapshotter
- SagaManager created, configured with AnnotatedSaga and registered with event bus
- A CDI capable SagaFactory created
There are available two annotations that allow you to customize configuration: @AggregateConfiguration
and @SagaConfiguration
.
Both work thanks to memes, but...
A meme is a type (interface type is recommended, but it can be a class) which is annotated with cdi qualifiers. The "meme" concept is introducted to bypass some limitation of annotation declarations. For example, if we have the qualifier @MyAwesomeQualifier, a meme can be decalred as
@MyAwesomeQualifier
public class interface MyAwesomeQualifierMeme {}
Meme allows CDI extension to capture the exact qualifier instances. Memes can declare qualifiers as complex as you need
@MyAwesomeQualifier @MyWonderfulQualifier(value="Yes! I'm the best")
public class interface MyAwesomeQualifierMeme {}
Suppose you have in your application a single command bus, but two event bus, one to dispatch and store events in a database for the aggregate A, and one to store events in a different database for the aggregate B. Then we need at least a qualifier annotation in order to distinguish the event bus configurations. How do you tell Axon that aggregate A should use event bus A and aggregate B the event bus B? By configuring axon-cdi as follow:
CDIConfiguration.java
@Produces
@AutoConfigure
@ApplicationScoped
public CommandBus commandBus() {...}
@Produces
@AutoConfigure
@ApplicationScoped
public EventBus eventBusAggregateA() {...}
@Produces
@AutoConfigure
@AggregateBQualifier
@ApplicationScoped
public EventBus eventBusAggregateB() {...}
@Produces
@ApplicationScoped
public EventStore eventStoreAggregateA() {...}
@Produces
@AggregateBQualifier
@ApplicationScoped
public EventStore eventStoreAggregateB() {...}
AggregateBQualifierMeme.java
@AggregateBQualifier
public interface AggregateBQualifierMeme {}
AggregateA.java
public class AggregateA extends AbstractAnnotatedAggregateRoot<String>
AggregateB.java
@AggregateConfiguration(
value = AggregateBQualifierMeme.class,
commandBus = DefaultQualifierMeme.class,
snapshotter = DefaultQualifierMeme.class,
snapshotterTrigger = DefaultQualifierMeme.class
)
public class AggregateB extends AbstractAnnotatedAggregateRoot<String>
In this way you tell axon-cdi to register the AggregateB with:
- Event bus qualified with @AggregateBQualifier
- EventStore qualified with @AggregateBQualifier
- ConflictResolver qualified with @AggregateBQualifier
- CommandBus with no qualifier
- Snapshotter with no qualifier
- SnapshotterTrigger with no qualifier
NB. CDI specification states that beans with no qualifiers are implicitly qualified with @Default (in addition to @Any)
In order to make code cleaner, stereotypes are supported so you can annotate you aggregate root with @AggregateBStereotype declared as follow
@AggregateConfiguration(
value = AggregateBQualifierMeme.class,
commandBus = DefaultQualifierMeme.class,
snapshotter = DefaultQualifierMeme.class,
snapshotterTrigger = DefaultQualifierMeme.class
)
@Stereotype
@Retention(RUNTIME)
@Target(TYPE)
public @interface AggregateBStereotype {
and your AggregateB
@AggregateBStereotype
public class AggregateB extends AbstractAnnotatedAggregateRoot<String>
All you need to do is to add the Bintray jcenter repository in the maven pom.xml
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>bintray</name>
<url>http://jcenter.bintray.com</url>
</repository>
</repositories>
and declare the dependency
<dependency>
<groupId>it.kamaladafrica</groupId>
<artifactId>axon-cdi</artifactId>
<version>2.0</version>
</dependency>
Here are some ways for you to contribute:
- Create GitHub tickets for bugs or new features and comment on the ones that you are interested in.
- GitHub is for social coding: if you want to write code, we encourage contributions through pull requests from forks of this repository. If you want to contribute code this way, please reference a GitHub ticket as well covering the specific issue you are addressing.