spring-framework / org.springframework.jms.annotation / EnableJms

EnableJms

@Target([AnnotationTarget.CLASS, AnnotationTarget.FILE]) @Import(JmsBootstrapConfiguration) class EnableJms

Enable JMS listener annotated endpoints that are created under the cover by a org.springframework.jms.config.JmsListenerContainerFactory. To be used on org.springframework.context.annotation.Configuration classes as follows:

 @Configuration @EnableJms public class AppConfig { @Bean public DefaultJmsListenerContainerFactory myJmsListenerContainerFactory() { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory()); factory.setDestinationResolver(destinationResolver()); 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 org.springframework.jms.config.DefaultJmsListenerContainerFactory used in the sample above, provides the necessary configuration options that are supported by the underlying org.springframework.jms.listener.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 javax.jms.Message is received on the javax.jms.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 org.springframework.jms.config.JmsListenerEndpointRegistry.

Annotated methods can use flexible signature; in particular, it is possible to use the org.springframework.messaging.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 org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory that is responsible to build the necessary invoker to process the annotated method. By default, org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory is used.

When more control is desired, a @Configuration class may implement JmsListenerConfigurer. This allows access to the underlying org.springframework.jms.config.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 org.springframework.jms.config.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 org.springframework.validation.Validator so that payloads annotated with org.springframework.validation.annotation.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"/&gt; <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.

Author
Stephane Nicoll

Since
4.1

See Also
JmsListenerJmsListenerAnnotationBeanPostProcessororg.springframework.jms.config.JmsListenerEndpointRegistrarorg.springframework.jms.config.JmsListenerEndpointRegistry

Constructors

<init>

EnableJms()

Enable JMS listener annotated endpoints that are created under the cover by a org.springframework.jms.config.JmsListenerContainerFactory. To be used on org.springframework.context.annotation.Configuration classes as follows:

 @Configuration @EnableJms public class AppConfig { @Bean public DefaultJmsListenerContainerFactory myJmsListenerContainerFactory() { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory()); factory.setDestinationResolver(destinationResolver()); 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 org.springframework.jms.config.DefaultJmsListenerContainerFactory used in the sample above, provides the necessary configuration options that are supported by the underlying org.springframework.jms.listener.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 javax.jms.Message is received on the javax.jms.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 org.springframework.jms.config.JmsListenerEndpointRegistry.

Annotated methods can use flexible signature; in particular, it is possible to use the org.springframework.messaging.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 org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory that is responsible to build the necessary invoker to process the annotated method. By default, org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory is used.

When more control is desired, a @Configuration class may implement JmsListenerConfigurer. This allows access to the underlying org.springframework.jms.config.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 org.springframework.jms.config.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 org.springframework.validation.Validator so that payloads annotated with org.springframework.validation.annotation.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"/&gt; <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.