diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQConnectionFactoryConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQConnectionFactoryConfiguration.java index 4127760398..b216241464 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQConnectionFactoryConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQConnectionFactoryConfiguration.java @@ -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"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ import org.apache.activemq.pool.PooledConnectionFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,6 +35,7 @@ import org.springframework.context.annotation.Configuration; * @author Stephane Nicoll * @author Phillip Webb * @author Andy Wilkinson + * @author Aurélien Leboulanger * @since 1.1.0 */ @Configuration @@ -41,7 +43,7 @@ import org.springframework.context.annotation.Configuration; class ActiveMQConnectionFactoryConfiguration { @Bean - @ConditionalOnProperty(prefix = "spring.activemq", name = "pooled", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", matchIfMissing = true) public ActiveMQConnectionFactory jmsConnectionFactory(ActiveMQProperties properties) { return new ActiveMQConnectionFactoryFactory(properties) .createConnectionFactory(ActiveMQConnectionFactory.class); @@ -51,12 +53,18 @@ class ActiveMQConnectionFactoryConfiguration { static class PooledConnectionFactoryConfiguration { @Bean(destroyMethod = "stop") - @ConditionalOnProperty(prefix = "spring.activemq", name = "pooled", havingValue = "true", matchIfMissing = false) - public PooledConnectionFactory pooledJmsConnectionFactory( - ActiveMQProperties properties) { - return new PooledConnectionFactory( + @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false) + @ConfigurationProperties("spring.activemq.pool.configuration") + public PooledConnectionFactory pooledJmsConnectionFactory(ActiveMQProperties properties) { + PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory( new ActiveMQConnectionFactoryFactory(properties) .createConnectionFactory(ActiveMQConnectionFactory.class)); + + ActiveMQProperties.Pool pool = properties.getPool(); + pooledConnectionFactory.setMaxConnections(pool.getMaxConnections()); + pooledConnectionFactory.setIdleTimeout(pool.getIdleTimeout()); + pooledConnectionFactory.setExpiryTimeout(pool.getExpiryTimeout()); + return pooledConnectionFactory; } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQProperties.java index f217ddb98b..ab719dbc82 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQProperties.java @@ -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. @@ -23,6 +23,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * * @author Greg Turnquist * @author Stephane Nicoll + * @author Aurélien Leboulanger */ @ConfigurationProperties(prefix = "spring.activemq") public class ActiveMQProperties { @@ -38,12 +39,6 @@ public class ActiveMQProperties { */ private boolean inMemory = true; - /** - * Specify if a PooledConnectionFactory should be created instead of a regular - * ConnectionFactory. - */ - private boolean pooled; - /** * Login user of the broker. */ @@ -54,6 +49,8 @@ public class ActiveMQProperties { */ private String password; + private Pool pool = new Pool(); + public String getBrokerUrl() { return this.brokerUrl; } @@ -70,14 +67,6 @@ public class ActiveMQProperties { this.inMemory = inMemory; } - public boolean isPooled() { - return this.pooled; - } - - public void setPooled(boolean pooled) { - this.pooled = pooled; - } - public String getUser() { return this.user; } @@ -94,4 +83,68 @@ public class ActiveMQProperties { this.password = password; } + public Pool getPool() { + return this.pool; + } + + public void setPool(Pool pool) { + this.pool = pool; + } + + protected static class Pool { + + /** + * Whether a PooledConnectionFactory should be created instead of a regular + * ConnectionFactory. + */ + private boolean enabled; + + /** + * Maximum number of pooled connections. + */ + private int maxConnections = 1; + + /** + * Connection idle timeout in milliseconds. + */ + private int idleTimeout = 30000; + + /** + * Connection expiration timeout in milliseconds. + */ + private long expiryTimeout = 0; + + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public int getMaxConnections() { + return this.maxConnections; + } + + public void setMaxConnections(int maxConnections) { + this.maxConnections = maxConnections; + } + + public int getIdleTimeout() { + return this.idleTimeout; + } + + public void setIdleTimeout(int idleTimeout) { + this.idleTimeout = idleTimeout; + } + + public long getExpiryTimeout() { + return this.expiryTimeout; + } + + public void setExpiryTimeout(long expiryTimeout) { + this.expiryTimeout = expiryTimeout; + } + + } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQXAConnectionFactoryConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQXAConnectionFactoryConfiguration.java index 7a67555fd1..24ecb240f1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQXAConnectionFactoryConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQXAConnectionFactoryConfiguration.java @@ -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. @@ -21,7 +21,6 @@ import javax.transaction.TransactionManager; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.ActiveMQXAConnectionFactory; -import org.apache.activemq.pool.PooledConnectionFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -36,6 +35,7 @@ import org.springframework.context.annotation.Primary; * Configuration for ActiveMQ XA {@link ConnectionFactory}. * * @author Phillip Webb + * @author Aurélien Leboulanger * @since 1.2.0 */ @Configuration @@ -45,7 +45,7 @@ import org.springframework.context.annotation.Primary; class ActiveMQXAConnectionFactoryConfiguration { @Primary - @Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" }) + @Bean(name = {"jmsConnectionFactory", "xaJmsConnectionFactory"}) public ConnectionFactory jmsConnectionFactory(ActiveMQProperties properties, XAConnectionFactoryWrapper wrapper) throws Exception { ActiveMQXAConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory( @@ -54,25 +54,11 @@ class ActiveMQXAConnectionFactoryConfiguration { } @Bean - @ConditionalOnProperty(prefix = "spring.activemq", name = "pooled", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", matchIfMissing = true) public ActiveMQConnectionFactory nonXaJmsConnectionFactory( ActiveMQProperties properties) { return new ActiveMQConnectionFactoryFactory(properties) .createConnectionFactory(ActiveMQConnectionFactory.class); } - @ConditionalOnClass(PooledConnectionFactory.class) - @ConditionalOnProperty(prefix = "spring.activemq", name = "pooled", havingValue = "true", matchIfMissing = false) - static class PooledConnectionFactoryConfiguration { - - @Bean(destroyMethod = "stop") - public PooledConnectionFactory pooledNonXaJmsConnectionFactory( - ActiveMQProperties properties) { - return new PooledConnectionFactory( - new ActiveMQConnectionFactoryFactory(properties) - .createConnectionFactory(ActiveMQConnectionFactory.class)); - } - - } - } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java index 306d73f74d..14a08208d3 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java @@ -54,6 +54,7 @@ import static org.mockito.Mockito.mock; * * @author Greg Turnquist * @author Stephane Nicoll + * @author Aurélien Leboulanger */ public class JmsAutoConfigurationTests { @@ -309,7 +310,7 @@ public class JmsAutoConfigurationTests { @Test public void testActiveMQOverriddenPool() { - load(TestConfiguration.class, "spring.activemq.pooled:true"); + load(TestConfiguration.class, "spring.activemq.pool.enabled:true"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); PooledConnectionFactory pool = this.context .getBean(PooledConnectionFactory.class); @@ -323,7 +324,7 @@ public class JmsAutoConfigurationTests { @Test public void testActiveMQOverriddenPoolAndStandalone() { - load(TestConfiguration.class, "spring.activemq.pooled:true", + load(TestConfiguration.class, "spring.activemq.pool.enabled:true", "spring.activemq.inMemory:false"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); PooledConnectionFactory pool = this.context @@ -338,7 +339,7 @@ public class JmsAutoConfigurationTests { @Test public void testActiveMQOverriddenPoolAndRemoteServer() { - load(TestConfiguration.class, "spring.activemq.pooled:true", + load(TestConfiguration.class, "spring.activemq.pool.enabled:true", "spring.activemq.brokerUrl:tcp://remote-host:10000"); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); PooledConnectionFactory pool = this.context diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQAutoConfigurationTests.java index 40bed97c0f..ed18e0ad3a 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQAutoConfigurationTests.java @@ -21,6 +21,7 @@ import javax.jms.JMSException; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.pool.PooledConnectionFactory; + import org.junit.Test; import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; @@ -37,6 +38,8 @@ import static org.mockito.Mockito.mockingDetails; * Tests for {@link ActiveMQAutoConfiguration} * * @author Andy Wilkinson + * @author Aurélien Leboulanger + * @author Stephane Nicoll */ public class ActiveMQAutoConfigurationTests { @@ -59,15 +62,34 @@ public class ActiveMQAutoConfigurationTests { .isTrue(); } + @Test + public void customPooledConnectionFactoryConfiguration() { + load(EmptyConfiguration.class, + "spring.activemq.pool.enabled:true", + "spring.activemq.pool.maxConnections:256", + "spring.activemq.pool.idleTimeout:512", + "spring.activemq.pool.expiryTimeout:4096", + "spring.activemq.pool.configuration.maximumActiveSessionPerConnection:1024", + "spring.activemq.pool.configuration.timeBetweenExpirationCheckMillis:2048"); + ConnectionFactory connectionFactory = this.context.getBean(ConnectionFactory.class); + assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class); + + PooledConnectionFactory pooledConnectionFactory = (PooledConnectionFactory) connectionFactory; + assertThat(pooledConnectionFactory.getMaxConnections()).isEqualTo(256); + assertThat(pooledConnectionFactory.getIdleTimeout()).isEqualTo(512); + assertThat(pooledConnectionFactory.getMaximumActiveSessionPerConnection()).isEqualTo(1024); + assertThat(pooledConnectionFactory.getTimeBetweenExpirationCheckMillis()).isEqualTo(2048); + assertThat(pooledConnectionFactory.getExpiryTimeout()).isEqualTo(4096); + } + @Test public void pooledConnectionFactoryConfiguration() throws JMSException { - load(EmptyConfiguration.class, "spring.activemq.pooled:true"); + load(EmptyConfiguration.class, "spring.activemq.pool.enabled:true"); ConnectionFactory connectionFactory = this.context .getBean(ConnectionFactory.class); assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class); this.context.close(); - assertThat(((PooledConnectionFactory) connectionFactory).createConnection()) - .isNull(); + assertThat(connectionFactory.createConnection()).isNull(); } private void load(Class config, String... environment) { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQPropertiesTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQPropertiesTests.java index 4e636117b6..fe032a1c4a 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQPropertiesTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQPropertiesTests.java @@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link ActiveMQProperties} and ActiveMQConnectionFactoryFactory. * * @author Stephane Nicoll + * @author Aurélien Leboulanger */ public class ActiveMQPropertiesTests { diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index f58dd2c0b8..a79080f1d3 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -726,8 +726,12 @@ content into your application; rather pick only the properties that you need. spring.activemq.broker-url= # URL of the ActiveMQ broker. Auto-generated by default. For instance `tcp://localhost:61616` spring.activemq.in-memory=true # Specify if the default broker URL should be in memory. Ignored if an explicit broker has been specified. spring.activemq.password= # Login password of the broker. - spring.activemq.pooled=false # Specify if a PooledConnectionFactory should be created instead of a regular ConnectionFactory. spring.activemq.user= # Login user of the broker. + spring.activemq.pool.configuration.*= # See PooledConnectionFactory + spring.activemq.pool.enabled=false # Whether a PooledConnectionFactory should be created instead of a regular ConnectionFactory. + spring.activemq.pool.expiry-timeout=0 # Connection expiration timeout in milliseconds. + spring.activemq.pool.idle-timeout=30000 # Connection idle timeout in milliseconds. + spring.activemq.pool.max-connections=1 # Maximum number of pooled connections. # ARTEMIS ({sc-spring-boot-autoconfigure}/jms/artemis/ArtemisProperties.{sc-ext}[ArtemisProperties]) spring.artemis.embedded.cluster-password= # Cluster password. Randomly generated on startup by default. diff --git a/spring-boot-samples/spring-boot-sample-activemq/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-activemq/src/main/resources/application.properties index e6f67126ea..9b10a7112b 100644 --- a/spring-boot-samples/spring-boot-sample-activemq/src/main/resources/application.properties +++ b/spring-boot-samples/spring-boot-sample-activemq/src/main/resources/application.properties @@ -1,2 +1,2 @@ spring.activemq.in-memory=true -spring.activemq.pooled=false \ No newline at end of file +spring.activemq.pool.enabled=false