Reputation: 1515
I'm using spring-boot-starter-activemq
with PoolFactory
. Everything works great and it's easy to configure via application.yaml
, but I cannot find correct way to inject my custom RedeliveryPolicy
. So the question is how can I do that?
Upvotes: 3
Views: 7065
Reputation: 154
I have tried the answer from @Iulian Rosca but it does not work for latest version of spring-boot-starter-activemq (I'm using version 2.2.0.RELEASE).
Spring provides many other implementation classes for ConnectionFactory
, such as CachingConnectionFactory
, JmsPooledConnectionFactory
,... and they are not inherited to each others. Therefore, the above solution need to refactor with many class type.
I discover Spring provide a functional interface ActiveMQConnectionFactoryCustomizer
, which will be injected when create ActiveMQ Connection Factory, whichever class no matter. It will customize connection factory class, you can set any properties, not only redelivery policy.
Here is my sample code:
@Configuration
public class RedeliveryCofiguration {
@Bean
public ActiveMQConnectionFactoryCustomizer configureRedeliveryPolicy() {
return connectionFactory ->
{
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
// configure redelivery policy
connectionFactory.setRedeliveryPolicy(redeliveryPolicy);
};
}
}
Upvotes: 10
Reputation: 1015
The re-delivery policy can be set on the connection factory. As the connection factory is configured automatically by spring boot, you can add a method to set it.
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Foo
{
@Bean
public InitializingBean connectionFactory(ActiveMQConnectionFactory connectionFactory)
{
return () ->
{
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
// configure redelivery policy
connectionFactory.setRedeliveryPolicy(redeliveryPolicy);
};
}
}
Update
As stated in one reply, the above solution works well when the following configuration is not set spring.activemq.pool.enabled = true
.
When using a pooled connection factory, Spring Boot auto-configures a org.apache.activemq.pool.PooledConnectionFactory
instead of org.apache.activemq.ActiveMQConnectionFactory
. This configuration happens here: org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectionFactoryConfiguration.PooledConnectionFactoryConfiguration#pooledJmsConnectionFactory
in the following line:
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(new ActiveMQConnectionFactoryFactory(properties,factoryCustomizers.getIfAvailable()).createConnectionFactory(ActiveMQConnectionFactory.class));
In order to make this work you have two options:
Use the common parent for ActiveMQConnectionFactory
and PooledConnectionFactory
when injecting the bean, which is javax.jms.ConnectionFactory
, and use instance-of and casting to set the redelivery policy.
@Bean
public InitializingBean connectionFactory(ConnectionFactory connectionFactory) {
if (connectionFactory instanceof ActiveMQConnectionFactory) {
return configureRedeliveryPolicy((ActiveMQConnectionFactory) connectionFactory);
} else if (connectionFactory instanceof PooledConnectionFactory) {
final PooledConnectionFactory pooledConnectionFactory = (PooledConnectionFactory) connectionFactory;
if (pooledConnectionFactory.getConnectionFactory() instanceof ActiveMQConnectionFactory) {
return configureRedeliveryPolicy((ActiveMQConnectionFactory) pooledConnectionFactory.getConnectionFactory());
}
}
// ...
}
Have two different custom initialization scenarios for each bean type, which is basically the same as 1, but you're leveraging ConditionalOnBean
instead of checking for the connectionFactory class type.
@Configuration
public class Foo {
@Bean
@ConditionalOnBean(ActiveMQConnectionFactory.class)
public InitializingBean connectionFactory(ActiveMQConnectionFactory connectionFactory) {
return configureRedeliveryPolicy(connectionFactory);
}
@Bean
@ConditionalOnBean(PooledConnectionFactory.class)
public InitializingBean pooledConnectionFactory(PooledConnectionFactory connectionFactory) {
if (connectionFactory.getConnectionFactory() instanceof ActiveMQConnectionFactory) {
return configureRedeliveryPolicy((ActiveMQConnectionFactory) connectionFactory.getConnectionFactory());
} else return () -> {
// do something else
};
}
private InitializingBean configureRedeliveryPolicy(ActiveMQConnectionFactory connectionFactory) {
return () ->
{
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
// configure redelivery policy
connectionFactory.setRedeliveryPolicy(redeliveryPolicy);
};
}
}
Upvotes: 7