Add support for JMS session caching
This commit adds support for CachingConnectionFactory for both Artemis and ActiveMQ. If connection pooling is not enabled explicitly, sessions, producers and consumers are cached. The factory can be further customized, including reverting to the raw ConnectionFactory, using the `spring.jms.*` namespace. Closes gh-12161
This commit is contained in:
@@ -40,6 +40,7 @@ import org.springframework.jms.config.JmsListenerConfigUtils;
|
||||
import org.springframework.jms.config.JmsListenerContainerFactory;
|
||||
import org.springframework.jms.config.JmsListenerEndpoint;
|
||||
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
|
||||
import org.springframework.jms.connection.CachingConnectionFactory;
|
||||
import org.springframework.jms.core.JmsMessagingTemplate;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
import org.springframework.jms.listener.DefaultMessageListenerContainer;
|
||||
@@ -74,15 +75,17 @@ public class JmsAutoConfigurationTests {
|
||||
}
|
||||
|
||||
private void testDefaultJmsConfiguration(AssertableApplicationContext loaded) {
|
||||
ActiveMQConnectionFactory factory = loaded
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
assertThat(loaded).hasSingleBean(ConnectionFactory.class);
|
||||
assertThat(loaded).hasSingleBean(CachingConnectionFactory.class);
|
||||
CachingConnectionFactory factory = loaded.getBean(CachingConnectionFactory.class);
|
||||
assertThat(factory.getTargetConnectionFactory())
|
||||
.isInstanceOf(ActiveMQConnectionFactory.class);
|
||||
JmsTemplate jmsTemplate = loaded.getBean(JmsTemplate.class);
|
||||
JmsMessagingTemplate messagingTemplate = loaded
|
||||
.getBean(JmsMessagingTemplate.class);
|
||||
assertThat(factory).isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate);
|
||||
assertThat(((ActiveMQConnectionFactory) jmsTemplate.getConnectionFactory())
|
||||
.getBrokerURL()).isEqualTo(ACTIVEMQ_EMBEDDED_URL);
|
||||
assertThat(getBrokerUrl(factory)).isEqualTo(ACTIVEMQ_EMBEDDED_URL);
|
||||
assertThat(loaded.containsBean("jmsListenerContainerFactory")).isTrue();
|
||||
}
|
||||
|
||||
@@ -313,9 +316,10 @@ public class JmsAutoConfigurationTests {
|
||||
public void testPubSubDomainOverride() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.withPropertyValues("spring.jms.pubSubDomain:false").run((context) -> {
|
||||
assertThat(context).hasSingleBean(JmsTemplate.class);
|
||||
assertThat(context).hasSingleBean(ConnectionFactory.class);
|
||||
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
|
||||
ActiveMQConnectionFactory factory = context
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
ConnectionFactory factory = context.getBean(ConnectionFactory.class);
|
||||
assertThat(jmsTemplate).isNotNull();
|
||||
assertThat(jmsTemplate.isPubSubDomain()).isFalse();
|
||||
assertThat(factory).isNotNull()
|
||||
@@ -327,15 +331,13 @@ public class JmsAutoConfigurationTests {
|
||||
public void testActiveMQOverriddenStandalone() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.withPropertyValues("spring.activemq.inMemory:false").run((context) -> {
|
||||
assertThat(context).hasSingleBean(JmsTemplate.class);
|
||||
assertThat(context).hasSingleBean(CachingConnectionFactory.class);
|
||||
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
|
||||
ActiveMQConnectionFactory factory = context
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
assertThat(jmsTemplate).isNotNull();
|
||||
assertThat(factory).isNotNull()
|
||||
.isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
assertThat(((ActiveMQConnectionFactory) jmsTemplate
|
||||
.getConnectionFactory()).getBrokerURL())
|
||||
.isEqualTo(ACTIVEMQ_NETWORK_URL);
|
||||
ConnectionFactory factory = context.getBean(ConnectionFactory.class);
|
||||
assertThat(factory).isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
assertThat(getBrokerUrl((CachingConnectionFactory) factory))
|
||||
.isEqualTo(ACTIVEMQ_NETWORK_URL);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -344,18 +346,23 @@ public class JmsAutoConfigurationTests {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.withPropertyValues("spring.activemq.brokerUrl:tcp://remote-host:10000")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JmsTemplate.class);
|
||||
assertThat(context).hasSingleBean(CachingConnectionFactory.class);
|
||||
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
|
||||
ActiveMQConnectionFactory factory = context
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
assertThat(jmsTemplate).isNotNull();
|
||||
assertThat(factory).isNotNull();
|
||||
ConnectionFactory factory = context.getBean(ConnectionFactory.class);
|
||||
assertThat(factory).isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
assertThat(((ActiveMQConnectionFactory) jmsTemplate
|
||||
.getConnectionFactory()).getBrokerURL())
|
||||
.isEqualTo("tcp://remote-host:10000");
|
||||
assertThat(getBrokerUrl((CachingConnectionFactory) factory))
|
||||
.isEqualTo("tcp://remote-host:10000");
|
||||
});
|
||||
}
|
||||
|
||||
private String getBrokerUrl(CachingConnectionFactory connectionFactory) {
|
||||
assertThat(connectionFactory.getTargetConnectionFactory())
|
||||
.isInstanceOf(ActiveMQConnectionFactory.class);
|
||||
return ((ActiveMQConnectionFactory) connectionFactory
|
||||
.getTargetConnectionFactory()).getBrokerURL();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActiveMQOverriddenPool() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
|
||||
@@ -27,6 +27,8 @@ import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jms.connection.CachingConnectionFactory;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -50,10 +52,13 @@ public class ActiveMQAutoConfigurationTests {
|
||||
public void brokerIsEmbeddedByDefault() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).getBean(ConnectionFactory.class)
|
||||
assertThat(context).hasSingleBean(CachingConnectionFactory.class);
|
||||
CachingConnectionFactory cachingConnectionFactory = context
|
||||
.getBean(CachingConnectionFactory.class);
|
||||
assertThat(cachingConnectionFactory.getTargetConnectionFactory())
|
||||
.isInstanceOf(ActiveMQConnectionFactory.class);
|
||||
assertThat(context.getBean(ActiveMQConnectionFactory.class)
|
||||
.getBrokerURL())
|
||||
assertThat(((ActiveMQConnectionFactory) cachingConnectionFactory
|
||||
.getTargetConnectionFactory()).getBrokerURL())
|
||||
.isEqualTo("vm://localhost?broker.persistent=false");
|
||||
});
|
||||
}
|
||||
@@ -68,10 +73,46 @@ public class ActiveMQAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultConnectionFactoryIsApplied() {
|
||||
public void connectionFactoryIsCachedByDefault() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.activemq.pool.enabled=false")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConnectionFactory.class);
|
||||
assertThat(context).hasSingleBean(CachingConnectionFactory.class);
|
||||
CachingConnectionFactory connectionFactory = context
|
||||
.getBean(CachingConnectionFactory.class);
|
||||
assertThat(connectionFactory.getTargetConnectionFactory())
|
||||
.isInstanceOf(ActiveMQConnectionFactory.class);
|
||||
assertThat(ReflectionTestUtils.getField(connectionFactory,
|
||||
"cacheConsumers")).isEqualTo(false);
|
||||
assertThat(ReflectionTestUtils.getField(connectionFactory,
|
||||
"cacheProducers")).isEqualTo(true);
|
||||
assertThat(connectionFactory.getSessionCacheSize()).isEqualTo(1);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionFactoryCachingCanBeCustomized() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.jms.cache.consumers=true",
|
||||
"spring.jms.cache.producers=false",
|
||||
"spring.jms.cache.session-cache-size=10")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConnectionFactory.class);
|
||||
assertThat(context).hasSingleBean(CachingConnectionFactory.class);
|
||||
CachingConnectionFactory connectionFactory = context
|
||||
.getBean(CachingConnectionFactory.class);
|
||||
assertThat(ReflectionTestUtils.getField(connectionFactory,
|
||||
"cacheConsumers")).isEqualTo(true);
|
||||
assertThat(ReflectionTestUtils.getField(connectionFactory,
|
||||
"cacheProducers")).isEqualTo(false);
|
||||
assertThat(connectionFactory.getSessionCacheSize()).isEqualTo(10);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionFactoryCachingCanBeDisabled() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.jms.cache.enabled=false").run((context) -> {
|
||||
assertThat(context.getBeansOfType(ActiveMQConnectionFactory.class))
|
||||
.hasSize(1);
|
||||
ActiveMQConnectionFactory connectionFactory = context
|
||||
@@ -99,7 +140,7 @@ public class ActiveMQAutoConfigurationTests {
|
||||
@Test
|
||||
public void customConnectionFactoryIsApplied() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.activemq.pool.enabled=false",
|
||||
.withPropertyValues("spring.jms.cache.enabled=false",
|
||||
"spring.activemq.brokerUrl=vm://localhost?useJmx=false&broker.persistent=false",
|
||||
"spring.activemq.user=foo", "spring.activemq.password=bar",
|
||||
"spring.activemq.closeTimeout=500",
|
||||
|
||||
@@ -48,10 +48,12 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jms.connection.CachingConnectionFactory;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
import org.springframework.jms.core.SessionCallback;
|
||||
import org.springframework.jms.support.destination.DestinationResolver;
|
||||
import org.springframework.jms.support.destination.DynamicDestinationResolver;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -70,17 +72,69 @@ public class ArtemisAutoConfigurationTests {
|
||||
.withConfiguration(AutoConfigurations.of(ArtemisAutoConfiguration.class,
|
||||
JmsAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void connectionFactoryIsCachedByDefault() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConnectionFactory.class);
|
||||
assertThat(context).hasSingleBean(CachingConnectionFactory.class);
|
||||
CachingConnectionFactory connectionFactory = context
|
||||
.getBean(CachingConnectionFactory.class);
|
||||
assertThat(connectionFactory.getTargetConnectionFactory())
|
||||
.isInstanceOf(ActiveMQConnectionFactory.class);
|
||||
assertThat(ReflectionTestUtils.getField(connectionFactory,
|
||||
"cacheConsumers")).isEqualTo(false);
|
||||
assertThat(ReflectionTestUtils.getField(connectionFactory,
|
||||
"cacheProducers")).isEqualTo(true);
|
||||
assertThat(connectionFactory.getSessionCacheSize()).isEqualTo(1);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionFactoryCachingCanBeCustomized() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.jms.cache.consumers=true",
|
||||
"spring.jms.cache.producers=false",
|
||||
"spring.jms.cache.session-cache-size=10")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConnectionFactory.class);
|
||||
assertThat(context).hasSingleBean(CachingConnectionFactory.class);
|
||||
CachingConnectionFactory connectionFactory = context
|
||||
.getBean(CachingConnectionFactory.class);
|
||||
assertThat(ReflectionTestUtils.getField(connectionFactory,
|
||||
"cacheConsumers")).isEqualTo(true);
|
||||
assertThat(ReflectionTestUtils.getField(connectionFactory,
|
||||
"cacheProducers")).isEqualTo(false);
|
||||
assertThat(connectionFactory.getSessionCacheSize()).isEqualTo(10);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionFactoryCachingCanBeDisabled() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.jms.cache.enabled=false").run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConnectionFactory.class);
|
||||
assertThat(context).doesNotHaveBean(CachingConnectionFactory.class);
|
||||
assertThat(context.getBean(ConnectionFactory.class))
|
||||
.isInstanceOf(ActiveMQConnectionFactory.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nativeConnectionFactory() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.withPropertyValues("spring.artemis.mode:native").run((context) -> {
|
||||
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
|
||||
ActiveMQConnectionFactory factory = context
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
assertThat(factory).isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
assertNettyConnectionFactory(factory, "localhost", 61616);
|
||||
assertThat(factory.getUser()).isNull();
|
||||
assertThat(factory.getPassword()).isNull();
|
||||
ConnectionFactory connectionFactory = context
|
||||
.getBean(ConnectionFactory.class);
|
||||
assertThat(connectionFactory)
|
||||
.isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
ActiveMQConnectionFactory activeMQConnectionFactory = getActiveMQConnectionFactory(
|
||||
connectionFactory);
|
||||
assertNettyConnectionFactory(activeMQConnectionFactory, "localhost",
|
||||
61616);
|
||||
assertThat(activeMQConnectionFactory.getUser()).isNull();
|
||||
assertThat(activeMQConnectionFactory.getPassword()).isNull();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -90,9 +144,10 @@ public class ArtemisAutoConfigurationTests {
|
||||
.withPropertyValues("spring.artemis.mode:native",
|
||||
"spring.artemis.host:192.168.1.144", "spring.artemis.port:9876")
|
||||
.run((context) -> {
|
||||
ActiveMQConnectionFactory factory = context
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
assertNettyConnectionFactory(factory, "192.168.1.144", 9876);
|
||||
assertNettyConnectionFactory(
|
||||
getActiveMQConnectionFactory(
|
||||
context.getBean(ConnectionFactory.class)),
|
||||
"192.168.1.144", 9876);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -103,12 +158,17 @@ public class ArtemisAutoConfigurationTests {
|
||||
"spring.artemis.user:user", "spring.artemis.password:secret")
|
||||
.run((context) -> {
|
||||
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
|
||||
ActiveMQConnectionFactory factory = context
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
assertThat(factory).isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
assertNettyConnectionFactory(factory, "localhost", 61616);
|
||||
assertThat(factory.getUser()).isEqualTo("user");
|
||||
assertThat(factory.getPassword()).isEqualTo("secret");
|
||||
ConnectionFactory connectionFactory = context
|
||||
.getBean(ConnectionFactory.class);
|
||||
assertThat(connectionFactory)
|
||||
.isEqualTo(jmsTemplate.getConnectionFactory());
|
||||
ActiveMQConnectionFactory activeMQConnectionFactory = getActiveMQConnectionFactory(
|
||||
connectionFactory);
|
||||
assertNettyConnectionFactory(activeMQConnectionFactory, "localhost",
|
||||
61616);
|
||||
assertThat(activeMQConnectionFactory.getUser()).isEqualTo("user");
|
||||
assertThat(activeMQConnectionFactory.getPassword())
|
||||
.isEqualTo("secret");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -125,9 +185,8 @@ public class ArtemisAutoConfigurationTests {
|
||||
org.apache.activemq.artemis.core.config.Configuration.class);
|
||||
assertThat(configuration.isPersistenceEnabled()).isFalse();
|
||||
assertThat(configuration.isSecurityEnabled()).isFalse();
|
||||
ActiveMQConnectionFactory factory = context
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
assertInVmConnectionFactory(factory);
|
||||
assertInVmConnectionFactory(getActiveMQConnectionFactory(
|
||||
context.getBean(ConnectionFactory.class)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -142,9 +201,8 @@ public class ArtemisAutoConfigurationTests {
|
||||
org.apache.activemq.artemis.core.config.Configuration.class);
|
||||
assertThat(configuration.isPersistenceEnabled()).isFalse();
|
||||
assertThat(configuration.isSecurityEnabled()).isFalse();
|
||||
ActiveMQConnectionFactory factory = context
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
assertInVmConnectionFactory(factory);
|
||||
assertInVmConnectionFactory(getActiveMQConnectionFactory(
|
||||
context.getBean(ConnectionFactory.class)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -155,9 +213,10 @@ public class ArtemisAutoConfigurationTests {
|
||||
.withPropertyValues("spring.artemis.embedded.enabled:false")
|
||||
.run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(EmbeddedJMS.class);
|
||||
ActiveMQConnectionFactory factory = context
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
assertNettyConnectionFactory(factory, "localhost", 61616);
|
||||
assertNettyConnectionFactory(
|
||||
getActiveMQConnectionFactory(
|
||||
context.getBean(ConnectionFactory.class)),
|
||||
"localhost", 61616);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -169,9 +228,8 @@ public class ArtemisAutoConfigurationTests {
|
||||
"spring.artemis.embedded.enabled:false")
|
||||
.run((context) -> {
|
||||
assertThat(context.getBeansOfType(EmbeddedJMS.class)).isEmpty();
|
||||
ActiveMQConnectionFactory connectionFactory = context
|
||||
.getBean(ActiveMQConnectionFactory.class);
|
||||
assertInVmConnectionFactory(connectionFactory);
|
||||
assertInVmConnectionFactory(getActiveMQConnectionFactory(
|
||||
context.getBean(ConnectionFactory.class)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -374,6 +432,13 @@ public class ArtemisAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
private ActiveMQConnectionFactory getActiveMQConnectionFactory(
|
||||
ConnectionFactory connectionFactory) {
|
||||
assertThat(connectionFactory).isInstanceOf(CachingConnectionFactory.class);
|
||||
return (ActiveMQConnectionFactory) ((CachingConnectionFactory) connectionFactory)
|
||||
.getTargetConnectionFactory();
|
||||
}
|
||||
|
||||
private TransportConfiguration assertInVmConnectionFactory(
|
||||
ActiveMQConnectionFactory connectionFactory) {
|
||||
TransportConfiguration transportConfig = getSingleTransportConfiguration(
|
||||
|
||||
Reference in New Issue
Block a user