Spring ApplicationEvent Support

Spring Integration provides support for inbound and outbound ApplicationEvents, as defined by the underlying Spring Framework. For more information about Spring’s support for events and listeners, see the Spring Reference Manual.

You need to include this dependency into your project:

Maven
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-event</artifactId>
    <version>5.5.1</version>
</dependency>
Gradle
compile "org.springframework.integration:spring-integration-event:5.5.1"

Receiving Spring Application Events

To receive events and send them to a channel, you can define an instance of Spring Integration’s ApplicationEventListeningMessageProducer. This class is an implementation of Spring’s ApplicationListener interface. By default, it passes all received events as Spring Integration messages. To limit based on the type of event, you can use the 'eventTypes' property to configure the list of event types that you want to receive. If a received event has a Message instance as its 'source', that Message is passed as-is. Otherwise, if a SpEL-based payloadExpression has been provided, that is evaluated against the ApplicationEvent instance. If the event’s source is not a Message instance and no payloadExpression has been provided, the ApplicationEvent itself is passed as the payload.

Starting with version 4.2, the ApplicationEventListeningMessageProducer implements GenericApplicationListener and can be configured to accept not only ApplicationEvent types but any type for treating payload events (which are also supported since Spring Framework 4.2). When the accepted event is an instance of PayloadApplicationEvent, its payload is used for the message to send.

For convenience, namespace support is provided to configure an ApplicationEventListeningMessageProducer with the inbound-channel-adapter element, as the following example shows:

<int-event:inbound-channel-adapter channel="eventChannel"
                                   error-channel="eventErrorChannel"
                                   event-types="example.FooEvent, example.BarEvent, java.util.Date"/>

<int:publish-subscribe-channel id="eventChannel"/>

In the preceding example, all application context events that match one of the types specified by the 'event-types' (optional) attribute are delivered as Spring Integration messages to the message channel named 'eventChannel'. If a downstream component throws an exception, a MessagingException that contains the failed message and exception is sent to the channel named 'eventErrorChannel'. If no error-channel is specified and the downstream channels are synchronous, the exception is propagated to the caller.

Using Java to configure the same adapter:

@Bean
public ApplicationEventListeningMessageProducer eventsAdapter(
            MessageChannel eventChannel, MessageChannel eventErrorChannel) {

    ApplicationEventListeningMessageProducer producer =
        new ApplicationEventListeningMessageProducer();
    producer.setEventTypes(example.FooEvent.class, example.BarEvent.class, java.util.Date.class);
    producer.setOutputChannel(eventChannel);
    producer.setErrorChannel(eventErrorChannel);
    return producer;
}

With the Java DSL:

@Bean
public ApplicationEventListeningMessageProducer eventsAdapter() {

    ApplicationEventListeningMessageProducer producer =
        new ApplicationEventListeningMessageProducer();
    producer.setEventTypes(example.FooEvent.class, example.BarEvent.class, java.util.Date.class);
    return producer;
}

@Bean
public IntegrationFlow eventFlow(ApplicationEventListeningMessageProducer eventsAdapter,
        MessageChannel eventErrorChannel) {

    return IntegrationFlows.from(eventsAdapter, e -> e.errorChannel(eventErrorChannel))
        .handle(...)
        ...
        .get();
}

Sending Spring Application Events

To send Spring ApplicationEvents, create an instance of the ApplicationEventPublishingMessageHandler and register it within an endpoint. This implementation of the MessageHandler interface also implements Spring’s ApplicationEventPublisherAware interface and consequently acts as a bridge between Spring Integration messages and ApplicationEvents.

For convenience, namespace support is provided to configure an ApplicationEventPublishingMessageHandler with the outbound-channel-adapter element, as the following example shows:

<int:channel id="eventChannel"/>

<int-event:outbound-channel-adapter channel="eventChannel"/>

If you use a PollableChannel (such as a QueueChannel), you can also provide a poller child element of the outbound-channel-adapter element. You can also optionally provide a task-executor reference for that poller. The following example demonstrates both:

<int:channel id="eventChannel">
  <int:queue/>
</int:channel>

<int-event:outbound-channel-adapter channel="eventChannel">
  <int:poller max-messages-per-poll="1" task-executor="executor" fixed-rate="100"/>
</int-event:outbound-channel-adapter>

<task:executor id="executor" pool-size="5"/>

In the preceding example, all messages sent to the 'eventChannel' channel are published as ApplicationEvent instances to any relevant ApplicationListener instances that are registered within the same Spring ApplicationContext. If the payload of the message is an ApplicationEvent, it is passed as-is. Otherwise, the message itself is wrapped in a MessagingEvent instance.

Starting with version 4.2, you can configure the ApplicationEventPublishingMessageHandler (<int-event:outbound-channel-adapter>) with the publish-payload boolean attribute to publish to the application context payload as is, instead of wrapping it to a MessagingEvent instance.

To configure the adapter using Java configuration:

@Bean
@ServiceActivator(inputChannel = "eventChannel")
public ApplicationEventPublishingMessageHandler eventHandler() {
    ApplicationEventPublishingMessageHandler handler =
            new ApplicationEventPublishingMessageHandler();
    handler.setPublishPayload(true);
    return handler;
}

With the Java DSL:

@Bean
public ApplicationEventPublishingMessageHandler eventHandler() {
    ApplicationEventPublishingMessageHandler handler =
            new ApplicationEventPublishingMessageHandler();
    handler.setPublishPayload(true);
    return handler;
}

@Bean
// MessageChannel is "eventsFlow.input"
public IntegrationFlow eventsOutFlow(ApplicationEventPublishingMessageHandler eventHandler) {
    return f -> f.handle(eventHandler);
}