Annotation 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 for creating the listener
container responsible for a particular endpoint. Typical implementations, as the
DefaultJmsListenerContainerFactory
used in the sample above, provide 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 invoked 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 for building 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 over 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 endpoint 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 into a regular bean
definition registered in the context in case you use the XML configuration.
- Since:
- 4.1
- Author:
- Stephane Nicoll
- See Also: