Commit 52461b42 authored by Stephane Nicoll's avatar Stephane Nicoll

Merge pull request #5372 from herau/fix/1598

* pr/5372:
  Polish contribution
  Improve ActiveMQ connection pool configuration
parents fa84b179 3d4a9d9c
/* /*
* 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.
...@@ -24,6 +24,7 @@ import org.apache.activemq.pool.PooledConnectionFactory; ...@@ -24,6 +24,7 @@ import org.apache.activemq.pool.PooledConnectionFactory;
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.boot.autoconfigure.condition.ConditionalOnProperty; 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.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -34,6 +35,7 @@ import org.springframework.context.annotation.Configuration; ...@@ -34,6 +35,7 @@ import org.springframework.context.annotation.Configuration;
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Aurélien Leboulanger
* @since 1.1.0 * @since 1.1.0
*/ */
@Configuration @Configuration
...@@ -41,7 +43,7 @@ import org.springframework.context.annotation.Configuration; ...@@ -41,7 +43,7 @@ import org.springframework.context.annotation.Configuration;
class ActiveMQConnectionFactoryConfiguration { class ActiveMQConnectionFactoryConfiguration {
@Bean @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) { public ActiveMQConnectionFactory jmsConnectionFactory(ActiveMQProperties properties) {
return new ActiveMQConnectionFactoryFactory(properties) return new ActiveMQConnectionFactoryFactory(properties)
.createConnectionFactory(ActiveMQConnectionFactory.class); .createConnectionFactory(ActiveMQConnectionFactory.class);
...@@ -51,12 +53,18 @@ class ActiveMQConnectionFactoryConfiguration { ...@@ -51,12 +53,18 @@ class ActiveMQConnectionFactoryConfiguration {
static class PooledConnectionFactoryConfiguration { static class PooledConnectionFactoryConfiguration {
@Bean(destroyMethod = "stop") @Bean(destroyMethod = "stop")
@ConditionalOnProperty(prefix = "spring.activemq", name = "pooled", havingValue = "true", matchIfMissing = false) @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false)
public PooledConnectionFactory pooledJmsConnectionFactory( @ConfigurationProperties("spring.activemq.pool.configuration")
ActiveMQProperties properties) { public PooledConnectionFactory pooledJmsConnectionFactory(ActiveMQProperties properties) {
return new PooledConnectionFactory( PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(
new ActiveMQConnectionFactoryFactory(properties) new ActiveMQConnectionFactoryFactory(properties)
.createConnectionFactory(ActiveMQConnectionFactory.class)); .createConnectionFactory(ActiveMQConnectionFactory.class));
ActiveMQProperties.Pool pool = properties.getPool();
pooledConnectionFactory.setMaxConnections(pool.getMaxConnections());
pooledConnectionFactory.setIdleTimeout(pool.getIdleTimeout());
pooledConnectionFactory.setExpiryTimeout(pool.getExpiryTimeout());
return pooledConnectionFactory;
} }
} }
......
/* /*
* 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"); * 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.
...@@ -23,6 +23,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; ...@@ -23,6 +23,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
* *
* @author Greg Turnquist * @author Greg Turnquist
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Aurélien Leboulanger
*/ */
@ConfigurationProperties(prefix = "spring.activemq") @ConfigurationProperties(prefix = "spring.activemq")
public class ActiveMQProperties { public class ActiveMQProperties {
...@@ -38,12 +39,6 @@ public class ActiveMQProperties { ...@@ -38,12 +39,6 @@ public class ActiveMQProperties {
*/ */
private boolean inMemory = true; private boolean inMemory = true;
/**
* Specify if a PooledConnectionFactory should be created instead of a regular
* ConnectionFactory.
*/
private boolean pooled;
/** /**
* Login user of the broker. * Login user of the broker.
*/ */
...@@ -54,6 +49,8 @@ public class ActiveMQProperties { ...@@ -54,6 +49,8 @@ public class ActiveMQProperties {
*/ */
private String password; private String password;
private Pool pool = new Pool();
public String getBrokerUrl() { public String getBrokerUrl() {
return this.brokerUrl; return this.brokerUrl;
} }
...@@ -70,14 +67,6 @@ public class ActiveMQProperties { ...@@ -70,14 +67,6 @@ public class ActiveMQProperties {
this.inMemory = inMemory; this.inMemory = inMemory;
} }
public boolean isPooled() {
return this.pooled;
}
public void setPooled(boolean pooled) {
this.pooled = pooled;
}
public String getUser() { public String getUser() {
return this.user; return this.user;
} }
...@@ -94,4 +83,68 @@ public class ActiveMQProperties { ...@@ -94,4 +83,68 @@ public class ActiveMQProperties {
this.password = password; 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;
}
}
} }
/* /*
* 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"); * 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.
...@@ -21,7 +21,6 @@ import javax.transaction.TransactionManager; ...@@ -21,7 +21,6 @@ import javax.transaction.TransactionManager;
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.ActiveMQXAConnectionFactory; import org.apache.activemq.ActiveMQXAConnectionFactory;
import org.apache.activemq.pool.PooledConnectionFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
...@@ -36,6 +35,7 @@ import org.springframework.context.annotation.Primary; ...@@ -36,6 +35,7 @@ import org.springframework.context.annotation.Primary;
* Configuration for ActiveMQ XA {@link ConnectionFactory}. * Configuration for ActiveMQ XA {@link ConnectionFactory}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Aurélien Leboulanger
* @since 1.2.0 * @since 1.2.0
*/ */
@Configuration @Configuration
...@@ -45,7 +45,7 @@ import org.springframework.context.annotation.Primary; ...@@ -45,7 +45,7 @@ import org.springframework.context.annotation.Primary;
class ActiveMQXAConnectionFactoryConfiguration { class ActiveMQXAConnectionFactoryConfiguration {
@Primary @Primary
@Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" }) @Bean(name = {"jmsConnectionFactory", "xaJmsConnectionFactory"})
public ConnectionFactory jmsConnectionFactory(ActiveMQProperties properties, public ConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
XAConnectionFactoryWrapper wrapper) throws Exception { XAConnectionFactoryWrapper wrapper) throws Exception {
ActiveMQXAConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory( ActiveMQXAConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(
...@@ -54,25 +54,11 @@ class ActiveMQXAConnectionFactoryConfiguration { ...@@ -54,25 +54,11 @@ class ActiveMQXAConnectionFactoryConfiguration {
} }
@Bean @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( public ActiveMQConnectionFactory nonXaJmsConnectionFactory(
ActiveMQProperties properties) { ActiveMQProperties properties) {
return new ActiveMQConnectionFactoryFactory(properties) return new ActiveMQConnectionFactoryFactory(properties)
.createConnectionFactory(ActiveMQConnectionFactory.class); .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));
}
}
} }
...@@ -54,6 +54,7 @@ import static org.mockito.Mockito.mock; ...@@ -54,6 +54,7 @@ import static org.mockito.Mockito.mock;
* *
* @author Greg Turnquist * @author Greg Turnquist
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Aurélien Leboulanger
*/ */
public class JmsAutoConfigurationTests { public class JmsAutoConfigurationTests {
...@@ -309,7 +310,7 @@ public class JmsAutoConfigurationTests { ...@@ -309,7 +310,7 @@ public class JmsAutoConfigurationTests {
@Test @Test
public void testActiveMQOverriddenPool() { 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); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
PooledConnectionFactory pool = this.context PooledConnectionFactory pool = this.context
.getBean(PooledConnectionFactory.class); .getBean(PooledConnectionFactory.class);
...@@ -323,7 +324,7 @@ public class JmsAutoConfigurationTests { ...@@ -323,7 +324,7 @@ public class JmsAutoConfigurationTests {
@Test @Test
public void testActiveMQOverriddenPoolAndStandalone() { public void testActiveMQOverriddenPoolAndStandalone() {
load(TestConfiguration.class, "spring.activemq.pooled:true", load(TestConfiguration.class, "spring.activemq.pool.enabled:true",
"spring.activemq.inMemory:false"); "spring.activemq.inMemory:false");
JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
PooledConnectionFactory pool = this.context PooledConnectionFactory pool = this.context
...@@ -338,7 +339,7 @@ public class JmsAutoConfigurationTests { ...@@ -338,7 +339,7 @@ public class JmsAutoConfigurationTests {
@Test @Test
public void testActiveMQOverriddenPoolAndRemoteServer() { 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"); "spring.activemq.brokerUrl:tcp://remote-host:10000");
JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
PooledConnectionFactory pool = this.context PooledConnectionFactory pool = this.context
......
...@@ -21,6 +21,7 @@ import javax.jms.JMSException; ...@@ -21,6 +21,7 @@ import javax.jms.JMSException;
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.pool.PooledConnectionFactory; import org.apache.activemq.pool.PooledConnectionFactory;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
...@@ -37,6 +38,8 @@ import static org.mockito.Mockito.mockingDetails; ...@@ -37,6 +38,8 @@ import static org.mockito.Mockito.mockingDetails;
* Tests for {@link ActiveMQAutoConfiguration} * Tests for {@link ActiveMQAutoConfiguration}
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Aurélien Leboulanger
* @author Stephane Nicoll
*/ */
public class ActiveMQAutoConfigurationTests { public class ActiveMQAutoConfigurationTests {
...@@ -59,15 +62,34 @@ public class ActiveMQAutoConfigurationTests { ...@@ -59,15 +62,34 @@ public class ActiveMQAutoConfigurationTests {
.isTrue(); .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 @Test
public void pooledConnectionFactoryConfiguration() throws JMSException { public void pooledConnectionFactoryConfiguration() throws JMSException {
load(EmptyConfiguration.class, "spring.activemq.pooled:true"); load(EmptyConfiguration.class, "spring.activemq.pool.enabled:true");
ConnectionFactory connectionFactory = this.context ConnectionFactory connectionFactory = this.context
.getBean(ConnectionFactory.class); .getBean(ConnectionFactory.class);
assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class); assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class);
this.context.close(); this.context.close();
assertThat(((PooledConnectionFactory) connectionFactory).createConnection()) assertThat(connectionFactory.createConnection()).isNull();
.isNull();
} }
private void load(Class<?> config, String... environment) { private void load(Class<?> config, String... environment) {
......
...@@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link ActiveMQProperties} and ActiveMQConnectionFactoryFactory. * Tests for {@link ActiveMQProperties} and ActiveMQConnectionFactoryFactory.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Aurélien Leboulanger
*/ */
public class ActiveMQPropertiesTests { public class ActiveMQPropertiesTests {
......
...@@ -726,8 +726,12 @@ content into your application; rather pick only the properties that you need. ...@@ -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.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.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.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.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]) # ARTEMIS ({sc-spring-boot-autoconfigure}/jms/artemis/ArtemisProperties.{sc-ext}[ArtemisProperties])
spring.artemis.embedded.cluster-password= # Cluster password. Randomly generated on startup by default. spring.artemis.embedded.cluster-password= # Cluster password. Randomly generated on startup by default.
......
spring.activemq.in-memory=true spring.activemq.in-memory=true
spring.activemq.pooled=false spring.activemq.pool.enabled=false
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment