Switch JMS pooling to `pooled-jms`

This commit removes support for `activemq-pool` in benefit of
`pooled-jms`. While the former is not JMS 2 compliant, the latter is and
is independent of the ActiveMQ codebase (so potentially reusable in
custom code).

Closes gh-13927
pull/13961/merge
Stephane Nicoll 6 years ago
parent fbf95b6997
commit 435c47925e

@ -183,17 +183,6 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<artifactId>geronimo-jms_1.1_spec</artifactId>
<groupId>org.apache.geronimo.specs</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>org.apache.activemq</groupId> <groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client</artifactId> <artifactId>artemis-jms-client</artifactId>
@ -346,6 +335,17 @@
<artifactId>jboss-transaction-spi</artifactId> <artifactId>jboss-transaction-spi</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>org.messaginghub</groupId>
<artifactId>pooled-jms</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_2.0_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>org.mongodb</groupId> <groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-async</artifactId> <artifactId>mongodb-driver-async</artifactId>

@ -14,36 +14,37 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.autoconfigure.jms.activemq; package org.springframework.boot.autoconfigure.jms;
import javax.jms.ConnectionFactory; import javax.jms.ConnectionFactory;
import org.apache.activemq.jms.pool.PooledConnectionFactory; import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
/** /**
* Factory to create a {@link PooledConnectionFactory} from properties defined in * Factory to create a {@link JmsPoolConnectionFactory} from properties defined in
* {@link PooledConnectionFactoryProperties}. * {@link JmsPoolConnectionFactoryProperties}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 2.1.0 * @since 2.1.0
*/ */
public class PooledConnectionFactoryFactory { public class JmsPoolConnectionFactoryFactory {
private final PooledConnectionFactoryProperties properties; private final JmsPoolConnectionFactoryProperties properties;
public PooledConnectionFactoryFactory(PooledConnectionFactoryProperties properties) { public JmsPoolConnectionFactoryFactory(
JmsPoolConnectionFactoryProperties properties) {
this.properties = properties; this.properties = properties;
} }
/** /**
* Create a {@link PooledConnectionFactory} based on the specified * Create a {@link JmsPoolConnectionFactory} based on the specified
* {@link ConnectionFactory}. * {@link ConnectionFactory}.
* @param connectionFactory the connection factory to wrap * @param connectionFactory the connection factory to wrap
* @return a pooled connection factory * @return a pooled connection factory
*/ */
public PooledConnectionFactory createPooledConnectionFactory( public JmsPoolConnectionFactory createPooledConnectionFactory(
ConnectionFactory connectionFactory) { ConnectionFactory connectionFactory) {
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(); JmsPoolConnectionFactory pooledConnectionFactory = new JmsPoolConnectionFactory();
pooledConnectionFactory.setConnectionFactory(connectionFactory); pooledConnectionFactory.setConnectionFactory(connectionFactory);
pooledConnectionFactory pooledConnectionFactory
@ -53,14 +54,14 @@ public class PooledConnectionFactoryFactory {
this.properties.getBlockIfFullTimeout().toMillis()); this.properties.getBlockIfFullTimeout().toMillis());
} }
if (this.properties.getIdleTimeout() != null) { if (this.properties.getIdleTimeout() != null) {
pooledConnectionFactory pooledConnectionFactory.setConnectionIdleTimeout(
.setIdleTimeout((int) this.properties.getIdleTimeout().toMillis()); (int) this.properties.getIdleTimeout().toMillis());
} }
pooledConnectionFactory.setMaxConnections(this.properties.getMaxConnections()); pooledConnectionFactory.setMaxConnections(this.properties.getMaxConnections());
pooledConnectionFactory.setMaximumActiveSessionPerConnection( pooledConnectionFactory.setMaxSessionsPerConnection(
this.properties.getMaximumActiveSessionPerConnection()); this.properties.getMaxSessionsPerConnection());
if (this.properties.getTimeBetweenExpirationCheck() != null) { if (this.properties.getTimeBetweenExpirationCheck() != null) {
pooledConnectionFactory.setTimeBetweenExpirationCheckMillis( pooledConnectionFactory.setConnectionCheckInterval(
this.properties.getTimeBetweenExpirationCheck().toMillis()); this.properties.getTimeBetweenExpirationCheck().toMillis());
} }
pooledConnectionFactory pooledConnectionFactory

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.autoconfigure.jms.activemq; package org.springframework.boot.autoconfigure.jms;
import java.time.Duration; import java.time.Duration;
@ -24,10 +24,10 @@ import java.time.Duration;
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 2.1.0 * @since 2.1.0
*/ */
public class PooledConnectionFactoryProperties { public class JmsPoolConnectionFactoryProperties {
/** /**
* Whether a PooledConnectionFactory should be created, instead of a regular * Whether a JmsPoolConnectionFactory should be created, instead of a regular
* ConnectionFactory. * ConnectionFactory.
*/ */
private boolean enabled; private boolean enabled;
@ -54,9 +54,9 @@ public class PooledConnectionFactoryProperties {
private int maxConnections = 1; private int maxConnections = 1;
/** /**
* Maximum number of active sessions per connection. * Maximum number of pooled sessions per connection in the pool.
*/ */
private int maximumActiveSessionPerConnection = 500; private int maxSessionsPerConnection = 500;
/** /**
* Time to sleep between runs of the idle connection eviction thread. When negative, * Time to sleep between runs of the idle connection eviction thread. When negative,
@ -110,13 +110,23 @@ public class PooledConnectionFactoryProperties {
this.maxConnections = maxConnections; this.maxConnections = maxConnections;
} }
@Deprecated
public int getMaximumActiveSessionPerConnection() { public int getMaximumActiveSessionPerConnection() {
return this.maximumActiveSessionPerConnection; return getMaxSessionsPerConnection();
} }
@Deprecated
public void setMaximumActiveSessionPerConnection( public void setMaximumActiveSessionPerConnection(
int maximumActiveSessionPerConnection) { int maximumActiveSessionPerConnection) {
this.maximumActiveSessionPerConnection = maximumActiveSessionPerConnection; setMaxSessionsPerConnection(maximumActiveSessionPerConnection);
}
public int getMaxSessionsPerConnection() {
return this.maxSessionsPerConnection;
}
public void setMaxSessionsPerConnection(int maxSessionsPerConnection) {
this.maxSessionsPerConnection = maxSessionsPerConnection;
} }
public Duration getTimeBetweenExpirationCheck() { public Duration getTimeBetweenExpirationCheck() {

@ -21,13 +21,14 @@ import java.util.List;
import javax.jms.ConnectionFactory; import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.jms.pool.PooledConnectionFactory;
import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObject;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
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.autoconfigure.jms.JmsPoolConnectionFactoryFactory;
import org.springframework.boot.autoconfigure.jms.JmsProperties; import org.springframework.boot.autoconfigure.jms.JmsProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -94,20 +95,19 @@ class ActiveMQConnectionFactoryConfiguration {
} }
@Configuration @Configuration
@ConditionalOnClass({ PooledConnectionFactory.class, PooledObject.class }) @ConditionalOnClass({ JmsPoolConnectionFactory.class, PooledObject.class })
static class PooledConnectionFactoryConfiguration { static class PooledConnectionFactoryConfiguration {
@Bean(destroyMethod = "stop") @Bean(destroyMethod = "stop")
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false) @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false)
public PooledConnectionFactory pooledJmsConnectionFactory( public JmsPoolConnectionFactory pooledJmsConnectionFactory(
ActiveMQProperties properties, ActiveMQProperties properties,
ObjectProvider<List<ActiveMQConnectionFactoryCustomizer>> factoryCustomizers) { ObjectProvider<List<ActiveMQConnectionFactoryCustomizer>> factoryCustomizers) {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory( ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(
properties, factoryCustomizers.getIfAvailable()) properties, factoryCustomizers.getIfAvailable())
.createConnectionFactory(ActiveMQConnectionFactory.class); .createConnectionFactory(ActiveMQConnectionFactory.class);
return new PooledConnectionFactoryFactory(properties.getPool()) return new JmsPoolConnectionFactoryFactory(properties.getPool())
.createPooledConnectionFactory(connectionFactory); .createPooledConnectionFactory(connectionFactory);
} }
} }

@ -20,6 +20,7 @@ import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.boot.autoconfigure.jms.JmsPoolConnectionFactoryProperties;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.boot.context.properties.NestedConfigurationProperty;
@ -72,7 +73,7 @@ public class ActiveMQProperties {
private Duration sendTimeout = Duration.ofMillis(0); private Duration sendTimeout = Duration.ofMillis(0);
@NestedConfigurationProperty @NestedConfigurationProperty
private final PooledConnectionFactoryProperties pool = new PooledConnectionFactoryProperties(); private final JmsPoolConnectionFactoryProperties pool = new JmsPoolConnectionFactoryProperties();
private final Packages packages = new Packages(); private final Packages packages = new Packages();
@ -132,7 +133,7 @@ public class ActiveMQProperties {
this.sendTimeout = sendTimeout; this.sendTimeout = sendTimeout;
} }
public PooledConnectionFactoryProperties getPool() { public JmsPoolConnectionFactoryProperties getPool() {
return this.pool; return this.pool;
} }

@ -19,15 +19,15 @@ package org.springframework.boot.autoconfigure.jms.artemis;
import javax.jms.ConnectionFactory; import javax.jms.ConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.jms.pool.PooledConnectionFactory;
import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObject;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ListableBeanFactory;
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.autoconfigure.jms.JmsPoolConnectionFactoryFactory;
import org.springframework.boot.autoconfigure.jms.JmsProperties; import org.springframework.boot.autoconfigure.jms.JmsProperties;
import org.springframework.boot.autoconfigure.jms.activemq.PooledConnectionFactoryFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.jms.connection.CachingConnectionFactory; import org.springframework.jms.connection.CachingConnectionFactory;
@ -87,17 +87,17 @@ class ArtemisConnectionFactoryConfiguration {
} }
@Configuration @Configuration
@ConditionalOnClass({ PooledConnectionFactory.class, PooledObject.class }) @ConditionalOnClass({ JmsPoolConnectionFactory.class, PooledObject.class })
static class PooledConnectionFactoryConfiguration { static class PooledConnectionFactoryConfiguration {
@Bean(destroyMethod = "stop") @Bean(destroyMethod = "stop")
@ConditionalOnProperty(prefix = "spring.artemis.pool", name = "enabled", havingValue = "true", matchIfMissing = false) @ConditionalOnProperty(prefix = "spring.artemis.pool", name = "enabled", havingValue = "true", matchIfMissing = false)
public PooledConnectionFactory pooledJmsConnectionFactory( public JmsPoolConnectionFactory pooledJmsConnectionFactory(
ListableBeanFactory beanFactory, ArtemisProperties properties) { ListableBeanFactory beanFactory, ArtemisProperties properties) {
ActiveMQConnectionFactory connectionFactory = new ArtemisConnectionFactoryFactory( ActiveMQConnectionFactory connectionFactory = new ArtemisConnectionFactoryFactory(
beanFactory, properties) beanFactory, properties)
.createConnectionFactory(ActiveMQConnectionFactory.class); .createConnectionFactory(ActiveMQConnectionFactory.class);
return new PooledConnectionFactoryFactory(properties.getPool()) return new JmsPoolConnectionFactoryFactory(properties.getPool())
.createPooledConnectionFactory(connectionFactory); .createPooledConnectionFactory(connectionFactory);
} }

@ -23,7 +23,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants; import org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants;
import org.springframework.boot.autoconfigure.jms.activemq.PooledConnectionFactoryProperties; import org.springframework.boot.autoconfigure.jms.JmsPoolConnectionFactoryProperties;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.boot.context.properties.NestedConfigurationProperty;
@ -65,7 +65,7 @@ public class ArtemisProperties {
private final Embedded embedded = new Embedded(); private final Embedded embedded = new Embedded();
@NestedConfigurationProperty @NestedConfigurationProperty
private final PooledConnectionFactoryProperties pool = new PooledConnectionFactoryProperties(); private final JmsPoolConnectionFactoryProperties pool = new JmsPoolConnectionFactoryProperties();
public ArtemisMode getMode() { public ArtemisMode getMode() {
return this.mode; return this.mode;
@ -111,7 +111,7 @@ public class ArtemisProperties {
return this.embedded; return this.embedded;
} }
public PooledConnectionFactoryProperties getPool() { public JmsPoolConnectionFactoryProperties getPool() {
return this.pool; return this.pool;
} }

@ -49,6 +49,18 @@
"description": "Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).", "description": "Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).",
"defaultValue": true "defaultValue": true
}, },
{
"name": "spring.activemq.pool.maximum-active-session-per-connection",
"deprecation": {
"replacement": "spring.activemq.pool.max-sessions-per-connection"
}
},
{
"name": "spring.artemis.pool.maximum-active-session-per-connection",
"deprecation": {
"replacement": "spring.artemis.pool.max-sessions-per-connection"
}
},
{ {
"name": "spring.application.admin.enabled", "name": "spring.application.admin.enabled",
"type": "java.lang.Boolean", "type": "java.lang.Boolean",

@ -20,8 +20,8 @@ import javax.jms.ConnectionFactory;
import javax.jms.Session; import javax.jms.Session;
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.jms.pool.PooledConnectionFactory;
import org.junit.Test; import org.junit.Test;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.DirectFieldAccessor;
@ -369,8 +369,8 @@ public class JmsAutoConfigurationTests {
.withPropertyValues("spring.activemq.pool.enabled:true") .withPropertyValues("spring.activemq.pool.enabled:true")
.run((context) -> { .run((context) -> {
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
PooledConnectionFactory pool = context JmsPoolConnectionFactory pool = context
.getBean(PooledConnectionFactory.class); .getBean(JmsPoolConnectionFactory.class);
assertThat(jmsTemplate).isNotNull(); assertThat(jmsTemplate).isNotNull();
assertThat(pool).isNotNull(); assertThat(pool).isNotNull();
assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory());
@ -387,8 +387,8 @@ public class JmsAutoConfigurationTests {
"spring.activemq.inMemory:false") "spring.activemq.inMemory:false")
.run((context) -> { .run((context) -> {
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
PooledConnectionFactory pool = context JmsPoolConnectionFactory pool = context
.getBean(PooledConnectionFactory.class); .getBean(JmsPoolConnectionFactory.class);
assertThat(jmsTemplate).isNotNull(); assertThat(jmsTemplate).isNotNull();
assertThat(pool).isNotNull(); assertThat(pool).isNotNull();
assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory());
@ -405,8 +405,8 @@ public class JmsAutoConfigurationTests {
"spring.activemq.brokerUrl:tcp://remote-host:10000") "spring.activemq.brokerUrl:tcp://remote-host:10000")
.run((context) -> { .run((context) -> {
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
PooledConnectionFactory pool = context JmsPoolConnectionFactory pool = context
.getBean(PooledConnectionFactory.class); .getBean(JmsPoolConnectionFactory.class);
assertThat(jmsTemplate).isNotNull(); assertThat(jmsTemplate).isNotNull();
assertThat(pool).isNotNull(); assertThat(pool).isNotNull();
assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory());

@ -19,8 +19,8 @@ package org.springframework.boot.autoconfigure.jms.activemq;
import javax.jms.ConnectionFactory; import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.jms.pool.PooledConnectionFactory;
import org.junit.Test; import org.junit.Test;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
@ -165,71 +165,86 @@ public class ActiveMQAutoConfigurationTests {
} }
@Test @Test
public void defaultPooledConnectionFactoryIsApplied() { public void defaultPoolConnectionFactoryIsApplied() {
this.contextRunner.withUserConfiguration(EmptyConfiguration.class) this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
.withPropertyValues("spring.activemq.pool.enabled=true") .withPropertyValues("spring.activemq.pool.enabled=true")
.run((context) -> { .run((context) -> {
assertThat(context.getBeansOfType(PooledConnectionFactory.class)) assertThat(context.getBeansOfType(JmsPoolConnectionFactory.class))
.hasSize(1); .hasSize(1);
PooledConnectionFactory connectionFactory = context JmsPoolConnectionFactory connectionFactory = context
.getBean(PooledConnectionFactory.class); .getBean(JmsPoolConnectionFactory.class);
PooledConnectionFactory defaultFactory = new PooledConnectionFactory(); JmsPoolConnectionFactory defaultFactory = new JmsPoolConnectionFactory();
assertThat(connectionFactory.isBlockIfSessionPoolIsFull()) assertThat(connectionFactory.isBlockIfSessionPoolIsFull())
.isEqualTo(defaultFactory.isBlockIfSessionPoolIsFull()); .isEqualTo(defaultFactory.isBlockIfSessionPoolIsFull());
assertThat(connectionFactory.getBlockIfSessionPoolIsFullTimeout()) assertThat(connectionFactory.getBlockIfSessionPoolIsFullTimeout())
.isEqualTo( .isEqualTo(
defaultFactory.getBlockIfSessionPoolIsFullTimeout()); defaultFactory.getBlockIfSessionPoolIsFullTimeout());
assertThat(connectionFactory.getIdleTimeout()) assertThat(connectionFactory.getConnectionIdleTimeout())
.isEqualTo(defaultFactory.getIdleTimeout()); .isEqualTo(defaultFactory.getConnectionIdleTimeout());
assertThat(connectionFactory.getMaxConnections()) assertThat(connectionFactory.getMaxConnections())
.isEqualTo(defaultFactory.getMaxConnections()); .isEqualTo(defaultFactory.getMaxConnections());
assertThat(connectionFactory.getMaximumActiveSessionPerConnection()) assertThat(connectionFactory.getMaxSessionsPerConnection())
.isEqualTo(defaultFactory .isEqualTo(defaultFactory.getMaxSessionsPerConnection());
.getMaximumActiveSessionPerConnection()); assertThat(connectionFactory.getConnectionCheckInterval())
assertThat(connectionFactory.getTimeBetweenExpirationCheckMillis()) .isEqualTo(defaultFactory.getConnectionCheckInterval());
.isEqualTo(
defaultFactory.getTimeBetweenExpirationCheckMillis());
assertThat(connectionFactory.isUseAnonymousProducers()) assertThat(connectionFactory.isUseAnonymousProducers())
.isEqualTo(defaultFactory.isUseAnonymousProducers()); .isEqualTo(defaultFactory.isUseAnonymousProducers());
}); });
} }
@Test @Test
public void customPooledConnectionFactoryIsApplied() { public void customPoolConnectionFactoryIsApplied() {
this.contextRunner.withUserConfiguration(EmptyConfiguration.class) this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
.withPropertyValues("spring.activemq.pool.enabled=true", .withPropertyValues("spring.activemq.pool.enabled=true",
"spring.activemq.pool.blockIfFull=false", "spring.activemq.pool.blockIfFull=false",
"spring.activemq.pool.blockIfFullTimeout=64", "spring.activemq.pool.blockIfFullTimeout=64",
"spring.activemq.pool.idleTimeout=512", "spring.activemq.pool.idleTimeout=512",
"spring.activemq.pool.maxConnections=256", "spring.activemq.pool.maxConnections=256",
"spring.activemq.pool.maximumActiveSessionPerConnection=1024", "spring.activemq.pool.maxSessionsPerConnection=1024",
"spring.activemq.pool.timeBetweenExpirationCheck=2048", "spring.activemq.pool.timeBetweenExpirationCheck=2048",
"spring.activemq.pool.useAnonymousProducers=false") "spring.activemq.pool.useAnonymousProducers=false")
.run((context) -> { .run((context) -> {
assertThat(context.getBeansOfType(PooledConnectionFactory.class)) assertThat(context.getBeansOfType(JmsPoolConnectionFactory.class))
.hasSize(1); .hasSize(1);
PooledConnectionFactory connectionFactory = context JmsPoolConnectionFactory connectionFactory = context
.getBean(PooledConnectionFactory.class); .getBean(JmsPoolConnectionFactory.class);
assertThat(connectionFactory.isBlockIfSessionPoolIsFull()).isFalse(); assertThat(connectionFactory.isBlockIfSessionPoolIsFull()).isFalse();
assertThat(connectionFactory.getBlockIfSessionPoolIsFullTimeout()) assertThat(connectionFactory.getBlockIfSessionPoolIsFullTimeout())
.isEqualTo(64); .isEqualTo(64);
assertThat(connectionFactory.getIdleTimeout()).isEqualTo(512); assertThat(connectionFactory.getConnectionIdleTimeout())
.isEqualTo(512);
assertThat(connectionFactory.getMaxConnections()).isEqualTo(256); assertThat(connectionFactory.getMaxConnections()).isEqualTo(256);
assertThat(connectionFactory.getMaximumActiveSessionPerConnection()) assertThat(connectionFactory.getMaxSessionsPerConnection())
.isEqualTo(1024); .isEqualTo(1024);
assertThat(connectionFactory.getTimeBetweenExpirationCheckMillis()) assertThat(connectionFactory.getConnectionCheckInterval())
.isEqualTo(2048); .isEqualTo(2048);
assertThat(connectionFactory.isUseAnonymousProducers()).isFalse(); assertThat(connectionFactory.isUseAnonymousProducers()).isFalse();
}); });
} }
@Test @Test
public void pooledConnectionFactoryConfiguration() { @Deprecated
public void customPoolConnectionFactoryIsAppliedWithDeprecatedSettings() {
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
.withPropertyValues("spring.activemq.pool.enabled=true",
"spring.activemq.pool.maximumActiveSessionPerConnection=1024")
.run((context) -> {
assertThat(context.getBeansOfType(JmsPoolConnectionFactory.class))
.hasSize(1);
JmsPoolConnectionFactory connectionFactory = context
.getBean(JmsPoolConnectionFactory.class);
assertThat(connectionFactory.getMaxSessionsPerConnection())
.isEqualTo(1024);
});
}
@Test
public void poolConnectionFactoryConfiguration() {
this.contextRunner.withUserConfiguration(EmptyConfiguration.class) this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
.withPropertyValues("spring.activemq.pool.enabled:true") .withPropertyValues("spring.activemq.pool.enabled:true")
.run((context) -> { .run((context) -> {
ConnectionFactory factory = context.getBean(ConnectionFactory.class); ConnectionFactory factory = context.getBean(ConnectionFactory.class);
assertThat(factory).isInstanceOf(PooledConnectionFactory.class); assertThat(factory).isInstanceOf(JmsPoolConnectionFactory.class);
context.getSourceApplicationContext().close(); context.getSourceApplicationContext().close();
assertThat(factory.createConnection()).isNull(); assertThat(factory.createConnection()).isNull();
}); });

@ -37,10 +37,10 @@ import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl;
import org.apache.activemq.artemis.jms.server.config.impl.JMSQueueConfigurationImpl; import org.apache.activemq.artemis.jms.server.config.impl.JMSQueueConfigurationImpl;
import org.apache.activemq.artemis.jms.server.config.impl.TopicConfigurationImpl; import org.apache.activemq.artemis.jms.server.config.impl.TopicConfigurationImpl;
import org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS; import org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS;
import org.apache.activemq.jms.pool.PooledConnectionFactory;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
@ -350,81 +350,83 @@ public class ArtemisAutoConfigurationTests {
} }
@Test @Test
public void defaultPooledConnectionFactoryIsApplied() { public void defaultPoolConnectionFactoryIsApplied() {
this.contextRunner.withPropertyValues("spring.artemis.pool.enabled=true") this.contextRunner.withPropertyValues("spring.artemis.pool.enabled=true")
.run((context) -> { .run((context) -> {
assertThat(context.getBeansOfType(PooledConnectionFactory.class)) assertThat(context.getBeansOfType(JmsPoolConnectionFactory.class))
.hasSize(1); .hasSize(1);
PooledConnectionFactory connectionFactory = context JmsPoolConnectionFactory connectionFactory = context
.getBean(PooledConnectionFactory.class); .getBean(JmsPoolConnectionFactory.class);
PooledConnectionFactory defaultFactory = new PooledConnectionFactory(); JmsPoolConnectionFactory defaultFactory = new JmsPoolConnectionFactory();
assertThat(connectionFactory.isBlockIfSessionPoolIsFull()) assertThat(connectionFactory.isBlockIfSessionPoolIsFull())
.isEqualTo(defaultFactory.isBlockIfSessionPoolIsFull()); .isEqualTo(defaultFactory.isBlockIfSessionPoolIsFull());
assertThat(connectionFactory.getBlockIfSessionPoolIsFullTimeout()) assertThat(connectionFactory.getBlockIfSessionPoolIsFullTimeout())
.isEqualTo( .isEqualTo(
defaultFactory.getBlockIfSessionPoolIsFullTimeout()); defaultFactory.getBlockIfSessionPoolIsFullTimeout());
assertThat(connectionFactory.isCreateConnectionOnStartup()) assertThat(connectionFactory.getConnectionIdleTimeout())
.isEqualTo(defaultFactory.isCreateConnectionOnStartup()); .isEqualTo(defaultFactory.getConnectionIdleTimeout());
assertThat(connectionFactory.getExpiryTimeout())
.isEqualTo(defaultFactory.getExpiryTimeout());
assertThat(connectionFactory.getIdleTimeout())
.isEqualTo(defaultFactory.getIdleTimeout());
assertThat(connectionFactory.getMaxConnections()) assertThat(connectionFactory.getMaxConnections())
.isEqualTo(defaultFactory.getMaxConnections()); .isEqualTo(defaultFactory.getMaxConnections());
assertThat(connectionFactory.getMaximumActiveSessionPerConnection()) assertThat(connectionFactory.getMaxSessionsPerConnection())
.isEqualTo(defaultFactory .isEqualTo(defaultFactory.getMaxSessionsPerConnection());
.getMaximumActiveSessionPerConnection()); assertThat(connectionFactory.getConnectionCheckInterval())
assertThat(connectionFactory.isReconnectOnException()) .isEqualTo(defaultFactory.getConnectionCheckInterval());
.isEqualTo(defaultFactory.isReconnectOnException());
assertThat(connectionFactory.getTimeBetweenExpirationCheckMillis())
.isEqualTo(
defaultFactory.getTimeBetweenExpirationCheckMillis());
assertThat(connectionFactory.isUseAnonymousProducers()) assertThat(connectionFactory.isUseAnonymousProducers())
.isEqualTo(defaultFactory.isUseAnonymousProducers()); .isEqualTo(defaultFactory.isUseAnonymousProducers());
}); });
} }
@Test @Test
public void customPooledConnectionFactoryIsApplied() { public void customPoolConnectionFactoryIsApplied() {
this.contextRunner this.contextRunner
.withPropertyValues("spring.artemis.pool.enabled=true", .withPropertyValues("spring.artemis.pool.enabled=true",
"spring.artemis.pool.blockIfFull=false", "spring.artemis.pool.blockIfFull=false",
"spring.artemis.pool.blockIfFullTimeout=64", "spring.artemis.pool.blockIfFullTimeout=64",
"spring.artemis.pool.createConnectionOnStartup=false",
"spring.artemis.pool.expiryTimeout=4096",
"spring.artemis.pool.idleTimeout=512", "spring.artemis.pool.idleTimeout=512",
"spring.artemis.pool.maxConnections=256", "spring.artemis.pool.maxConnections=256",
"spring.artemis.pool.maximumActiveSessionPerConnection=1024", "spring.artemis.pool.maxSessionsPerConnection=1024",
"spring.artemis.pool.reconnectOnException=false",
"spring.artemis.pool.timeBetweenExpirationCheck=2048", "spring.artemis.pool.timeBetweenExpirationCheck=2048",
"spring.artemis.pool.useAnonymousProducers=false") "spring.artemis.pool.useAnonymousProducers=false")
.run((context) -> { .run((context) -> {
assertThat(context.getBeansOfType(PooledConnectionFactory.class)) assertThat(context.getBeansOfType(JmsPoolConnectionFactory.class))
.hasSize(1); .hasSize(1);
PooledConnectionFactory connectionFactory = context JmsPoolConnectionFactory connectionFactory = context
.getBean(PooledConnectionFactory.class); .getBean(JmsPoolConnectionFactory.class);
assertThat(connectionFactory.isBlockIfSessionPoolIsFull()).isFalse(); assertThat(connectionFactory.isBlockIfSessionPoolIsFull()).isFalse();
assertThat(connectionFactory.getBlockIfSessionPoolIsFullTimeout()) assertThat(connectionFactory.getBlockIfSessionPoolIsFullTimeout())
.isEqualTo(64); .isEqualTo(64);
assertThat(connectionFactory.isCreateConnectionOnStartup()).isFalse(); assertThat(connectionFactory.getConnectionIdleTimeout())
assertThat(connectionFactory.getExpiryTimeout()).isEqualTo(4096); .isEqualTo(512);
assertThat(connectionFactory.getIdleTimeout()).isEqualTo(512);
assertThat(connectionFactory.getMaxConnections()).isEqualTo(256); assertThat(connectionFactory.getMaxConnections()).isEqualTo(256);
assertThat(connectionFactory.getMaximumActiveSessionPerConnection()) assertThat(connectionFactory.getMaxSessionsPerConnection())
.isEqualTo(1024); .isEqualTo(1024);
assertThat(connectionFactory.isReconnectOnException()).isFalse(); assertThat(connectionFactory.getConnectionCheckInterval())
assertThat(connectionFactory.getTimeBetweenExpirationCheckMillis())
.isEqualTo(2048); .isEqualTo(2048);
assertThat(connectionFactory.isUseAnonymousProducers()).isFalse(); assertThat(connectionFactory.isUseAnonymousProducers()).isFalse();
}); });
} }
@Test @Test
public void pooledConnectionFactoryConfiguration() { public void customPoolConnectionFactoryIsAppliedWithDeprecatedSettings() {
this.contextRunner
.withPropertyValues("spring.artemis.pool.enabled=true",
"spring.artemis.pool.maximumActiveSessionPerConnection=1024")
.run((context) -> {
assertThat(context.getBeansOfType(JmsPoolConnectionFactory.class))
.hasSize(1);
JmsPoolConnectionFactory connectionFactory = context
.getBean(JmsPoolConnectionFactory.class);
assertThat(connectionFactory.getMaxSessionsPerConnection())
.isEqualTo(1024);
});
}
@Test
public void poolConnectionFactoryConfiguration() {
this.contextRunner.withPropertyValues("spring.artemis.pool.enabled:true") this.contextRunner.withPropertyValues("spring.artemis.pool.enabled:true")
.run((context) -> { .run((context) -> {
ConnectionFactory factory = context.getBean(ConnectionFactory.class); ConnectionFactory factory = context.getBean(ConnectionFactory.class);
assertThat(factory).isInstanceOf(PooledConnectionFactory.class); assertThat(factory).isInstanceOf(JmsPoolConnectionFactory.class);
context.getSourceApplicationContext().close(); context.getSourceApplicationContext().close();
assertThat(factory.createConnection()).isNull(); assertThat(factory.createConnection()).isNull();
}); });

@ -135,6 +135,7 @@
<netty.version>4.1.27.Final</netty.version> <netty.version>4.1.27.Final</netty.version>
<netty-tcnative.version>2.0.12.Final</netty-tcnative.version> <netty-tcnative.version>2.0.12.Final</netty-tcnative.version>
<nio-multipart-parser.version>1.1.0</nio-multipart-parser.version> <nio-multipart-parser.version>1.1.0</nio-multipart-parser.version>
<pooled-jms-version>1.0.2</pooled-jms-version>
<postgresql.version>42.2.4</postgresql.version> <postgresql.version>42.2.4</postgresql.version>
<quartz.version>2.3.0</quartz.version> <quartz.version>2.3.0</quartz.version>
<querydsl.version>4.2.1</querydsl.version> <querydsl.version>4.2.1</querydsl.version>
@ -2282,6 +2283,11 @@
<artifactId>mariadb-java-client</artifactId> <artifactId>mariadb-java-client</artifactId>
<version>${mariadb.version}</version> <version>${mariadb.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.messaginghub</groupId>
<artifactId>pooled-jms</artifactId>
<version>${pooled-jms-version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>

@ -962,10 +962,10 @@ content into your application. Rather, pick only the properties that you need.
spring.activemq.packages.trusted= # Comma-separated list of specific packages to trust (when not trusting all packages). spring.activemq.packages.trusted= # Comma-separated list of specific packages to trust (when not trusting all packages).
spring.activemq.pool.block-if-full=true # Whether to block when a connection is requested and the pool is full. Set it to false to throw a "JMSException" instead. spring.activemq.pool.block-if-full=true # Whether to block when a connection is requested and the pool is full. Set it to false to throw a "JMSException" instead.
spring.activemq.pool.block-if-full-timeout=-1ms # Blocking period before throwing an exception if the pool is still full. spring.activemq.pool.block-if-full-timeout=-1ms # Blocking period before throwing an exception if the pool is still full.
spring.activemq.pool.enabled=false # Whether a PooledConnectionFactory should be created, instead of a regular ConnectionFactory. spring.activemq.pool.enabled=false # Whether a JmsPoolConnectionFactory should be created, instead of a regular ConnectionFactory.
spring.activemq.pool.idle-timeout=30s # Connection idle timeout. spring.activemq.pool.idle-timeout=30s # Connection idle timeout.
spring.activemq.pool.max-connections=1 # Maximum number of pooled connections. spring.activemq.pool.max-connections=1 # Maximum number of pooled connections.
spring.activemq.pool.maximum-active-session-per-connection=500 # Maximum number of active sessions per connection. spring.activemq.pool.max-sessions-per-connection=500 # Maximum number of pooled sessions per connection in the pool.
spring.activemq.pool.time-between-expiration-check=-1ms # Time to sleep between runs of the idle connection eviction thread. When negative, no idle connection eviction thread runs. spring.activemq.pool.time-between-expiration-check=-1ms # Time to sleep between runs of the idle connection eviction thread. When negative, no idle connection eviction thread runs.
spring.activemq.pool.use-anonymous-producers=true # Whether to use only one anonymous "MessageProducer" instance. Set it to false to create one "MessageProducer" every time one is required. spring.activemq.pool.use-anonymous-producers=true # Whether to use only one anonymous "MessageProducer" instance. Set it to false to create one "MessageProducer" every time one is required.
@ -983,11 +983,11 @@ content into your application. Rather, pick only the properties that you need.
spring.artemis.pool.block-if-full=true # Whether to block when a connection is requested and the pool is full. Set it to false to throw a "JMSException" instead. spring.artemis.pool.block-if-full=true # Whether to block when a connection is requested and the pool is full. Set it to false to throw a "JMSException" instead.
spring.artemis.pool.block-if-full-timeout=-1ms # Blocking period before throwing an exception if the pool is still full. spring.artemis.pool.block-if-full-timeout=-1ms # Blocking period before throwing an exception if the pool is still full.
spring.artemis.pool.create-connection-on-startup=true # Whether to create a connection on startup. Can be used to warm up the pool on startup. spring.artemis.pool.create-connection-on-startup=true # Whether to create a connection on startup. Can be used to warm up the pool on startup.
spring.artemis.pool.enabled=false # Whether a PooledConnectionFactory should be created, instead of a regular ConnectionFactory. spring.artemis.pool.enabled=false # Whether a JmsPoolConnectionFactory should be created, instead of a regular ConnectionFactory.
spring.artemis.pool.expiry-timeout=0ms # Connection expiration timeout. spring.artemis.pool.expiry-timeout=0ms # Connection expiration timeout.
spring.artemis.pool.idle-timeout=30s # Connection idle timeout. spring.artemis.pool.idle-timeout=30s # Connection idle timeout.
spring.artemis.pool.max-connections=1 # Maximum number of pooled connections. spring.artemis.pool.max-connections=1 # Maximum number of pooled connections.
spring.artemis.pool.maximum-active-session-per-connection=500 # Maximum number of active sessions per connection. spring.artemis.pool.max-sessions-per-connection=500 # Maximum number of pooled sessions per connection in the pool.
spring.artemis.pool.reconnect-on-exception=true # Reset the connection when a "JMSException" occurs. spring.artemis.pool.reconnect-on-exception=true # Reset the connection when a "JMSException" occurs.
spring.artemis.pool.time-between-expiration-check=-1ms # Time to sleep between runs of the idle connection eviction thread. When negative, no idle connection eviction thread runs. spring.artemis.pool.time-between-expiration-check=-1ms # Time to sleep between runs of the idle connection eviction thread. When negative, no idle connection eviction thread runs.
spring.artemis.pool.use-anonymous-producers=true # Whether to use only one anonymous "MessageProducer" instance. Set it to false to create one "MessageProducer" every time one is required. spring.artemis.pool.use-anonymous-producers=true # Whether to use only one anonymous "MessageProducer" instance. Set it to false to create one "MessageProducer" every time one is required.

@ -5110,8 +5110,8 @@ sensible settings that you can control by external configuration properties in
---- ----
If you'd rather use native pooling, you can do so by adding a dependency to If you'd rather use native pooling, you can do so by adding a dependency to
`org.apache.activemq:activemq-jms-pool` and configuring the `PooledConnectionFactory` `org.messaginghub:pooled-jms` and configuring the `JmsPoolConnectionFactory` accordingly,
accordingly, as shown in the following example: as shown in the following example:
[source,properties,indent=0] [source,properties,indent=0]
---- ----
@ -5119,8 +5119,6 @@ accordingly, as shown in the following example:
spring.activemq.pool.max-connections=50 spring.activemq.pool.max-connections=50
---- ----
WARNING: `PooledConnectionFactory` is not JMS 2.0 compliant
TIP: See TIP: See
{sc-spring-boot-autoconfigure}/jms/activemq/ActiveMQProperties.{sc-ext}[`ActiveMQProperties`] {sc-spring-boot-autoconfigure}/jms/activemq/ActiveMQProperties.{sc-ext}[`ActiveMQProperties`]
for more of the supported options. You can also register an arbitrary number of beans for more of the supported options. You can also register an arbitrary number of beans
@ -5178,8 +5176,8 @@ sensible settings that you can control by external configuration properties in
---- ----
If you'd rather use native pooling, you can do so by adding a dependency to If you'd rather use native pooling, you can do so by adding a dependency to
`org.apache.activemq:activemq-jms-pool` and configuring the `PooledConnectionFactory` `org.messaginghub:pooled-jms` and configuring the `JmsPoolConnectionFactory` accordingly,
accordingly, as shown in the following example: as shown in the following example:
[source,properties,indent=0] [source,properties,indent=0]
---- ----

Loading…
Cancel
Save