Today, I released the 0.7 version of Axon Framework. A lot has happened since 0.6, and that’s why it took a little longer for this version to come out. This new version is a huge step towards the 1.0, of which the first milestone release should be available before March 2011. All basic building blocks that you need to run a CQRS application have been implemented.
0.7 offers a large number of new features, such as support for Sagas, Event versioning, Spring Namespace Configuration, and many others, which I will describe in more detail further on.
Axon Framework helps build scalable, extensible and maintainable applications by supporting developers apply the Command Query Responsibility Segregation (CQRS) architectural pattern. It does so by providing implementations of the most important building blocks, such as aggregates, repositories and event busses (the dispatching mechanism for events). Furthermore, Axon provides annotation support, which allows you to build aggregates and event listeners without tying your code to Axon specific logic. This allows you to focus on your business logic, instead of the plumbing, and helps to test your code in isolation.
New features and changes
The 0.7 version has a number of large new features as well as some smaller changes, that might affect code based on the 0.6 version.
Support for Event Sourced Aggregates consisting of more than one entity
When domain models become more complex, it is not always feasible to put all event handler methods exclusively inside the aggregate root. Axon now provides the AbstractAnnotatedEntity, which your non-aggregate-root entities can extend. Events are automatically applied to the aggregate as a whole, instead of the aggregate root.
Software changes, and so does the class definition of events you might be using in production. Although the XStream implementation of the EventSerializer offers some flexibility in class definition changes, it doesn’t provide support for more complex structural updates.
You now have the ability to configure EventUpcasters. An EventUpcaster converts the (intermediate form of) events before they are sent to the aggregates. The XStreamEventSerializer supports upcasters using a DOM4J document. This allows you to manipulate the XML Tree XStream generated (in the past) and convert it to the form currently in use.
Custom matchers in test fixtures
Given-when-then tests are a very good way to define test scenarios in functional terms. In practice, however, it is not always possible to fill in the exact expectancies. To allow for a more flexible verification of test outcomes, you can use Hamcrest Matchers in the “then” part.
Easier configuration of building blocks in Spring
Many thanks to Ben Tels, who provided the initial Spring namespace support for Axon. The Axon namespace (http://www.axonframework.org/schema/core) allows you to easily define many of the infrastructure components using simple to use XML tags. If your Spring context file declares the Axon namespace, many IDE’s will provide auto-complete features to make configuration easier than ever.
Other, smaller changes
Besides these major changes, there is a number of smaller changes that are worth mentioning.
Snapshotting configuration is made easier by migration the configuration of snapshot triggering to the repositories, instead of the event store. If you use namespace support, all you need to do is add a <axon:snapshot-trigger> tag inside the repository configuration.
Aggregates no longer rely on a UUID identifier type. Instead, there is an AggregateIdentifier interface, that allows you to choose any type of identifier you wish to use. Two implementations are provided: UUIDAggregateIdentifier, which still uses the UUID in the background, and a StringAggregateIdentifier, which allows any String as identifier.
The JPA Event Store will translate Duplicate Key Violations into ConcurrencyException. The Java Persitence API does not define a special exception for this type op error, so a custom piece of detection code was necessary. It will try to automatically detect your database type and detect the SQL Error codes that represent this type of error.
The API for Command Handler interceptors has changed, making them easier to implement and much more flexible and powerful.
The shape of events has been altered to make a clear distinction of data and meta-data. This makes configuration of auditing and tracing a lot easier.
The use of a UnitOfWork is pushed towards the background. You shouldn’t be bothered anymore with a UnitOfWorkInterceptor and things of the sort. From now on, it just works.
If you have a system in production on the 0.6 version, unfortunately you cannot seamlessly migrate to 0.7. There are a few changes that you’ll have to make to your codebase.
If you have been using
CommandBus.dispatch(command) (which was deprecated in 0.6), beware! That method is still available in 0.7, but with different behavior. This is the fire-and-forget implementation, which means you will not be notified of any failures. Use the other
dispatch() method if the result of command processing is important. Axon provides a number of callback implementations that you might want to use.
The identifier of aggregates has changed from UUID to AggregateIdentifier. Where you previously passed a UUID to an aggregate’s constructor, change that constructor to accept AggregateIdentifier. You can use the UUIDAggregateIdentifier to wrap the UUID in an AggregateIdentifier. The GenericEventSourcingRepository also needs a constructor with the AggregateIdentifier as sole parameter.
Since the definition of events has changed, you need to register an upcaster if you wish to read in old events. The LegacyAxonEventUpcaster converts the old format to the new. Configure this upcaster in your event serializer, and you should be ready to move on.
If you have questions or doubts about migrating or anything else, don’t hesitate to send a message to the Axon mailing list (firstname.lastname@example.org, registration required: www.axonframework.org/group). The community behind Axon is growing, so if I’m not there to answer your question quickly, someone else is likely to be.
If you need hands-on help, don’t hesitate to contact JTeam about support and consulting.
If you want to download the complete package (incl. documentation, sources and dependencies) directly, visit: http://www.jteam.nl/products/axonframework.html.