美文网首页
记一次工作中使用spring-boot-activemq的排错经

记一次工作中使用spring-boot-activemq的排错经

作者: renmen2000 | 来源:发表于2020-05-30 11:06 被阅读0次

一. 问题描述

最近在使用新版本的spring boot连接activeMQ时(2.1.1.RELEASE)遇到了一个问题:引入依赖后

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.1.RELEASE</version>
    <relativePath/>
</parent>
 
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-activemq</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-pool</artifactId>
    </dependency>
</dependencies>

如果开启activemq的连接池,则 JmsTemplate 就无法自动注入进来,如下所示:


2019032009243494.png

但是如果用老版本的spring boot(1.5.13.RELEASE),同样的配置下则没有这个问题。

经过分析源码,终于找到了这个问题的答案

二. 原因

对spring boot activemq的配置

  activemq:
    # 连接用户名
    user: admin
    # 连接密码
    password: admin
    # mq broker地址
    broker-url: tcp://192.168.1.49:61616
    pool:
      #启用连接池
      enabled: true
      #连接池最大连接数
      max-connections: 20
      #空闲的连接过期时间,默认为30秒
      idle-timeout: 30000

在2.X版本中:

package org.springframework.boot.autoconfigure.jms.activemq;
 
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
 
 
/**
 * Configuration for ActiveMQ {@link ConnectionFactory}.
 *
 * @author Greg Turnquist
 * @author Stephane Nicoll
 * @author Phillip Webb
 * @author Andy Wilkinson
 * @author Aurélien Leboulanger
 * @since 1.1.0
 */
@Configuration
@ConditionalOnMissingBean(ConnectionFactory.class)
class ActiveMQConnectionFactoryConfiguration {
 
        @Configuration
    @ConditionalOnClass(CachingConnectionFactory.class)
    @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", matchIfMissing = true)
    static class SimpleConnectionFactoryConfiguration {
 
        private final JmsProperties jmsProperties;
 
        private final ActiveMQProperties properties;
 
        private final List<ActiveMQConnectionFactoryCustomizer> connectionFactoryCustomizers;
 
        SimpleConnectionFactoryConfiguration(JmsProperties jmsProperties,
                ActiveMQProperties properties,
                ObjectProvider<ActiveMQConnectionFactoryCustomizer> connectionFactoryCustomizers) {
            this.jmsProperties = jmsProperties;
            this.properties = properties;
            this.connectionFactoryCustomizers = connectionFactoryCustomizers
                    .orderedStream().collect(Collectors.toList());
        }
 
        @Bean
        @ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "true", matchIfMissing = true)
        public CachingConnectionFactory cachingJmsConnectionFactory() {
            JmsProperties.Cache cacheProperties = this.jmsProperties.getCache();
            CachingConnectionFactory connectionFactory = new CachingConnectionFactory(
                    createConnectionFactory());
            connectionFactory.setCacheConsumers(cacheProperties.isConsumers());
            connectionFactory.setCacheProducers(cacheProperties.isProducers());
            connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize());
            return connectionFactory;
        }
 
        @Bean
        @ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "false")
        public ActiveMQConnectionFactory jmsConnectionFactory() {
            return createConnectionFactory();
        }
 
        private ActiveMQConnectionFactory createConnectionFactory() {
            return new ActiveMQConnectionFactoryFactory(this.properties,
                    this.connectionFactoryCustomizers)
                            .createConnectionFactory(ActiveMQConnectionFactory.class);
        }
 
    }
 
 
    @Configuration
    @ConditionalOnClass({ JmsPoolConnectionFactory.class, PooledObject.class })
    static class PooledConnectionFactoryConfiguration {
 
        @Bean(destroyMethod = "stop")
        @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false)
        public JmsPoolConnectionFactory pooledJmsConnectionFactory(
                ActiveMQProperties properties,
                ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) {
            ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(
                    properties,
                    factoryCustomizers.orderedStream().collect(Collectors.toList()))
                            .createConnectionFactory(ActiveMQConnectionFactory.class);
            return new JmsPoolConnectionFactoryFactory(properties.getPool())
                    .createPooledConnectionFactory(connectionFactory);
        }
 
    }
 
}

由以上代码可知,当配置文件中存在 "spring.activemq.pool.enabled=true" 时,会使用 JmsPoolConnectionFactory,但是这个类(org.messaginghub.pooled.jms.JmsPoolConnectionFactory)并不在activemq-pool这个依赖中,所以导致ConnectionFactory无法注入,因此 JmsTemplate也就无法由Spring容器来管理。因此需要引入别的依赖,如下所示:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
    <groupId>org.messaginghub</groupId>
    <artifactId>pooled-jms</artifactId>
</dependency>

而在1.5.13版本中

package org.springframework.boot.autoconfigure.jms.activemq;
 
 
import org.apache.activemq.pool.PooledConnectionFactory;
 
 
/**
 * Configuration for ActiveMQ {@link ConnectionFactory}.
 *
 * @author Greg Turnquist
 * @author Stephane Nicoll
 * @author Phillip Webb
 * @author Andy Wilkinson
 * @author Aurélien Leboulanger
 * @since 1.1.0
 */
@Configuration
@ConditionalOnMissingBean(ConnectionFactory.class)
class ActiveMQConnectionFactoryConfiguration {
 
    @Bean
    @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", matchIfMissing = true)
    public ActiveMQConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
            ObjectProvider<List<ActiveMQConnectionFactoryCustomizer>> factoryCustomizers) {
        return new ActiveMQConnectionFactoryFactory(properties,
                factoryCustomizers.getIfAvailable())
                        .createConnectionFactory(ActiveMQConnectionFactory.class);
    }
 
    @Configuration
    @ConditionalOnClass(PooledConnectionFactory.class)
    static class PooledConnectionFactoryConfiguration {
 
        @Bean(destroyMethod = "stop")
        @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false)
        @ConfigurationProperties(prefix = "spring.activemq.pool.configuration")
        public PooledConnectionFactory pooledJmsConnectionFactory(
                ActiveMQProperties properties,
                ObjectProvider<List<ActiveMQConnectionFactoryCustomizer>> factoryCustomizers) {
            PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(
                    new ActiveMQConnectionFactoryFactory(properties,
                            factoryCustomizers.getIfAvailable()).createConnectionFactory(
                                    ActiveMQConnectionFactory.class));
            ActiveMQProperties.Pool pool = properties.getPool();
            pooledConnectionFactory.setBlockIfSessionPoolIsFull(pool.isBlockIfFull());
            pooledConnectionFactory
                    .setBlockIfSessionPoolIsFullTimeout(pool.getBlockIfFullTimeout());
            pooledConnectionFactory
                    .setCreateConnectionOnStartup(pool.isCreateConnectionOnStartup());
            pooledConnectionFactory.setExpiryTimeout(pool.getExpiryTimeout());
            pooledConnectionFactory.setIdleTimeout(pool.getIdleTimeout());
            pooledConnectionFactory.setMaxConnections(pool.getMaxConnections());
            pooledConnectionFactory.setMaximumActiveSessionPerConnection(
                    pool.getMaximumActiveSessionPerConnection());
            pooledConnectionFactory
                    .setReconnectOnException(pool.isReconnectOnException());
            pooledConnectionFactory.setTimeBetweenExpirationCheckMillis(
                    pool.getTimeBetweenExpirationCheck());
            pooledConnectionFactory
                    .setUseAnonymousProducers(pool.isUseAnonymousProducers());
            return pooledConnectionFactory;
        }
 
    }
 
}

当 "spring.activemq.pool.enabled=true" 这个配置项存在时,往spring容器中注入的是 PooledConnectionFactory 这个类,而这个类,在activemq-pool这个依赖中,因此,在1.5.13的版本中,可以依赖activemq-pool。

相关文章

  • 记一次工作中使用spring-boot-activemq的排错经

    一. 问题描述 最近在使用新版本的spring boot连接activeMQ时(2.1.1.RELEASE)遇到了...

  • 记databinding的一次排错

    某天一早我过来打开Android studio,一运行发现突然报错了,错误如下: 69个错误,2个警告,这些错误都...

  • 记一次mysql排错—死锁

    故事起源:ZY问我,有没有遇到过在mysql客户端执行了添加表字段的的命令,显示成功了,在客户端也看的到,为啥到服...

  • 记一次辛酸的排错过程

    《PIL:从入门到放弃》 最近在学习用Python写爬虫,在模拟登录的时候遇到了这样一个问题,如何处理网站的验证码...

  • 磁盘【故障集合】-欢迎补充

    一、挂载分区中的报错及排错二、各种提示集合 一、挂载分区中的报错及排错 1.fdisk /dev/sdb 第一次...

  • 记一次关于MYSQL的排错过程

    今天打开网站发现数据无法加载,只有基础的静态页面。。。本来以为是后端应用挂了,于是打算登录查看一下. 使用ssh登...

  • 记一次奇葩的排错经历(删除cell)

    慎重!慎重!照这个方法删除cell后,会导致已存在的虚拟机无法获取详情! 此文后续 https://www.jia...

  • 一次排错的收获

    前段时间,定投践行群迎来了新的课程——李俊老师的编程课,让我对学习编程这件事有了系统全面的理解,而且另外印象最深刻...

  • 一次mysql排错

    最近mac上折腾mysql,apache。mysql装完之后,可以正常使用。随后又折腾了一下其他软件,再回过头来的...

  • 解决Failure to find org.glassfish:

    问题描述 Maven项目编译打包报错 排错步骤 使用mvn dependency:tree,找出引用javax.e...

网友评论

      本文标题:记一次工作中使用spring-boot-activemq的排错经

      本文链接:https://www.haomeiwen.com/subject/zkeczhtx.html