【问题标题】:ConnectionFactory get destroyed before camelConnectionFactory 在骆驼之前被摧毁
【发布时间】:2017-10-02 22:47:58
【问题描述】:

我正在使用带有骆驼和 ActiveMQ 的 spring-boot。

我正在通过@EnableJms 注释使用activemq 自动配置。 但是创建我自己的 ActiveMQComponent 以在所有队列上启用“transacted(true)”。

@Bean(name = "activemq")
@ConditionalOnClass(ActiveMQComponent.class)
public ActiveMQComponent activeMQComponent(ConnectionFactory connectionFactory) {
    ActiveMQComponent activeMQComponent = new ActiveMQComponent();
    activeMQComponent.setConnectionFactory(connectionFactory);
    activeMQComponent.setTransacted(true);
    activeMQComponent.setTransactionManager(jmsTransactionManager(connectionFactory));
    return activeMQComponent;
}

它运行良好,但是当我尝试正常关闭应用程序时。 PooledConnectionFactory 在骆驼正常关闭发生之前被销毁。

导致大量错误,导致路线无法正确停止。

像这个错误的 20 倍:

2017-05-04 18:21:59.748  WARN 12188 --- [er[test.queue]] o.a.activemq.jms.pool.PooledSession      : Caught exception trying rollback() when putting session back into the pool, will invalidate. javax.jms.IllegalStateException: The Session is closed

接着是:

2017-05-04 18:21:59.748  INFO 12188 --- [      Thread-18] o.a.camel.spring.SpringCamelContext      : Apache Camel 2.18.3 (CamelContext: route) is shutting down

然后:

2017-05-04 18:21:59.766 INFO 12188 --- [ - ShutdownTask] o.a.camel.impl.DefaultShutdownStrategy : Waiting as there are still 1 inflight and pending exchanges to complete, timeout in 300 seconds. Inflights per route: [test2 = 1]

谁能帮我配置spring-boot camel activemq和优雅关机?

谢谢

更新: 这是我的 pom.xml 的示例:

        <properties>

        <!-- Spring -->
        <spring-boot.version>1.4.3.RELEASE</spring-boot.version>

        <!-- Camel -->
        <camel-spring-boot.version>2.18.3</camel-spring-boot.version>
    </properties>
    ....

    <!-- Camel BOM -->
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring-boot-dependencies</artifactId>
            <version>${camel-spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
...
    <!-- Spring -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator</artifactId>
    </dependency>

    <!-- ActiveMQ -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-activemq</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-camel</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-pool</artifactId>
    </dependency>

    <!-- Camel -->
    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-spring-boot-starter</artifactId>
    </dependency>

更新 2: 经过进一步调查并创建了一个新项目,并一一添加了每个修改,我已经隔离了问题。

在我添加特定端点之前,关闭工作正常:

@EndpointInject(uri = "direct:aaa")
private Endpoint errorHandling;

使用:

private String errorHandling = "direct:aaa";

不会产生错误。

似乎使用@EndpointInject 是先关闭activemq

更新 3:

发现 SpringCamelContext 没有实现 ApplicationListener,因此它的方法“onApplicationEvent”没有被称为处理骆驼的“shutdownEager”。

【问题讨论】:

  • 方法 SpringCamelContext.onApplicationEvent 使用 ContextStoppedEvent 调用,将日志转为跟踪或调试
  • 添加断点,它从未调用过。创建了一个监听这个事件的组件,然后手动调用 springCamelContext.onApplicationEvent(event)。它似乎工作

标签: spring-boot apache-camel activemq


【解决方案1】:

重要的是使用 Camel Spring Boot Starter。

http://camel.apache.org/spring-boot.html

如何在我的 Spring Boot 应用程序中启用 Camel 自动配置?

只需将 camel-spring-boot jar 放入您的类路径:

 <dependency>
     <groupId>org.apache.camel</groupId>
     <artifactId>camel-spring-boot</artifactId>
     <version>${camel.version}</version> <!-- use the same version as your Camel core version -->
</dependency>

camel-spring-boot jar 带有 spring.factories 文件,因此只要您将该依赖项添加到类路径中,Spring Boot 就会自动为您自动配置 Camel。耶!那很快;)。

自动配置的骆驼上下文

Camel 自动配置提供的最重要的功能是 CamelContext 实例。

Camel 自动配置会为您创建 SpringCamelContext,并负责该上下文的正确初始化和关闭。

创建的 Camel 上下文也注册在 Spring 应用程序上下文中(在 camelContext bean 名称下),因此您可以像访问任何其他 Spring bean 一样访问它。

@Configuration
public class MyAppConfig {

  @Autowired
  CamelContext camelContext;

  @Bean
  MyService myService() {
    return new DefaultMyService(camelContext);
  }
}

【讨论】:

  • 我用我的 pom.xml 示例更新了我的问题。我正在使用camel-spring-boot,一切都是自动配置的。问题实际上是在骆驼路线之前被破坏的activemq。
  • 添加另一个bean定义,如connectionFactories、broker、camel
  • 更新了我的问题,它与@EndpointInject 不知道如何/为什么有关
  • 尝试使用@Produce(uri = "direct:aaa")
【解决方案2】:

显然是因为https://issues.apache.org/jira/browse/CAMEL-2607 SpringCamelContext 不再实现 ApplicationListener 接口。

由于我使用的是 spring-boot 自动配置,所以我没有使用添加侦听器的 CamelContextFactoryBean。

有一个临时修复,我创建了一个组件来监听 ApplicationEvent 并将它们分派给 SpringCamelContext 方法:

public class SpringCamelContextFix implements ApplicationListener<ApplicationEvent> {

private SpringCamelContext camelContext;

public SpringCamelContextFix(SpringCamelContext camelContext) {
    this.camelContext = camelContext;
}

@Override
public void onApplicationEvent(ApplicationEvent event) {
    camelContext.onApplicationEvent(event);
}

}

【讨论】:

    【解决方案3】:

    我在使用 Spring Boot、ActiveMQ 或 A-MQ 和 Camel(版本 2.18.1.redhat-000012)运行单元/集成测试时遇到了同样的问题。显然,当 Spring Boot 关闭时,JMS 线程池在 Camel 上下文关闭之前关闭,这是错误的顺序。 @John D 在Camel users mailing list thread 中提供了一个代码修复,这与他在此线程中提供的类似。这是对我有用的 John D 代码版本:

    @Component 
    public class SpringCamelContextFix implements 
    ApplicationListener<ApplicationEvent> {
    
        @Inject
        private SpringCamelContext camelContext;
    
        public SpringCamelContextFix(SpringCamelContext camelContext) {
            this.camelContext = camelContext;
        }
    
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            camelContext.onApplicationEvent(event);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-09
      • 1970-01-01
      • 2022-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 2016-02-21
      相关资源
      最近更新 更多