繁体   English   中英

在IDE中以及在JBoss Fuse中部署时Apache Camel聚合的不同行为

[英]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和doz​​er-osgi,这是合乎逻辑的,因为MyClass实例是由dozer转换产生的。

好的,所以也许我不应该经常卸载并重新安装捆绑软件,而应使用osgi:updateosgi:refresh或其他任何方式。 但是,仍然应该有一种方法可以使这项工作成功吗? 除了卸载我的软件包,刷新/更新推土机,停止/重新启动Fuse以及重新安装我的软件包以外,还希望上述操作之一以某种方式使正确的类被加载吗?

对于那些将来可能会遇到此问题的人,这里有一个回顾:

  • 该问题是由于您的捆绑软件导出的软件包的较旧版本仍被另一个软件包(在我的情况下是dozer-osgi)使用而造成的。 在这里,这导致对MyClass的getBody转换失败,这使getBody返回null( getMandatoryBody将返回异常,等等)。
  • 要确定引起问题的捆绑软件,请使用命令osgi:find-class MyClass 这将返回您的捆绑包……等等。
  • 通过找到其束ID( 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM