Auto-configure JMS MessageConverter

If a `MessageConverter` bean is available, we now associate it to the
created `JmsTemplate` and `JmsListenerContainerFactory`. That way,
registering a custom `MessageConverter` is all that's needed.

The JMS auto-configuration is now using the new `ObjectProvider` that
offers a nicer API to detect if a primary candidate is available for
optional collaborators.

Closes gh-4282
pull/5289/head
Stephane Nicoll 9 years ago
parent ad7cf48497
commit d13b9a98c5

@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.jms;
import javax.jms.ConnectionFactory;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.util.Assert;
@ -33,6 +34,8 @@ public final class DefaultJmsListenerContainerFactoryConfigurer {
private DestinationResolver destinationResolver;
private MessageConverter messageConverter;
private JtaTransactionManager transactionManager;
private JmsProperties jmsProperties;
@ -46,6 +49,16 @@ public final class DefaultJmsListenerContainerFactoryConfigurer {
this.destinationResolver = destinationResolver;
}
/**
* Set the {@link MessageConverter} to use or {@code null} if the out-of-the-box
* converter should be used.
* @param messageConverter the {@link MessageConverter}
* @since 1.4.0
*/
public void setMessageConverter(MessageConverter messageConverter) {
this.messageConverter = messageConverter;
}
/**
* Set the {@link JtaTransactionManager} to use or {@code null} if the JTA support
* should not be used.
@ -84,6 +97,9 @@ public final class DefaultJmsListenerContainerFactoryConfigurer {
if (this.destinationResolver != null) {
factory.setDestinationResolver(this.destinationResolver);
}
if (this.messageConverter != null) {
factory.setMessageConverter(this.messageConverter);
}
JmsProperties.Listener listener = this.jmsProperties.getListener();
factory.setAutoStartup(listener.isAutoStartup());
if (listener.getAcknowledgeMode() != null) {

@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.jms;
import javax.jms.ConnectionFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnJndi;
@ -27,6 +28,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerConfigUtils;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.jms.support.destination.JndiDestinationResolver;
import org.springframework.transaction.jta.JtaTransactionManager;
@ -42,11 +44,14 @@ import org.springframework.transaction.jta.JtaTransactionManager;
@ConditionalOnClass(EnableJms.class)
class JmsAnnotationDrivenConfiguration {
@Autowired(required = false)
private DestinationResolver destinationResolver;
@Autowired
private ObjectProvider<DestinationResolver> destinationResolver;
@Autowired
private ObjectProvider<JtaTransactionManager> transactionManager;
@Autowired(required = false)
private JtaTransactionManager transactionManager;
@Autowired
private ObjectProvider<MessageConverter> messageConverter;
@Autowired
private JmsProperties properties;
@ -55,8 +60,9 @@ class JmsAnnotationDrivenConfiguration {
@ConditionalOnMissingBean
public DefaultJmsListenerContainerFactoryConfigurer jmsListenerContainerFactoryConfigurer() {
DefaultJmsListenerContainerFactoryConfigurer configurer = new DefaultJmsListenerContainerFactoryConfigurer();
configurer.setDestinationResolver(this.destinationResolver);
configurer.setTransactionManager(this.transactionManager);
configurer.setDestinationResolver(this.destinationResolver.getIfUnique());
configurer.setTransactionManager(this.transactionManager.getIfUnique());
configurer.setMessageConverter(this.messageConverter.getIfUnique());
configurer.setJmsProperties(this.properties);
return configurer;
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.jms;
import javax.jms.ConnectionFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@ -29,6 +30,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.destination.DestinationResolver;
/**
@ -50,8 +52,11 @@ public class JmsAutoConfiguration {
@Autowired
private ConnectionFactory connectionFactory;
@Autowired(required = false)
private DestinationResolver destinationResolver;
@Autowired
private ObjectProvider<DestinationResolver> destinationResolver;
@Autowired
private ObjectProvider<MessageConverter> messageConverter;
@Bean
@ConditionalOnMissingBean
@ -59,7 +64,10 @@ public class JmsAutoConfiguration {
JmsTemplate jmsTemplate = new JmsTemplate(this.connectionFactory);
jmsTemplate.setPubSubDomain(this.properties.isPubSubDomain());
if (this.destinationResolver != null) {
jmsTemplate.setDestinationResolver(this.destinationResolver);
jmsTemplate.setDestinationResolver(this.destinationResolver.getIfUnique());
}
if (this.messageConverter != null) {
jmsTemplate.setMessageConverter(this.messageConverter.getIfUnique());
}
return jmsTemplate;
}

@ -32,6 +32,7 @@ import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
@ -42,6 +43,7 @@ import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.transaction.jta.JtaTransactionManager;
import static org.assertj.core.api.Assertions.assertThat;
@ -202,6 +204,20 @@ public class JmsAutoConfigurationTests {
.getPropertyValue("transactionManager")).isNull();
}
@Test
public void testDefaultContainerFactoryWithMessageConverters() {
this.context = createContext(MessageConvertersConfiguration.class,
EnableJmsConfiguration.class);
JmsListenerContainerFactory<?> jmsListenerContainerFactory = this.context.getBean(
"jmsListenerContainerFactory", JmsListenerContainerFactory.class);
assertThat(jmsListenerContainerFactory.getClass())
.isEqualTo(DefaultJmsListenerContainerFactory.class);
DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory)
.createListenerContainer(mock(JmsListenerEndpoint.class));
assertThat(listenerContainer.getMessageConverter())
.isSameAs(this.context.getBean("myMessageConverter"));
}
@Test
public void testCustomContainerFactoryWithConfigurer() {
this.context = doLoad(
@ -219,6 +235,15 @@ public class JmsAutoConfigurationTests {
assertThat(listenerContainer.isAutoStartup()).isFalse();
}
@Test
public void testJmsTemplateWithMessageConverters() {
load(MessageConvertersConfiguration.class);
JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
assertThat(jmsTemplate.getMessageConverter()).isSameAs(
this.context.getBean("myMessageConverter"));
}
@Test
public void testPubSubDisabledByDefault() {
load(TestConfiguration.class);
@ -452,6 +477,22 @@ public class JmsAutoConfigurationTests {
}
@Configuration
protected static class MessageConvertersConfiguration {
@Bean
@Primary
public MessageConverter myMessageConverter() {
return mock(MessageConverter.class);
}
@Bean
public MessageConverter anotherMessageConverter() {
return mock(MessageConverter.class);
}
}
@Configuration
protected static class TestConfiguration9 {

@ -3590,7 +3590,9 @@ beans:
----
NOTE: {spring-javadoc}/jms/core/JmsMessagingTemplate.{dc-ext}[`JmsMessagingTemplate`]
can be injected in a similar manner.
can be injected in a similar manner. If a `DestinationResolver` or `MessageConverter`
beans are defined, they are associated automatically to the auto-configured
`JmsTemplate`.
@ -3599,7 +3601,8 @@ can be injected in a similar manner.
When the JMS infrastructure is present, any bean can be annotated with `@JmsListener` to
create a listener endpoint. If no `JmsListenerContainerFactory` has been defined, a
default one is configured automatically.
default one is configured automatically. If a `DestinationResolver` or `MessageConverter`
beans are defined, they are associated automatically to the default factory.
The default factory is transactional by default. If you are running in an infrastructure
where a `JtaTransactionManager` is present, it will be associated to the listener container

Loading…
Cancel
Save