Skip to content

Commit

Permalink
Merge pull request AxonIQ#156 from AxonIQ/framework-4.4-update
Browse files Browse the repository at this point in the history
Axon Framework 4.4 new features
  • Loading branch information
smcvb authored Aug 6, 2020
2 parents 2efb9d4 + 5ad4d86 commit 2f43d8d
Show file tree
Hide file tree
Showing 21 changed files with 598 additions and 264 deletions.
3 changes: 1 addition & 2 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* [Anatomy of a Message](axon-framework/messaging-concepts/anatomy-message.md)
* [Message Intercepting](axon-framework/messaging-concepts/message-intercepting.md)
* [Supported Parameters for Annotated Handlers](axon-framework/messaging-concepts/supported-parameters-annotated-handlers.md)
* [Exception Handling](axon-framework/messaging-concepts/exception-handling.md)
* [Unit of Work](axon-framework/messaging-concepts/unit-of-work.md)
* [Commands](axon-framework/axon-framework-commands/README.md)
* [Modeling](axon-framework/axon-framework-commands/modeling/README.md)
Expand All @@ -39,7 +40,6 @@
* [Command Handlers](axon-framework/axon-framework-commands/command-handlers.md)
* [Implementations](axon-framework/axon-framework-commands/implementations.md)
* [Configuration](axon-framework/axon-framework-commands/configuration.md)
* [Exception Handling](axon-framework/axon-framework-commands/exception-handling.md)
* [Events](axon-framework/events/README.md)
* [Event Dispatchers](axon-framework/events/event-dispatchers.md)
* [Event Handlers](axon-framework/events/event-handlers.md)
Expand All @@ -53,7 +53,6 @@
* [Query Handlers](axon-framework/queries/query-handlers.md)
* [Implementations](axon-framework/queries/implementations.md)
* [Configuration](axon-framework/queries/configuration.md)
* [Exception Handling](axon-framework/queries/exception-handling.md)
* [Sagas](axon-framework/sagas/README.md)
* [Implementation](axon-framework/sagas/implementation.md)
* [Associations](axon-framework/sagas/associations.md)
Expand Down
3 changes: 1 addition & 2 deletions axon-framework/axon-framework-commands/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ A summary of the various sub-sections is given below.
| Sub-Section | Purpose |
| :--- | :--- |
| [Modeling](modeling/) | Axon Framework provided components to address Aggregate Modeling concerns |
| [Command Dispatchers ](command-dispatchers.md)/ [Command Handlers](command-handlers.md) | Functional Development concerns for Command Messages using the Axon Framework |
| [Command Dispatchers](command-dispatchers.md)/ [Command Handlers](command-handlers.md) | Functional Development concerns for Command Messages using the Axon Framework |
| [Implementations](implementations.md) | Non-Functional Development concerns for Command Messages using the Axon Framework |
| [Configuration](configuration.md) | Configuration concerns for Command Messages using the Axon Framework |
| [Exception Handling](exception-handling.md) | Exception Handling concerns for Command Messages using the Axon Framework |

This guide is complemented by a video tutorial which gives a practical demonstration of the concepts explained in this section. The tutorial is available at -> [Axon Coding Tutorial - Command Messages](https://www.youtube.com/watch?v=7oy4w5THFEU&feature=youtu.be)

3 changes: 2 additions & 1 deletion axon-framework/axon-framework-commands/command-handlers.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,9 @@ public class GiftCard {
As is shown above, the `@CreationPolicy` annotation requires stating the `AggregateCreationPolicy`. This enumeration has the following options available:

* `ALWAYS` - A creation policy of "always" will expect to instantiate the aggregate.

This effectively works like a command handler annotated constructor.
Without defining a return type, the aggregate identifier used during the creation will be returned.
Through this approach, it is possible to return other results next to the aggregate identifier.

* `CREATE_IF_MISSING` - A creation policy of "create if missing" can either create an aggregate or act on an existing instance.

Expand Down
7 changes: 7 additions & 0 deletions axon-framework/axon-framework-commands/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ The following is needed to register a `GiftCardCommandHandler` as being a Comman
Configurer axonConfigurer = DefaultConfigurer.defaultConfiguration()
.registerCommandHandler(conf -> new GiftCardCommandHandler());
```

Or, a more general approach to registering _all_ types of message handlers in a component can be used:

```java
Configurer axonConfigurer = DefaultConfigurer.defaultConfiguration()
.registerMessageHandler(conf -> new GiftCardCommandHandler());
```
{% endtab %}

{% tab title="Spring Boot AutoConfiguration" %}
Expand Down
12 changes: 0 additions & 12 deletions axon-framework/axon-framework-commands/exception-handling.md

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public class GiftCard {
There are a couple of noteworthy concepts from the given code snippets, marked with numbered Java comments referring to the following bullets:

1. The `@AggregateIdentifier` is the external reference point to into the `GiftCard` Aggregate.

This field is a hard requirement, as without it Axon will not know to which Aggregate a given Command is targeted.
Note that this annotation can be placed on a field and a method.

2. A `@CommandHandler` annotated constructor, or differently put the 'command handling constructor'.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,18 @@ public class GiftCardTransaction {
Entities are, just like the aggregate root, simple objects, as is shown with the new `GiftCardTransaction` entity. The snippet above shows two important concepts of multi-entity aggregates:

1. The field that declares the child entity/entities must be annotated with `@AggregateMember`.

This annotation tells Axon that the annotated field contains a class that should be inspected for message handlers.

This example shows the annotation on an implementation of `Iterable`, but it can also be placed on a single Object or a `Map`.

In the latter case, the values of the `Map` are expected to contain the entities, while the key contains a value that is used as their reference.
Note that this annotation can be placed on a field and a method.

2. The `@EntityId` annotation specifying the identifying field of an Entity.

Required to be able to route a command \(or [event](multi-entity-aggregates.md#event-sourcing-handlers-in-entities)\) message to the correct entity instance.

The property on the payload that will be used to find the entity that the message should be routed to, defaults to the name of the `@EntityId` annotated field.

For example, when annotating the field `transactionId`, the command must define a property with that same name, which means either a `transactionId` or a `getTransactionId()` method must be present.

If the name of the field and the routing property differ, you may provide a value explicitly using `@EntityId(routingKey = "customRoutingProperty")`.

This annotation is **mandatory** on the Entity implementation if it will be part of a `Collection` or `Map` of child entities.
Note that this annotation can be placed on a field and a method.

> **Defining the Entity type**
>
Expand Down
45 changes: 36 additions & 9 deletions axon-framework/deadlines/event-schedulers.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,52 @@

This section will proceed with a suggested course of action when utilizing the `EventScheduler` for dealing with deadlines.

To help understand this better lets take the scenario of a saga. It is easy to make a saga take action when something happens. After all, there is an event to notify the saga. But what if you want your saga to do something when _nothing_ happens? That's what deadlines are used for. For invoices, that is typically several weeks, whereas the confirmation of a credit card payment should occur within a few seconds.
To help understand this better lets take the scenario of a saga:
It is easy to make a saga take action when something happens.
After all, there is an event to notify the saga. But what if you want your saga to do something when _nothing_ happens?
That's what deadlines are used for.
For invoices, that is typically several weeks, whereas the confirmation of a credit card payment should occur within a few seconds.

## Scheduled Events as Deadlines

In Axon, you can use an `EventScheduler` to schedule an event for publication. In the example of an invoice, you would expect the invoice to be paid within thirty days. A saga would, after sending the `CreateInvoiceCommand`, schedule an `InvoicePaymentDeadlineExpiredEvent` to be published in 30 days. The `EventScheduler` returns a `ScheduleToken` after scheduling an event. This token can be used to cancel the schedule, for example when a payment of an Invoice has been received.

Axon provides two `EventScheduler` implementations: a pure Java one and one using Quartz 2 as a backing scheduling mechanism.

The pure-Java implementation of the `EventScheduler` uses a `ScheduledExecutorService` to schedule event publication. Although the timing of this scheduler is very reliable, it is a pure in-memory implementation. Once the JVM is shut down, all schedules are lost. This makes this implementation unsuitable for long-term schedules.
Axon provides three `EventScheduler` implementations:
1. Pure Java
2. [Quartz](http://www.quartz-scheduler.org/) based
3. [Axon Server](../../axon-server/introduction.md) based

The pure-Java implementation of the `EventScheduler` uses a `ScheduledExecutorService` to schedule event publication.
Although the timing of this scheduler is very reliable, it is a pure in-memory implementation.
Once the JVM is shut down, all schedules are lost.
This makes this implementation unsuitable for long-term schedules.
The `SimpleEventScheduler` needs to be configured with an `EventBus` and a `SchedulingExecutorService` \(see the static methods on the `java.util.concurrent.Executors` class for helper methods\).

The `QuartzEventScheduler` is a more reliable and enterprise-worthy implementation. Using Quartz as underlying scheduling mechanism, it provides more powerful features, such as persistence, clustering and misfire management. This means event publication is guaranteed. It might be a little late, but it will be published.
The `QuartzEventScheduler` is a more reliable and enterprise-worthy implementation.
Using Quartz as underlying scheduling mechanism, it provides more powerful features, such as persistence, clustering and misfire management.
This means event publication is guaranteed. It might be a little late, but it will be published.
It needs to be configured with a Quartz `Scheduler` and an `EventBus`.
Optionally, you may set the name of the group that Quartz jobs are scheduled in, which defaults to `"AxonFramework-Events"`.

The `AxonServerEventScheduler` uses Axon Server to schedule events for publication.
As such, it is a *hard requirement* to use Axon Server as your Event Store solution to utilize this event scheduler.
Just as the `QuartzEventScheduler`, the `AxonServerEventScheduler` is a reliable and enterprise-worthy implementation of the `EventScheduler` interface.
Creating a `AxonServerEventScheduler` can be done through its builder, whose sole requirement is the `AxonServerConnectionManager`.

It needs to be configured with a Quartz `Scheduler` and an `EventBus`. Optionally, you may set the name of the group that Quartz jobs are scheduled in, which defaults to `"AxonFramework-Events"`.
It is important to note that both the `QuartzEventScheduler` and `AxonServerEventScheduler` should use the [event `Serializer`](../events/event-serialization.md#event-serialization) to serialize and deserialize the scheduled event.
If the `Serializer` used by the scheduler does not align with the `Seralizer` used by the event store, exceptional scenarios should be expected.
The Quartz implementation's `Serializer` can be set by defining a different `EventJobDataBinder`, whereas the Axon Server implementation allows defining the used `Serializer` directly through the builder.

One or more components will be listening for scheduled Events. These components might rely on a Transaction being bound to the thread that invokes them. Scheduled events are published by threads managed by the `EventScheduler`. To manage transactions on these threads, you can configure a `TransactionManager` or a `UnitOfWorkFactory` that creates a transaction bound unit of work.
One or more components will be listening for scheduled Events.
These components might rely on a transaction bound to the thread that invokes them.
Scheduled events are published by threads managed by the `EventScheduler`.
To manage transactions on these threads, you can configure a `TransactionManager` or a `UnitOfWorkFactory` that creates a transaction bound unit of work.

> **Note**
> **Spring Configuration**
>
> Spring users can use the `QuartzEventSchedulerFactoryBean` or `SimpleEventSchedulerFactoryBean` for easier configuration.
> It allows you to set the `PlatformTransactionManager` directly.
>
> Spring users can use the `QuartzEventSchedulerFactoryBean` or `SimpleEventSchedulerFactoryBean` for easier configuration. It allows you to set the `PlatformTransactionManager` directly.
> Spring Boot users which rely on Axon Server do not have to define anything.
> The auto configuration will automatically create a `AxonServerEventScheduler` for them.
2 changes: 1 addition & 1 deletion axon-framework/events/event-handlers.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Axon provides out-of-the-box support for the following parameter types:
* Parameters annotated with `@MetaDataValue` will resolve to the metadata value with the key as indicated on the annotation. If `required` is `false` \(default\), `null` is passed when the metadata value is not present. If `required` is `true`, the resolver will not match and prevent the method from being invoked when the metadata value is not present.
* Parameters of type `MetaData` will have the entire `MetaData` of an `EventMessage` injected.
* Parameters annotated with `@Timestamp` and of type `java.time.Instant` \(or `java.time.temporal.Temporal`\) will resolve to the timestamp of the `EventMessage`. This is the time at which the event was generated.
* Parameters annotated with `@SequenceNumber` and of type `java.lang.Long` or `long` will resolve to the `sequenceNumber` of a `DomainEventMessage`. This provides the order in which the event was generated \(within the scope of the aggregate it originated from\).
* Parameters annotated with `@SequenceNumber` and of type `java.lang.Long` or `long` will resolve to the `sequenceNumber` of a `DomainEventMessage`. This provides the order in which the event was generated \(within the scope of the aggregate it originated from\). It is important to note that `DomainEventMessage` **can only** originate from an Aggregate. Event which thus have been published directly on the `EventBus`/`EventGateway` are _not_ implementations of the `DomainEventMessage` and as such will not resolve a sequence number.
* Parameters assignable to message will have the entire `EventMessage` injected \(if the message is assignable to that parameter\). If the first parameter is of type message, it effectively matches an event of any type, even if generic parameters would suggest otherwise. Due to type erasure, Axon cannot detect what parameter is expected. In such case, it is best to declare a parameter of the payload type, followed by a parameter of type message.
* Parameters of type `TrackingToken` will have the current `TrackingToken` related to the processed Event injected.
* When using Spring and the Axon Configuration is activated \(either by including the Axon Spring Boot Starter module\), any other parameters will resolve to autowired beans, if exactly one injectable candidate is available in the application context. This allows you to inject resources directly into `@EventHandler` annotated methods.
Expand Down
Loading

0 comments on commit 2f43d8d

Please sign in to comment.