簡體   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