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: