gpt4 book ai didi

java - Apache Camel 聚合在 IDE 中和在 JBoss Fuse 中部署时的不同行为

转载 作者:行者123 更新时间:2023-12-02 13:30:58 25 4
gpt4 key购买 nike

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

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

在 JBoss Developer Studio 中,我通过执行“Run as...> local Camel context”来测试这一点。在幕后,这只是运行mvn clean package org.apache.camel:camel-maven-plugin:run。无论我是从 IDE 执行此操作,还是在终端中手动执行此操作,该路线都可以正常工作。

但是,当我构建 OSGi bundle (使用 mvn clean install)并将其部署到 JBoss Fuse (Apache Karaf) 中时,应用程序部署成功并且下载/转换部分工作正常,但是那么聚合失败。

聚合由实现 org.apache.camel.processor.aggregate.AggregationStrategy 的自定义类处理(记录为 here )。我遇到的问题是我收到的 newExchange 参数始终具有空主体。现在,oldExchange 第一次为 null 是正常的,但是 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();),结果不为 null ,但我无法将其转换为 MyClass:我收到 java.lang.ClassCastException: net.j11e.MyClass 无法转换为 net.j11e.MyClass

阅读有关 OSGi 如何导致多个类加载器加载同一个类的信息后,我将 MyClass 重命名为 MyOtherClass ,并在重新启动后(??),一切正常。但是,卸载我的 bundle 并重新安装后,问题又回来了。

osgi:find-class MyClass 返回两个包:mine 和 dozer-osgi,(我猜)这是合乎逻辑的,因为 MyClass 实例是由 dozer 转换生成的。

好吧,也许我不应该经常卸载和重新安装 bundle ,而应该使用 osgi:update 、 osgi:refresh 或其他。但是,仍然应该有办法让这项工作发挥作用吗?除了卸载我的 bundle 、刷新/更新推土机、停止/重新启动 Fuse 以及重新安装我的 bundle 之外,还希望上述操作之一能够以某种方式加载正确的类吗?

最佳答案

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

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

对于这个问题来说,这更像是一种缓解措施,而不是适当的解决方案。真正的解决方案可能涉及修复包导入/导出规则或其他内容,但这超出了我目前的技能范围。

也是公平的警告:有时,刷新 dozer-osgi 显然是不够的。 MyClass 不再被它导入(osgi:find-class MyClass 不会返回 dozer-osgi),但我仍然遇到 NullPointerException 问题。在这些罕见的情况下,我不得不重新启动 Fuse。我不知道为什么会发生这几个案例。

关于java - Apache Camel 聚合在 IDE 中和在 JBoss Fuse 中部署时的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43184357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com