7. Using Spring

The AxonFramework has many integration points with the Spring Framework. All major building blocks in Axon are Spring configurable. Furthermore, there are some Bean Post Processors that scan the application context for building blocks and automatically wires them.

Axon uses JSR 250 annotations (@PostConstruct and @PreDestroy) to annotate lifecycle methods of some of the building blocks. Spring doesn't always automatically evaluate these annotations. To force Spring to do so, add the <context:annotation-config/> tag to your application context, as shown in the example below:

<beans xmlns="http://www.springframework.org/schema/beans" 
       xmlns:context="http://www.springframework.org/schema/context">

    <context:annotation-config/>

</beans>

7.1. Wiring event handlers

Using the annotated event listeners is very easy when you use Spring. All you need to do is configure the AnnotationEventListenerBeanPostProcessor in your application context. This post processor will discover beans with @EventHandler annotated methods and automatically connect them to the event bus.

<beans xmlns="http://www.springframework.org/schema/beans">

    <bean class="org...AnnotationEventListenerBeanPostProcessor"> (1)
        <property name="eventBus" ref="eventBus"/> (2)
    </bean>

    <bean class="org.axonframework.sample.app.query.AddressTableUpdater"/> (3)

</beans>
1

This bean post processor will scan the application context for beans with an @EventHandler annotated method.

2

The reference to the event bus is optional, if only a single EventBus implementation is configured in the application context. The bean postprocessor will automatically find and wire it. If there is more than one EventBus in the context, you must specify the one to use in the postprocessor.

3

This event listener will be automatically recognized and subscribed to the event bus.

You can also wire event listeners "manually", by explicitly defining them within a AnnotationEventListenerAdapter bean, as shown in the code sample below.

<beans xmlns="http://www.springframework.org/schema/beans">

    <bean class="org.axonframework...annotation.AnnotationEventListenerAdapter"> (1)
        <constructor-arg>
            <bean class="org.axonframework.sample.app.query.AddressTableUpdater"/>
        </constructor-arg>
        <property name="eventBus" ref="eventBus"/> (2)
    </bean>

</beans>
1

The adapter turns any bean with @EventHandler methods into an EventListener

2

You need to explicitly reference the event bus to which you like to register the event listener

[Warning]Warning

Be careful when wiring event listeners "manually" while there is also an AnnotationEventListenerBeanPostProcessor in the application context. This will cause the event listener to be wired twice.

7.2. Wiring the event bus

In a typical Axon application, there is only one event bus. Wiring it is just a matter of creating a bean of a subtype of EventBus. The SimpleEventBus is the provided implementation.

<beans xmlns="http://www.springframework.org/schema/beans">

    <bean id="eventBus" class="org.axonframework.eventhandling.SimpleEventBus"/>

</beans>

7.3. Wiring the command bus

The command bus doesn't take any configuration to use. However, it allows you to configure a number of interceptors that should take action based on each incoming command.

<beans xmlns="http://www.springframework.org/schema/beans">

    <bean id="eventBus" class="org.axonframework.commandhandling.CommandBus">
        <property name="interceptors">
            <list>
                <bean class="org.axonframework...SpringTransactionalInterceptor">
                    <property name="transactionManager" ref="transactionManager"/>
                </bean>
                <bean class="other-interceptors"/>
            </list>
        </property>
    </bean>

</beans>

7.4. Wiring the Repository

Wiring a repository is very similar to any other bean you would use in a Spring application. Axon only provides abstract implementations for repositories, which means you need to extend one of them. See Chapter 5, Repositories and Event Stores for the available implementations.

Repository implementations that do support event sourcing just need the event bus to be configured, as well as any dependencies that your own implementation has.

<bean id="simpleRepository" class="my.package.SimpleRepository">
    <property name="eventBus" ref="eventBus"/>
</bean>

Repositories that support event sourcing will also need an event store, which takes care of the actual storage and retrieval of events. The example below shows a repository configuration of a repository that extends the EventSourcingRepository.

<bean id="contactRepository" class="org.axonframework.sample.app.command.ContactRepository">
    <property name="eventBus" ref="eventBus"/>
    <property name="eventStore" ref="eventStore"/>
</bean>

In many cases, you can use the GenericEventSourcingRepository. Below is an example of XML application context configuration to wire such a repository.

<bean id="myRepository" class="org.axonframework.eventsourcing.GenericEventSourcingRepository">
    <constructor-arg value="fully.qualified.class.Name"/>
    <property name="eventBus" ref="eventBus"/>
    <property name="eventStore" ref="eventStore"/>
</bean>

The repository will delegate the storage of events to the configured eventStore, while these events are dispatched using the provided eventBus.

7.5. Wiring the event store

All event sourcing repositorties need an event store. Wiring the JpaEventStore and the FileSystemEventStore is very similar, but the JpaEventStore needs to run in a Spring managed transaction. Unless you use the SpringTransactionalInterceptor on your command bus, you need to declare the annotation-driven transaction-manager as shown in the sample below.

<bean id="eventStore" class="org.axonframework.eventstore.jpa.JpaEventStore"/>

<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>

<!-- declare transaction manager, data source, EntityManagerFactoryBean, etc -->