【问题标题】:Camel not starting in spring骆驼不从春天开始
【发布时间】:2018-05-30 01:49:41
【问题描述】:

我可以使用 maven (mvn camel:run) 中的 camel-maven-plugin 运行我的 Camel 应用程序。读取了 camel-context.xml 文件,并且我的路线正确启动。

当我尝试在春季执行这些骆驼路线时,我的问题就出现了。当春天开始时,我没有看到任何来自 Camel 的日志,就像我直接运行骆驼插件时所做的那样。我也没有任何证据表明任何与骆驼有关的事情已经开始。我缺少什么配置才能成功运行应用程序?我目前正在尝试通过嵌入式 tomcat 实例运行它(请参阅下面的 mvn 配置文件)。我想我需要做一些独特的事情才能让 spring 找到骆驼的背景。

感谢您的所有帮助!

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
    <groupId>---</groupId>
    <artifactId>---</artifactId>
    <version>1.0.6-SNAPSHOT</version>
</parent>

<artifactId>---</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>${packaging.type}</packaging>

<properties>
    <jacoco.minimum.code.coverage>0.8</jacoco.minimum.code.coverage>
    <packaging.type>war</packaging.type>
    <failOnMissingWebXml>false</failOnMissingWebXml>
    <org.apache.camel.version>2.16.0</org.apache.camel.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-csv</artifactId>
    </dependency>


    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-core</artifactId>
        <version>2.19.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-aws</artifactId>
        <version>2.19.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-spring</artifactId>
        <version>2.19.2</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-maven-plugin</artifactId>
            <version>2.19.2</version>
        </plugin>
    </plugins>
</build>


<profiles>
    <!-- Default build profile for generating war -->
    <profile>
        <id>war</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <packaging.type>war</packaging.type>
            <log.dir>${catalina.base}/logs</log.dir>
            <!-- updates bootstrap.properties -->
            <config.override.path>file:${catalina.base}/conf</config.override.path>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <scope>provided</scope>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>2.6</version>
                    <configuration>
                        <descriptor>/src/main/resources/deployablecontent.xml</descriptor>
                        <tarLongFileMode>posix</tarLongFileMode>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>single</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

            </plugins>
        </build>
    </profile>

    <!-- Build profile for stand-alone java application with embedded Tomcat 
        Container -->
    <profile>
        <id>embedded</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <properties>
            <packaging.type>jar</packaging.type>
            <log.dir>logs</log.dir>
            <!-- updates bootstrap.properties -->
            <config.override.path>./conf</config.override.path>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.camel</groupId>
                    <artifactId>camel-maven-plugin</artifactId>
                    <version>2.19.2</version>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

我的 Routebuilder 类:

public class PriorityCodeSourcesUpdaterRouteBuilder extends RouteBuilder {

private Endpoint incomingEndpoint;
private Endpoint outgoingEndpoint;

@Override
public void configure() throws Exception {
    from(incomingEndpoint)
        .process((exchange) -> {
            System.out.println("new file received");
        })
        .to(outgoingEndpoint);
}

/**
 * Set the incoming endpoint from the spring config file.
 * @param incomingEndpoint incoming endpoint
 */
public void setIncomingEndpoint(final Endpoint incomingEndpoint) {
    this.incomingEndpoint = incomingEndpoint;
}

/**
 * Set the outgoing endpoint from the spring config file.
 * @param outgoingEndpoint outgoing endpoint
 */
public void setOutgoingEndpoint(final Endpoint outgoingEndpoint) {
    this.outgoingEndpoint = outgoingEndpoint;
}
}

我的 camel-context.xml 位于 resources/META-INF/spring/ 中:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:util="http://www.springframework.org/schema/util"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:camel="http://camel.apache.org/schema/spring" xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
                    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                    ">


<camel:camelContext id="camel">

    <camel:routeBuilder ref="PriorityCodeSourcesUpdaterRouteBuilder"/>

    <camel:endpoint id="incomingEndpoint" uri="">
        <camel:property key="accessKey" value=""/>
        <camel:property key="secretKey" value="RAW()"/>
        <camel:property key="region" value=""/>
        <camel:property key="deleteAfterRead" value="false"/>
    </camel:endpoint>
    <camel:endpoint id="outgoingEndpoint" uri="file://#{systemProperties['java.io.tmpdir']}">
        <camel:property key="fileName" value="deadBeefName"/>
        <camel:property key="readLock" value="markerFile "/>
        <!-- We need a customer idempotentKey because all files sent to this endpoint have the same fileName. -->
        <!-- This will prevent camel from thinking that it has already consumed the file. -->
        <!--<camel:property key="idempotentKey" value="3"/>-->
    </camel:endpoint>

</camel:camelContext>


<bean id="PriorityCodeSourcesUpdaterRouteBuilder" class=".....PriorityCodeSourcesUpdaterRouteBuilder">
    <property name="incomingEndpoint" ref="incomingEndpoint" />
    <property name="outgoingEndpoint" ref="outgoingEndpoint" />
</bean>

【问题讨论】:

  • 您不需要camel-spring-javaconfig Maven 依赖项来启用RouteBuilder 类的自动发现吗?
  • 让我快速研究一下
  • 我不认为这是必需的。我已经在没有额外依赖的示例项目中看到了这一点。当我添加它时,我的项目也可以工作。
  • 你是对的,它没有。只有在使用 Spring Boot 时才需要,并且 RouteBuilder 被注释为 Spring @Component。这就是我们在构建 Spring-Camel 应用程序时选择的方法。您是否也考虑过这种方法?
  • 您的方法是否允许上下文或 spring xml 文件注入端点/其他组件?

标签: spring maven spring-mvc tomcat apache-camel


【解决方案1】:

根据要求,以下是我们在 Camel 项目中使用的 Camel-Spring 设置的简化版本。使用了 Spring Boot(它提供的好东西实在是太好了,IMO 无法忽视),我们也在使用 web starter。由于您无论如何都在使用 WAR 打包,所以这对您来说应该不是问题。

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <artifactId>stackoverflow</artifactId>
    <groupId>sandbox</groupId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>1.5.3.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring-boot-starter</artifactId>
            <version>2.19.2</version>
        </dependency>
    </dependencies>
</project>

src/main/java/stackoverflow/CamelRoute.java(路由定义,在启动时自动发现,由于被放置在@SpringBootApplication类的包路径中 - 下面是TestApp类):

package stackoverflow;

import org.apache.camel.builder.RouteBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class CamelRoute extends RouteBuilder {
    @Value("${message}")
    private String message;
    // you can also have dependencies @Autowired here

    @Override
    public void configure() {
        from("direct:test").process(exchange -> {
            exchange.getIn().setBody(message);
        });
    }
}

src/main/resources/application.properties(说明如何将配置值传递给您的路由定义):

message=Test

src/main/resources/log4j.properties(主要是为了让您在日志中看到您的路线开始):

log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p %c:%L - %m%n

src/main/java/stackoverflow/TestApp.java:

package stackoverflow;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestApp {
    public static void main(String[] args) {
        SpringApplication.run(TestApp.class, args);
    }
}

TestApp 类启动应用程序,并一直运行直到停止(它启动嵌入式 Tomcat 服务器)。路由会在应用启动时发现并启动。

此设置更喜欢 Java 配置而不是 XML,但如果您仍然更喜欢 XML,您可以使用 TestApp 上的 @ImportResource 注释导入您的配置。您还可以将 XML 配置的类自动装配到您的路由定义中。

如果您对此设置有任何疑问,请告诉我。

【讨论】:

  • 感谢您的信息!我最终采用了混合方法
【解决方案2】:

TL;DR:

尝试将camel-spring-boot-starter 依赖项添加到您的POM 文件中,使用@Component 注释标记您的路线并添加一个@SpringBootApplication 类以启动与Camel 绑定的Spring 上下文。


阅读您的文件,我猜您正在使用 Spring Boot,对吧?

如果是这样,最好在您的 POM 中包含以下依赖项:

<dependencyManagement>
    <dependencies>
        <!-- Spring Boot BOM -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring.boot-version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- Camel BOM -->
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring-boot-dependencies</artifactId>
            <version>${camel.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

这是来自 Spring Boot 和 Camel 的 BOM(物料清单)。这样您所有需要的依赖项都将得到很好的解决,并且避免了一直描述骆驼组件版本的需要。

必须拥有camel-context.xml 文件吗?如果不是您,可以在您的 RouteBuilder 类上定义所有内容,并将 @SpringBootApplication 注释类放在您的类路径中。

来自docs

Spring Boot 组件为 Apache Camel 提供自动配置。 我们固执己见的 Camel 上下文自动配置会自动检测 Spring 上下文中可用的 Camel 路由,并将关键的 Camel 实用程序(如生产者模板、消费者模板和类型转换器)注册为 bean。

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

我认为您面临的问题是您的 Spring 上下文和 Camel 上下文(camel-context.xml 文件)之间没有“胶水”。将 @Component 注释添加到您的 RouteBuilder 和以下依赖项:

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

然后这些路线将自动启动。要保持主线程阻塞以使 Camel 保持运行,请包含 spring-boot-starter-web 依赖项,或将 camel.springboot.main-run-controller=true 添加到您的 application.properties 或 application.yml 文件中。

docs 中有更多信息和示例。

干杯!

【讨论】:

  • 使用纯 java 配置并将我的路由构建器添加为组件是一个更简单的解决方案。感谢您的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2013-01-21
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多