@Target(value=TYPE) @Retention(value=RUNTIME) @Documented @Import(value=JmsBootstrapConfiguration.class) public @interface EnableJms
JmsListenerContainerFactory
. To be used on
Configuration
classes as follows:
@Configuration @EnableJms public class AppConfig { @Bean public DefaultJmsListenerContainerFactory myJmsListenerContainerFactory() { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory()); factory.setDestinationResolver(destinationResolver()); factory.setSessionTransacted(true); factory.setConcurrency("5"); return factory; } // other @Bean definitions }The
JmsListenerContainerFactory
is responsible to create the listener container
responsible for a particular endpoint. Typical implementations, as the
DefaultJmsListenerContainerFactory
used in the sample above, provides the necessary configuration options that are supported by
the underlying MessageListenerContainer
.
@EnableJms
enables detection of JmsListener
annotations on any
Spring-managed bean in the container. For example, given a class MyService
:
package com.acme.foo; public class MyService { @JmsListener(containerFactory = "myJmsListenerContainerFactory", destination="myQueue") public void process(String msg) { // process incoming message } }The container factory to use is identified by the
containerFactory
attribute defining the name of the JmsListenerContainerFactory
bean to use. When none
is set a JmsListenerContainerFactory
bean with name jmsListenerContainerFactory
is
assumed to be present.
the following configuration would ensure that every time a Message
is received on the Destination
named "myQueue", MyService.process()
is called with the content of the message:
@Configuration @EnableJms public class AppConfig { @Bean public MyService myService() { return new MyService(); } // JMS infrastructure setup }Alternatively, if
MyService
were annotated with @Component
, the
following configuration would ensure that its @JmsListener
annotated
method is invoked with a matching incoming message:
@Configuration @EnableJms @ComponentScan(basePackages="com.acme.foo") public class AppConfig { }Note that the created containers are not registered against the application context but can be easily located for management purposes using the
JmsListenerEndpointRegistry
.
Annotated methods can use flexible signature; in particular, it is possible to use
the Message
abstraction and related annotations,
see JmsListener
Javadoc for more details. For instance, the following would
inject the content of the message and a custom "myCounter" JMS header:
@JmsListener(containerFactory = "myJmsListenerContainerFactory", destination="myQueue") public void process(String msg, @Header("myCounter") int counter) { // process incoming message }These features are abstracted by the
MessageHandlerMethodFactory
that is responsible to build the necessary invoker to process the annotated method. By default,
DefaultMessageHandlerMethodFactory
is used.
When more control is desired, a @Configuration
class may implement
JmsListenerConfigurer
. This allows access to the underlying
JmsListenerEndpointRegistrar
instance. The following example demonstrates how to specify an explicit default
JmsListenerContainerFactory
@Configuration @EnableJms public class AppConfig implements JmsListenerConfigurer { @Override public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { registrar.setContainerFactory(myJmsListenerContainerFactory()); } @Bean public JmsListenerContainerFactory<?> myJmsListenerContainerFactory() { // factory settings } @Bean public MyService myService() { return new MyService(); } }For reference, the example above can be compared to the following Spring XML configuration:
<beans> <jms:annotation-driven container-factory="myJmsListenerContainerFactory"/> <bean id="myJmsListenerContainerFactory" class="org.springframework.jms.config.DefaultJmsListenerContainerFactory"> // factory settings </bean> <bean id="myService" class="com.acme.foo.MyService"/> </beans> }It is also possible to specify a custom
JmsListenerEndpointRegistry
in case you need more control on the way the containers
are created and managed. The example below also demonstrates how to customize the
JmsHandlerMethodFactory
to use with a custom Validator
so that payloads annotated with Validated
are first validated against a custom Validator
.
@Configuration @EnableJms public class AppConfig implements JmsListenerConfigurer { @Override public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { registrar.setEndpointRegistry(myJmsListenerEndpointRegistry()); registrar.setMessageHandlerMethodFactory(myJmsHandlerMethodFactory); } @Bean public JmsListenerEndpointRegistry<?> myJmsListenerEndpointRegistry() { // registry configuration } @Bean public JmsHandlerMethodFactory myJmsHandlerMethodFactory() { DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory(); factory.setValidator(new MyValidator()); return factory; } @Bean public MyService myService() { return new MyService(); } }For reference, the example above can be compared to the following Spring XML configuration:
<beans> <jms:annotation-driven registry="myJmsListenerEndpointRegistry" handler-method-factory="myJmsHandlerMethodFactory"/> <bean id="myJmsListenerEndpointRegistry" class="org.springframework.jms.config.JmsListenerEndpointRegistry"> // registry configuration </bean> <bean id="myJmsHandlerMethodFactory" class="org.springframework.messaging.handler.support.DefaultJmsHandlerMethodFactory"> <property name="validator" ref="myValidator"/> </bean> <bean id="myService" class="com.acme.foo.MyService"/> </beans>Implementing
JmsListenerConfigurer
also allows for fine-grained
control over endpoints registration via the JmsListenerEndpointRegistrar
.
For example, the following configures an extra endpoint:
@Configuration @EnableJms public class AppConfig implements JmsListenerConfigurer { @Override public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { SimpleJmsListenerEndpoint myEndpoint = new SimpleJmsListenerEndpoint(); // ... configure the endpoint registrar.registerEndpoint(endpoint, anotherJmsListenerContainerFactory()); } @Bean public MyService myService() { return new MyService(); } @Bean public JmsListenerContainerFactory<?> anotherJmsListenerContainerFactory() { // ... } // JMS infrastructure setup }Note that all beans implementing
JmsListenerConfigurer
will be detected and
invoked in a similar fashion. The example above can be translated in a regular bean
definition registered in the context in case you use the XML configuration.JmsListener
,
JmsListenerAnnotationBeanPostProcessor
,
JmsListenerEndpointRegistrar
,
JmsListenerEndpointRegistry