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 4127760398e..b808f976324 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 @@ -34,6 +34,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 +42,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,14 +52,28 @@ 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) + 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.getIdleTimeMillis()); + pooledConnectionFactory.setMaximumActiveSessionPerConnection(pool.getMaxSessionsPerConnection()); + pooledConnectionFactory.setExpiryTimeout(pool.getExpiryTimeMillis()); + pooledConnectionFactory.setTimeBetweenExpirationCheckMillis(pool.getTimeBetweenEvictionRunsMillis()); + + return pooledConnectionFactory; } + @Bean + @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", matchIfMissing = true) + + public ActiveMQConnectionFactory jmsConnectionFactory(ActiveMQProperties properties) { + return new ActiveMQConnectionFactoryFactory(properties).createConnectionFactory(ActiveMQConnectionFactory.class); + } } } 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 f217ddb98b4..0261f3e01a5 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 @@ -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,93 @@ public class ActiveMQProperties { this.password = password; } + public Pool getPool() { + return this.pool; + } + + public void setPool(Pool pool) { + this.pool = pool; + } + + protected static class Pool { + + /** + * Specify if a PooledConnectionFactory should be created instead of a regular + * ConnectionFactory. + */ + private boolean enabled; + + /** + * Sets the maximum number of pooled Connections. + */ + private int maxConnections = 1; + + /** + * Sets the idle timeout value for Connection's that are created by this pool in Milliseconds. + */ + private int idleTimeMillis = 30 * 1000; + + /** + * Allow connections to expire, irrespective of load or idle time. + */ + private long expiryTimeMillis = 0L; + + /** + * Sets the maximum number of active sessions per connection. + */ + private int maxSessionsPerConnection = 500; + + /** + * Sets the number of milliseconds to sleep between runs of the idle Connection eviction thread. + */ + private long timeBetweenEvictionRunsMillis = -1L; + + 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 getIdleTimeMillis() { + return this.idleTimeMillis; + } + + public void setIdleTimeMillis(int idleTimeMillis) { + this.idleTimeMillis = idleTimeMillis; + } + + public long getExpiryTimeMillis() { + return this.expiryTimeMillis; + } + + public void setExpiryTimeMillis(long expiryTimeMillis) { + this.expiryTimeMillis = expiryTimeMillis; + } + + public int getMaxSessionsPerConnection() { + return this.maxSessionsPerConnection; + } + + public void setMaxSessionsPerConnection(int maxSessionsPerConnection) { + this.maxSessionsPerConnection = maxSessionsPerConnection; + } + + public long getTimeBetweenEvictionRunsMillis() { + return this.timeBetweenEvictionRunsMillis; + } + + public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { + this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; + } + } } 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 7a67555fd12..c9cd8c6943d 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 @@ -36,6 +36,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 @@ -54,7 +55,7 @@ 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) @@ -62,17 +63,25 @@ class ActiveMQXAConnectionFactoryConfiguration { } @ConditionalOnClass(PooledConnectionFactory.class) - @ConditionalOnProperty(prefix = "spring.activemq", name = "pooled", havingValue = "true", matchIfMissing = false) + @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false) static class PooledConnectionFactoryConfiguration { @Bean(destroyMethod = "stop") public PooledConnectionFactory pooledNonXaJmsConnectionFactory( ActiveMQProperties properties) { - return new PooledConnectionFactory( + PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory( new ActiveMQConnectionFactoryFactory(properties) .createConnectionFactory(ActiveMQConnectionFactory.class)); - } + ActiveMQProperties.Pool pool = properties.getPool(); + pooledConnectionFactory.setExpiryTimeout(pool.getExpiryTimeMillis()); + pooledConnectionFactory.setMaxConnections(pool.getMaxConnections()); + pooledConnectionFactory.setIdleTimeout(pool.getIdleTimeMillis()); + pooledConnectionFactory.setMaximumActiveSessionPerConnection(pool.getMaxSessionsPerConnection()); + pooledConnectionFactory.setTimeBetweenExpirationCheckMillis(pool.getTimeBetweenEvictionRunsMillis()); + + return pooledConnectionFactory; + } } } 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 306d73f74d9..14a08208d3e 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 40bed97c0f4..3f9a015d335 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,7 @@ import static org.mockito.Mockito.mockingDetails; * Tests for {@link ActiveMQAutoConfiguration} * * @author Andy Wilkinson + * @author Aurélien Leboulanger */ public class ActiveMQAutoConfigurationTests { @@ -59,9 +61,30 @@ public class ActiveMQAutoConfigurationTests { .isTrue(); } + @Test + public void custompooledConnectionFactoryConfiguration() { + load(EmptyConfiguration.class, + "spring.activemq.pool.enabled:true", + "spring.activemq.pool.max-connections:256", + "spring.activemq.pool.idle-time-millis:512", + "spring.activemq.pool.max-sessions-per-connection:1024", + "spring.activemq.pool.time-between-eviction-runs-millis:2048", + "spring.activemq.pool.expiry-time-millis:4096" + ); + 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); 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 4e636117b6a..fe032a1c4ae 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 f58dd2c0b84..deddfa405b9 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,13 @@ 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.enabled=false # Specify if a PooledConnectionFactory should be created instead of a regular ConnectionFactory. + spring.activemq.pool.max-connections=1 # The maximum number of pooled Connections + spring.activemq.pool.max-sessions-per-connection=500 # The maximum number of active sessions per connection + spring.activemq.pool.time-between-eviction-runs-millis=-1 # The number of milliseconds to sleep between runs of the idle Connection eviction thread. + spring.activemq.pool.idle-time-millis=30000 # The idle timeout value for Connection's that are created by this pool (in Milliseconds) + spring.activemq.pool.expiry-time-millis=0 # Allow connections to expire, irrespective of load or idle time # 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 e6f67126eaf..9b10a7112b9 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