[英]Apache Camel (JBoss Fuse) - how to unzip a file from a MQ route?
[英]Different behavior of Apache Camel aggregation in IDE and when deployed in JBoss Fuse
我在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
( 在此处记录 )的自定义类处理。 我newExchange
的问题是,我收到的newExchange
参数始终为空。 现在,预计oldExchange
第一次为null,但是newExchange
的主体是什么? (编辑:相关表达式是一个简单的常量,因为所有POJO都聚集在一起)
甚至更奇怪:如果我修改路由以在聚合器之前封送我的POJO,则会收到包含预期数据的String。 这证明了(我认为!)转换按预期进行。 另外,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();
)时,结果不为null,但是我无法将其转换为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实例是由dozer转换产生的。
好的,所以也许我不应该经常卸载并重新安装捆绑软件,而应使用osgi:update
, osgi:refresh
或其他任何方式。 但是,仍然应该有一种方法可以使这项工作成功吗? 除了卸载我的软件包,刷新/更新推土机,停止/重新启动Fuse以及重新安装我的软件包以外,还希望上述操作之一以某种方式使正确的类被加载吗?
对于那些将来可能会遇到此问题的人,这里有一个回顾:
getBody
转换失败,这使getBody
返回null( getMandatoryBody
将返回异常,等等)。 osgi:find-class MyClass
。 这将返回您的捆绑包……等等。 osgi:list | grep thebundle
)并刷新它( osgi:refresh 123
)刷新该束。 您也可以从Fuse的Web UI(hawtio)刷新捆绑软件:OSGi>捆绑软件>您的捆绑软件>页面顶部的刷新按钮(开始,停止,更新和卸载按钮旁边)。 解决此问题比适当解决方案更具缓解作用。 真正的解决方案可能涉及修复软件包的导入/导出规则等,但这超出了我目前的技能。
也有合理的警告:有时,刷新dozer-osgi显然还不够。 MyClass不再由它导入( osgi:find-class MyClass
不会返回dozer-osgi),但是我仍然遇到NullPointerException
问题。 在这些罕见的情况下,我不得不重新启动Fuse。 我不知道为什么这几种情况会发生。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.