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:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-event</artifactId>
<version>5.4.5</version>
</dependency>
compile "org.springframework.integration:spring-integration-event:5.4.5"
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);
}