【发布时间】:2017-04-13 15:35:19
【问题描述】:
我在使用 Apache Camel 时遇到了一个我无法理解的问题。 JBoss Fuse 6.3.0 有这个问题,它捆绑了 Apache Camel 2.17.0.redhat-630224。
我有一个简单的路线:它从 FTP 服务器下载文件,将它们转换为 POJO(这部分有效),然后将它们聚合成一个 POJO,然后编组并保存到一个文件中。
在 JBoss Developer Studio 中,我通过执行“运行方式... > 本地 Camel 上下文”来对此进行测试。在幕后,这只是运行mvn clean package org.apache.camel:camel-maven-plugin:run。无论我是从 IDE 还是在终端中手动执行,路由都可以正常工作。
但是,当我构建一个 OSGi 包(使用 mvn clean install)并将其部署到 JBoss Fuse (Apache Karaf) 中时,应用程序部署成功并且下载/转换部分工作正常,但随后聚合失败。
聚合由实现org.apache.camel.processor.aggregate.AggregationStrategy 的自定义类处理(记录在here)。我遇到的问题是我收到的newExchange 参数总是有一个空正文。现在,oldExchange 第一次为空是意料之中的,但newExchange 的主体呢? (编辑:相关表达式是一个简单的常数,因为所有 POJO 都聚合在一起)
更奇怪的是:如果我在聚合器之前修改路由以编组我的 POJO,我会收到一个包含预期数据的字符串。这证明(我认为!)转换按预期工作。此外,Fuse 的日志没有显示错误消息(无论是在部署时还是在运行时)。这看起来很像配置或依赖问题,但在我的一生中,我在任何地方都找不到任何类似的问题。
有没有人见过类似的东西?或者至少,您对问题的根源有什么建议吗?
编辑:这是路线的相关部分:
<choice>
// one <when> per file which produces a POJO
<when id="_when_some_xml">
<simple>${file:onlyname} == 'something.xml'</simple>
<to id="_to2" uri="ref:transform_something_xml"/>
</when>
</choice>
// if I add a marshalling here, I receive non-null exchanges in the aggregator... but they're strings and not the POJOs I want.
<aggregate completionSize="12" id="_aggregate_things"
strategyMethodAllowNull="true" strategyRef="MyAggregator">
<correlationExpression>
<constant trim="false">true</constant>
</correlationExpression>
<log id="_log_things_aggregated" message="Data aggregated."/>
<convertBodyTo id="_convertBodyTo_anotherClass" type="net.j11e.mypackage.MyClass"/>
// [...] next: marshal and save to file
注意:我尝试了 strategyMethodAllowNull="false",没有改变任何东西。
这里是聚合器:
public class EpgAggregator implements AggregationStrategy {
@Override
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
// first message being aggregated: no oldExchange, simply keep the message
if (oldExchange == null) {
System.out.println("Old exchange is null");
return newExchange;
}
if (newExchange.getIn().getBody(MyClass.class) == null) {
System.out.println("newExchange body is null");
}
// ...
如果我删除第一个if 中的return,则每次都会触发第二个if,即使对于第一个聚合也是如此。
编辑 好的,感谢 noMad17n 在下面的评论,我有了一个突破:问题与类加载有关。
当我得到newExchanges 的主体而不指定类时(Object newBody = newExchange.getIn().getBody();),结果不为空,但我无法将其转换为MyClass:我得到了java.lang.ClassCastException: net.j11e.MyClass cannot be cast to net.j11e.MyClass。
阅读了有关 OSGi 如何导致多个类加载器加载同一个类的信息,我将 MyClass 重命名为 MyOtherClass 并在重新启动 (??) 后,一切正常。但是,在卸载我的捆绑包并重新安装后,问题又回来了。
osgi:find-class MyClass 返回两个包:mine 和 dozer-osgi,这(我猜)是合乎逻辑的,因为 MyClass 实例是由推土机转换产生的。
好的,所以也许我不应该经常卸载和重新安装捆绑包,而是使用osgi:update、osgi:refresh 或其他任何东西。但是,应该有办法使这项工作?除了卸载我的包、刷新/更新推土机、停止/重新启动 Fuse 和重新安装我的包之外,希望上述操作之一以某种方式加载正确的类?
【问题讨论】:
-
我认为 cusom 类是正在部署的同一个包的一部分?您如何进行部署?
-
@SoucianceEqdamRashti 是的,自定义聚合器在捆绑包中。我可以通过检查 maven 生成的工件来检查这一点 - 也因为当应用程序运行时,我在聚合方法中对 System.out.println 的调用出现在我的日志中;)
-
在您的 Fuse 安装上,您的 Camel 是否比 2.16 更新?
-
看看你的实际路线会很有趣。
-
@SoucianceEqdamRashti:是的,它是 Camel 2.17.0。
标签: java eclipse apache-camel apache-karaf