[英]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.