Java 在IDE中和在JBoss Fuse中部署时Apache Camel聚合的不同行为
我对Apache Camel有一个我无法理解的问题。我在JBoss Fuse 6.3.0中遇到了这个问题,它捆绑了Apache Camel 2.17.0.redhat-630224 我有一个简单的方法:它从FTP服务器下载文件,将它们转换成POJO(这部分工作正常),然后将它们聚合成单个POJO,然后将其编组并保存到文件中 在JBossDeveloperStudio中,我通过执行“RunAs…>LocalCamelContext”来测试这一点。在幕后,它只是运行Java 在IDE中和在JBoss Fuse中部署时Apache Camel聚合的不同行为,java,eclipse,apache-camel,apache-karaf,Java,Eclipse,Apache Camel,Apache Karaf,我对Apache Camel有一个我无法理解的问题。我在JBoss Fuse 6.3.0中遇到了这个问题,它捆绑了Apache Camel 2.17.0.redhat-630224 我有一个简单的方法:它从FTP服务器下载文件,将它们转换成POJO(这部分工作正常),然后将它们聚合成单个POJO,然后将其编组并保存到文件中 在JBossDeveloperStudio中,我通过执行“RunAs…>LocalCamelContext”来测试这一点。在幕后,它只是运行mvncleanpackage o
mvncleanpackage org.apache.camel:camel-maven-plugin:run
。无论是从IDE还是在终端中手动执行,路由都可以正常工作
但是,当我构建一个OSGi捆绑包(使用mvn clean install
)并将其部署到JBoss Fuse(Apache Karaf)中时,应用程序成功部署,下载/转换部分工作正常,但聚合失败
聚合由实现org.apache.camel.processor.aggregate.AggregationStrategy
(文档化)的自定义类处理。我遇到的问题是,我收到的newExchange
参数的正文总是空的。现在,预期oldchange
第一次为空,但是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
第二个if
每次都会触发,即使对于第一个聚合,如果我删除第一个if
中的return
编辑
好的,感谢noMad17n下面的评论,我有了一个突破:问题与类加载有关
当我在没有指定类的情况下得到newExchanges
的主体时(Object newBody=newExchange.getIn().getBody();
),结果不是空的,但我不能将其转换为MyClass
:我得到了java.lang.ClassCastException:net.j11e.MyClass不能转换为net.j11e.MyClass
在阅读OSGi如何导致多个类加载器加载同一个类时,我将MyClass
重命名为MyOtherClass
,重新启动(??)后,一切正常。但是,在卸载并重新安装我的捆绑包之后,问题又出现了
osgi:find class MyClass
返回两个捆绑包:mine和dozer osgi,这(我猜)是合乎逻辑的,因为MyClass实例是由dozer转换生成的
好吧,也许我不应该经常卸载和重新安装捆绑包,而应该使用
osgi:update
,osgi:refresh
,或者其他什么。但是,还是应该有办法让它发挥作用?除了卸载我的捆绑包、刷新/更新推土机、停止/重新启动Fuse和重新安装我的捆绑包,希望上述操作之一能够以某种方式加载正确的类之外,还有什么其他方法吗?对于将来可能遇到此问题的人,这里有一个概述:
- 这个问题是由另一个包(在我的例子中是dozer osgi)仍在使用由您的包导出的包的旧版本这一事实引起的。在这里,这会导致对MyClass的转换失败,这使得
返回null(getBody
将返回异常,等等)getMandatoryBody
- 要识别导致问题的捆绑包,请使用命令
。这将退还您的包裹。。。还有一个osgi:find class MyClass
- 通过查找捆绑包id(
)并刷新它(osgi:list | grep thebundle
),刷新该捆绑包。您还可以从Fuse的web UI(hawtio)中刷新捆绑包:OSGi>捆绑包>您的捆绑包>页面顶部的刷新按钮(在开始、停止、更新和卸载按钮旁边)osgi:refresh 123
公平的警告:有时候,仅仅刷新dozer osgi显然是不够的。MyClass不再由它导入(
osgi:find class MyClass
不会返回dozer osgi),但我仍然存在NullPointerException
问题。在这些罕见的事件中,我不得不重新启动保险丝。我不知道为什么会发生这几起案件 我想cusom类是正在部署的包的一部分吧?如何进行部署?@SoucianceEqdamRashti是的,自定义聚合器在捆绑包中。我可以通过检查maven生成的工件来检查这一点,这也是因为当应用程序运行时,我在聚合方法中对System.out.println的调用出现在我的日志中;)在您的保险丝安装中,您的Camel是否比2.16版本更新?如果能看到您的实际路线,那将非常有趣。@SoucianceEqdamRashti:是的,它是Camel 2.17.0。
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");
}
// ...