Merge branch '1.3.x'

pull/3499/merge
Stephane Nicoll 9 years ago
commit 85cc885fd1

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,7 +20,6 @@ import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.config.RabbitListenerConfigUtils; import org.springframework.amqp.rabbit.config.RabbitListenerConfigUtils;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties.Listener;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -37,30 +36,18 @@ import org.springframework.context.annotation.Configuration;
@ConditionalOnClass(EnableRabbit.class) @ConditionalOnClass(EnableRabbit.class)
class RabbitAnnotationDrivenConfiguration { class RabbitAnnotationDrivenConfiguration {
@Bean
@ConditionalOnMissingBean
public RabbitListenerContainerFactoryConfigurer rabbitListenerContainerFactoryConfigurer() {
return new RabbitListenerContainerFactoryConfigurer();
}
@Bean @Bean
@ConditionalOnMissingBean(name = "rabbitListenerContainerFactory") @ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory( public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory, RabbitProperties config) { RabbitListenerContainerFactoryConfigurer configurer,
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); ConnectionFactory connectionFactory) {
factory.setConnectionFactory(connectionFactory); return configurer.createRabbitListenerContainerFactory(connectionFactory);
Listener listenerConfig = config.getListener();
factory.setAutoStartup(listenerConfig.isAutoStartup());
if (listenerConfig.getAcknowledgeMode() != null) {
factory.setAcknowledgeMode(listenerConfig.getAcknowledgeMode());
}
if (listenerConfig.getConcurrency() != null) {
factory.setConcurrentConsumers(listenerConfig.getConcurrency());
}
if (listenerConfig.getMaxConcurrency() != null) {
factory.setMaxConcurrentConsumers(listenerConfig.getMaxConcurrency());
}
if (listenerConfig.getPrefetch() != null) {
factory.setPrefetchCount(listenerConfig.getPrefetch());
}
if (listenerConfig.getTransactionSize() != null) {
factory.setTxSize(listenerConfig.getTransactionSize());
}
return factory;
} }
@EnableRabbit @EnableRabbit

@ -0,0 +1,87 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.amqp;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
/**
* Configure {@link RabbitListenerContainerFactory} with sensible defaults.
*
* @author Stephane Nicoll
* @since 1.3.3
*/
public final class RabbitListenerContainerFactoryConfigurer {
private RabbitProperties rabbitProperties;
/**
* Set the {@link RabbitProperties} to use.
* @param rabbitProperties the {@link RabbitProperties}
*/
@Autowired
public void setRabbitProperties(RabbitProperties rabbitProperties) {
this.rabbitProperties = rabbitProperties;
}
/**
* Create a new and pre-configured {@link SimpleRabbitListenerContainerFactory} instance
* for the specified {@link ConnectionFactory}.
* @param connectionFactory the {@link ConnectionFactory} to use.
* @return a pre-configured {@link SimpleRabbitListenerContainerFactory}
*/
public SimpleRabbitListenerContainerFactory createRabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
configure(factory, connectionFactory);
return factory;
}
/**
* Apply the default settings for the specified jms listener container factory. The
* factory can be further tuned and default settings can be overridden.
* @param factory the {@link SimpleRabbitListenerContainerFactory} instance to configure
* @param connectionFactory the {@link ConnectionFactory} to use
*/
public void configure(SimpleRabbitListenerContainerFactory factory,
ConnectionFactory connectionFactory) {
Assert.notNull(factory, "Factory must not be null");
Assert.notNull(connectionFactory, "ConnectionFactory must not be null");
factory.setConnectionFactory(connectionFactory);
RabbitProperties.Listener listenerConfig = this.rabbitProperties.getListener();
factory.setAutoStartup(listenerConfig.isAutoStartup());
if (listenerConfig.getAcknowledgeMode() != null) {
factory.setAcknowledgeMode(listenerConfig.getAcknowledgeMode());
}
if (listenerConfig.getConcurrency() != null) {
factory.setConcurrentConsumers(listenerConfig.getConcurrency());
}
if (listenerConfig.getMaxConcurrency() != null) {
factory.setMaxConcurrentConsumers(listenerConfig.getMaxConcurrency());
}
if (listenerConfig.getPrefetch() != null) {
factory.setPrefetchCount(listenerConfig.getPrefetch());
}
if (listenerConfig.getTransactionSize() != null) {
factory.setTxSize(listenerConfig.getTransactionSize());
}
}
}

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,7 +18,6 @@ package org.springframework.boot.autoconfigure.jms;
import javax.jms.ConnectionFactory; import javax.jms.ConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnJndi; import org.springframework.boot.autoconfigure.condition.ConditionalOnJndi;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -29,7 +28,6 @@ import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerConfigUtils; import org.springframework.jms.config.JmsListenerConfigUtils;
import org.springframework.jms.support.destination.DestinationResolver; import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.jms.support.destination.JndiDestinationResolver; import org.springframework.jms.support.destination.JndiDestinationResolver;
import org.springframework.transaction.jta.JtaTransactionManager;
/** /**
* Configuration for Spring 4.1 annotation driven JMS. * Configuration for Spring 4.1 annotation driven JMS.
@ -42,41 +40,17 @@ import org.springframework.transaction.jta.JtaTransactionManager;
@ConditionalOnClass(EnableJms.class) @ConditionalOnClass(EnableJms.class)
class JmsAnnotationDrivenConfiguration { class JmsAnnotationDrivenConfiguration {
@Autowired(required = false) @Bean
private DestinationResolver destinationResolver; @ConditionalOnMissingBean
public JmsListenerContainerFactoryConfigurer jmsListenerContainerFactoryConfigurer() {
@Autowired(required = false) return new JmsListenerContainerFactoryConfigurer();
private JtaTransactionManager transactionManager; }
@Autowired
private JmsProperties properties;
@Bean @Bean
@ConditionalOnMissingBean(name = "jmsListenerContainerFactory") @ConditionalOnMissingBean(name = "jmsListenerContainerFactory")
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory( public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(
ConnectionFactory connectionFactory) { JmsListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); return configurer.createJmsListenerContainerFactory(connectionFactory);
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(this.properties.isPubSubDomain());
if (this.transactionManager != null) {
factory.setTransactionManager(this.transactionManager);
}
else {
factory.setSessionTransacted(true);
}
if (this.destinationResolver != null) {
factory.setDestinationResolver(this.destinationResolver);
}
JmsProperties.Listener listener = this.properties.getListener();
factory.setAutoStartup(listener.isAutoStartup());
if (listener.getAcknowledgeMode() != null) {
factory.setSessionAcknowledgeMode(listener.getAcknowledgeMode().getMode());
}
String concurrency = listener.formatConcurrency();
if (concurrency != null) {
factory.setConcurrency(concurrency);
}
return factory;
} }
@EnableJms @EnableJms

@ -0,0 +1,116 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.jms;
import javax.jms.ConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.util.Assert;
/**
* Configure {@link JmsListenerContainerFactory} with sensible defaults.
*
* @author Stephane Nicoll
* @since 1.3.3
*/
public final class JmsListenerContainerFactoryConfigurer {
private DestinationResolver destinationResolver;
private JtaTransactionManager transactionManager;
private JmsProperties jmsProperties;
/**
* Set the {@link DestinationResolver} to use or {@code null} if no destination
* resolver should be associated with the factory by default.
* @param destinationResolver the {@link DestinationResolver}
*/
@Autowired(required = false)
public void setDestinationResolver(DestinationResolver destinationResolver) {
this.destinationResolver = destinationResolver;
}
/**
* Set the {@link JtaTransactionManager} to use or {@code null} if the JTA
* support should not be used.
* @param transactionManager the {@link JtaTransactionManager}
*/
@Autowired(required = false)
public void setTransactionManager(JtaTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/**
* Set the {@link JmsProperties to use}.
* @param jmsProperties the {@link JmsProperties}
*/
@Autowired
public void setJmsProperties(JmsProperties jmsProperties) {
this.jmsProperties = jmsProperties;
}
/**
* Create a new and pre-configured {@link DefaultJmsListenerContainerFactory} instance
* for the specified {@link ConnectionFactory}.
* @param connectionFactory the {@link ConnectionFactory} to use.
* @return a pre-configured {@link DefaultJmsListenerContainerFactory}
*/
public DefaultJmsListenerContainerFactory createJmsListenerContainerFactory(
ConnectionFactory connectionFactory) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configure(factory, connectionFactory);
return factory;
}
/**
* Apply the default settings for the specified jms listener container factory. The
* factory can be further tuned and default settings can be overridden.
* @param factory the {@link DefaultJmsListenerContainerFactory} instance to configure
* @param connectionFactory the {@link ConnectionFactory} to use
*/
public void configure(DefaultJmsListenerContainerFactory factory,
ConnectionFactory connectionFactory) {
Assert.notNull(factory, "Factory must not be null");
Assert.notNull(connectionFactory, "ConnectionFactory must not be null");
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(this.jmsProperties.isPubSubDomain());
if (this.transactionManager != null) {
factory.setTransactionManager(this.transactionManager);
}
else {
factory.setSessionTransacted(true);
}
if (this.destinationResolver != null) {
factory.setDestinationResolver(this.destinationResolver);
}
JmsProperties.Listener listener = this.jmsProperties.getListener();
factory.setAutoStartup(listener.isAutoStartup());
if (listener.getAcknowledgeMode() != null) {
factory.setSessionAcknowledgeMode(listener.getAcknowledgeMode().getMode());
}
String concurrency = listener.formatConcurrency();
if (concurrency != null) {
factory.setConcurrency(concurrency);
}
}
}

@ -202,6 +202,20 @@ public class JmsAutoConfigurationTests {
.getPropertyValue("transactionManager")).isNull(); .getPropertyValue("transactionManager")).isNull();
} }
@Test
public void testCustomContainerFactoryWithConfigurer() {
this.context = doLoad(new Class<?>[]{TestConfiguration9.class,
EnableJmsConfiguration.class}, "spring.jms.listener.autoStartup=false");
assertThat(this.context.containsBean("jmsListenerContainerFactory")).isTrue();
JmsListenerContainerFactory<?> jmsListenerContainerFactory = this.context.getBean(
"customListenerContainerFactory", JmsListenerContainerFactory.class);
assertThat(jmsListenerContainerFactory).isInstanceOf(DefaultJmsListenerContainerFactory.class);
DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory)
.createListenerContainer(mock(JmsListenerEndpoint.class));
assertThat(listenerContainer.getCacheLevel()).isEqualTo(DefaultMessageListenerContainer.CACHE_CONSUMER);
assertThat(listenerContainer.isAutoStartup()).isFalse();
}
@Test @Test
public void testPubSubDisabledByDefault() { public void testPubSubDisabledByDefault() {
load(TestConfiguration.class); load(TestConfiguration.class);
@ -435,6 +449,21 @@ public class JmsAutoConfigurationTests {
} }
@Configuration
protected static class TestConfiguration9 {
@Bean
JmsListenerContainerFactory<?> customListenerContainerFactory(
JmsListenerContainerFactoryConfigurer configurer,
ConnectionFactory connectionFactory) {
DefaultJmsListenerContainerFactory factory = configurer
.createJmsListenerContainerFactory(connectionFactory);
factory.setCacheLevel(DefaultMessageListenerContainer.CACHE_CONSUMER);
return factory;
}
}
@Configuration @Configuration
@EnableJms @EnableJms
protected static class EnableJmsConfiguration { protected static class EnableJmsConfiguration {

@ -3504,6 +3504,44 @@ The following component creates a listener endpoint on the `someQueue` destinati
TIP: Check {spring-javadoc}/jms/annotation/EnableJms.{dc-ext}[the Javadoc of `@EnableJms`] for TIP: Check {spring-javadoc}/jms/annotation/EnableJms.{dc-ext}[the Javadoc of `@EnableJms`] for
more details. more details.
If you need to create more `JmsListenerContainerFactory` instances or if you want to override
the default, Spring Boot provides a `JmsListenerContainerFactoryConfigurer` that you can use
to initialize a `DefaultJmsListenerContainerFactory` with the same settings as the one that
is auto-configured.
For instance, the following exposes another factory that uses a specific `MessageConverter`:
[source,java,indent=0]
----
@Configuration
static class JmsConfiguration {
@Bean
public DefaultJmsListenerContainerFactory myFactory(
JmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = configurer
.createJmsListenerContainerFactory(connectionFactory());
factory.setMessageConverter(myMessageConverter());
return factory;
}
}
----
That you can use in any `@JmsListener`-annotated method as follows:
[source,java,indent=0]
----
@Component
public class MyBean {
@JmsListener(destination = "someQueue", **containerFactory="myFactory"**)
public void processMessage(String content) {
// ...
}
}
----
[[boot-features-amqp]] [[boot-features-amqp]]
@ -3600,6 +3638,44 @@ The following component creates a listener endpoint on the `someQueue` queue:
TIP: Check {spring-amqp-javadoc}/rabbit/annotation/EnableRabbit.{dc-ext}[the Javadoc of `@EnableRabbit`] TIP: Check {spring-amqp-javadoc}/rabbit/annotation/EnableRabbit.{dc-ext}[the Javadoc of `@EnableRabbit`]
for more details. for more details.
If you need to create more `RabbitListenerContainerFactory` instances or if you want to override
the default, Spring Boot provides a `RabbitListenerContainerFactoryConfigurer` that you can use
to initialize a `SimpleRabbitListenerContainerFactory` with the same settings as the one that
is auto-configured.
For instance, the following exposes another factory that uses a specific `MessageConverter`:
[source,java,indent=0]
----
@Configuration
static class RabbitConfiguration {
@Bean
public SimpleRabbitListenerContainerFactory myFactory(
RabbitListenerContainerFactoryConfigurer configurer) {
SimpleRabbitListenerContainerFactory factory = configurer
.createRabbitListenerContainerFactory(connectionFactory());
factory.setMessageConverter(myMessageConverter());
return factory;
}
}
----
That you can use in any `@RabbitListener`-annotated method as follows:
[source,java,indent=0]
----
@Component
public class MyBean {
@RabbitListener(queues = "someQueue", **containerFactory="myFactory"**)
public void processMessage(String content) {
// ...
}
}
----
[[boot-features-email]] [[boot-features-email]]

Loading…
Cancel
Save