在Java中使用Apache Camel聚合的不同行为以及部署在JBoss Fuse

时间:2017-04-03 12:11:55

标签: java eclipse apache-camel apache-karaf

我遇到了Apache Camel的问题,我无法理解。我在JBoss Fuse 6.3.0中遇到了这个问题,它捆绑了Apache Camel 2.17.0.redhat-630224。

我有一个简单的路线:它从FTP服务器下载文件,将它们转换为POJO(这部分有效),然后将它们聚合到一个POJO中,该POJO被编组并保存到文件中。

在JBoss Developer Studio中,我通过执行" Run as ...>来测试它。当地的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 =&#34; false&#34;,没有改变任何东西。

这里是聚合器:

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();的主体时,结果不为空,但我无法将其转换为{{1} }:我得到了MyClass

阅读OSGi如何导致多个类加载器加载同一个类,我将java.lang.ClassCastException: net.j11e.MyClass cannot be cast to net.j11e.MyClass重命名为MyClass并重启(??)后,一切正常。但是,卸载我的软件包并重新安装后,问题就出现了。

MyOtherClass返回两个包:mine和doz​​er-osgi,这是(我猜)逻辑,因为MyClass实例是由推土机转换生成的。

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

1 个答案:

答案 0 :(得分:1)

对于将来可能会遇到此问题的人,请回顾一下:

  • 问题是由于您的捆绑包导出的旧版本的包仍然被另一个包使用(在我的例子中是dozer-osgi)。这里导致转换为MyClass失败,这使getBody返回null(getMandatoryBody将返回异常等)。
  • 要识别导致问题的捆绑包,请使用命令osgi:find-class MyClass。这将返回你的包...和另一个。
  • 通过查找其包ID(osgi:list | grep thebundle)并刷新它(osgi:refresh 123)来刷新该包。您还可以从Fuse的Web UI(hawtio)刷新捆绑包:OSGi&gt;捆绑&gt;你的捆绑&gt;页面顶部的刷新按钮(启动,停止,更新和卸载按钮旁边)。

这不仅仅是解决这个问题的缓解措施。真正的解决方案可能涉及修复包导入/导出规则或其他内容,但这超出了我目前的技能。

公平警告:有时候,令人耳目一新的推土机osgi显然还不够。 MyClass不再被它导入(osgi:find-class MyClass不会返回dozer-osgi),但我仍遇到NullPointerException问题。在这些罕见的事件中,我不得不重启Fuse。我不知道为什么会发生这几起案件。