Red Hatエンジニアリングの佐藤匡剛です。昨年12月の赤帽エンジニアAdvent Calendarの記事で、Camel 3へのマイグレーションガイドの紹介記事を年明けに書くと宣言していましたが、ようやく書きました。
今回紹介する本家のガイドは、こちらです。
Apache Camel 2.x to 3.0 Migration Guide - Apache Camel
このガイドは長いので、このブログでは2つの記事(camel-core編、コンポーネント編)に分けてお送りします。コンポーネント編はこちらです。
今回は、camel-core編です。
- Javaのバージョン
- ランタイム/プラットフォーム
- camel-coreのモジュール化
- CamelContext
- Message API
- ルート/エンドポイント
- その他のAPI
- EIP
- テスト
- 管理/監視
- カスタムコンポーネント/言語
- 言語
- Camel Mavenプラグイン
- 既知の問題
- 最後に
Javaのバージョン
Camel 3が正式にサポートするのはJava 11です。当面はJava 8もベストエフォートでサポートを続けますが、いずれどこかの段階でドロップされます。
JAXB
Java 11でJAXBを使うには、Maven dependencyの明示的な追加が必要です。XML DSLでJAXBを使っていたり、camel-jaxbコンポーネントを使っている場合は、これらのdependency
をpom.xml
に追加します。
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.3.0.1</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.2</version> </dependency>
ランタイム/プラットフォーム
Spring Boot StarterのGroup ID変更
Spring Boot StarterのMaven groupId
がorg.apache.camel
からorg.apache.camel.springboot
に変更されました。
Camel 2.x:
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-component-starter</artifactId> </dependency>
Camel 3.0:
<dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-component-starter</artifactId> </dependency>
Mainクラス
CamelのMain
クラス(Camelアプリケーションをスタンドアロンで実行するためのユーティリティクラス)が含まれるJARが、camel-core
からcamel-main
に変わりました。Main
クラスを使っている方は、camel-main
のpom.xml
への追加が必要です。
camel-coreのモジュール化
camel-core
Camel 3の大きな変更の1つがcamel-coreのモジュール化です。camel-coreは、以下のJARに細分化されました。後方互換性のために、これらを1つにまとめたcamel-coreは引き続き提供されていますが、マイクロサービス化のためにアプリケーションをスリムダウンしたい方は必要なdependencyだけをピックアップして使えます。
- camel-api
- camel-base
- camel-caffeine-lrucache
- camel-cloud
- camel-core
- camel-jaxp
- camel-main
- camel-management-api
- camel-management
- camel-support
- camel-util
- camel-util-json
コアコンポーネント
さらに、camel-coreに含まれていた下記のコアコンポーネントも、通常のコンポーネントと同様に外だしされました。それぞれ、使いたいコンポーネントをピックアップして使う形になります。
- camel-attachments
- camel-bean
- camel-browse
- camel-controlbus
- camel-dataformat
- camel-dataset
- camel-direct
- camel-directvm
- camel-file
- camel-language
- camel-log
- camel-mock
- camel-ref
- camel-rest
- camel-saga
- camel-scheduler
- camel-seda
- camel-stub
- camel-timer
- camel-validator
- camel-vm
- camel-xpath
- camel-xslt
- camel-xslt-saxon
- camel-zip-deflater
CamelContext
複数CamelContextの非サポート
元々アプリケーションのデプロイメント毎に複数のCamelContextを定義する方法は、推奨されてもおらず100%完全な実装でもなかったのですが、Camel 3ではデプロイメント毎に1つのCamelContextのみサポート、ということが明示化されました。
それに伴い、複数のCamelContextを扱うために提供されていたAPIはごっそり削除されました。@EndpointInject
、@Produce
、@Consume
などのCamelアノテーションにあったcontext
属性は削除されました。
Mainクラスの複数CamelContext非サポート
camel-core、camel-spring、camel-cdiのMain
クラスでも、同様に1つのCamelContextのみ対応するための変更が加えられています。具体的には、getCamelContextMap()
メソッドが削除され、getCamelContext()
メソッドだけになりました。
CamelContextのグローバルオプション
Camel 2.xでdeprecatedだったCamelContext
のgetProperties()
は削除されました。代わりに、getGlobalOptions()
を使います。
Java:
context.getGlobalOptions().put("CamelJacksonEnableTypeConverter", "true"); context.getGlobalOptions().put("CamelJacksonTypeConverterToPojo", "true");
XML:
<globalOptions> <globalOption key="CamelJacksonEnableTypeConverter" value="true"/> <globalOption key="CamelJacksonTypeConverterToPojo" value="true"/> </globalOptions>
ExtendedCamelContext
CamelContext
のAPIが一般ユーザ向けに整理され、高度なユースケース向けのAPIやSPIはExtendedCamelContext
に移されました。ExtendedCamelContext
には以下のようにしてアクセスします。
ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class);
ModelCamelContext
ModelCamelContext
にあったloadRouteDefinitions()
とloadRestDefinitions()
のメソッドは、他のメソッドと名前を揃えるためにaddRouteDefinitions()
とaddRestDefinitions()
になりました。ローダ関連のメソッドはModelHelper
ユーティリティクラスに見つかります。
ModelCamelContext
にアクセスしたいときは、以下のようにします。
ModelCamelContext mcc = camelContext.adapt(ModelCamelContext.class);
CatalogCamelContext
CamelContext
に定義されていたカタログ関連のメソッドは、CatalogCamelContext
インタフェースに移動しました。以下のようにして使います。
CatalogCamelContext ccc = context.adapt(CatalogCamelContext.class);
CamelContextによるルートの制御
CamelContext
にあったstartRoute()
、stopRoute()
、suspendRoute()
、resumeRoute()
、getRouteStatus()
とその他関連するメソッドはRouteController
クラスに移されました。以下のようにアクセスします。
context.getRouteController().startRoute("myRoute");
Message API
MessageのgetOut()
Message
クラスのhasOut()
、getOut()
メソッドはdeprecateになりました。代わりにシンプルにgetMessage()
を使います。メッセージのINとOUTというコンセプトは廃止になりました。これらは、JBIやSOAPといった古い仕様から採用されたものですが、実際はそれほど有用でなかったためです。
それに伴い、他の部分でもIN、OUTのコンセプトに基づいた要素は削除されています。Beanパラメータバインディングの@OutHeaders
アノテーションは削除され、代わりに@Headers
を使います。
MessageのFault API
Message
クラスのFault APIも削除されました。SOAPのFaultメッセージにしか使われていなかったためです。handleFault
オプションも削除されています。
SOAPを扱うcamel-cxf、camel-spring-wsコンポーネントでは、それぞれ独自にFaultメッセージを実装していて、handleFault
の有効化をコンポーネント/エンドポイントのオプションとして設定する必要があります。
MessageのAttachments API
javax.activation
のAttachments APIは、Message
クラスからcamel-attachmentsのorg.apache.camel.attachment.AttachmentMessage
クラスに移動しました。
使い方は、以下のとおりです。
AttachmentMessage am = exchange.getMessage(AttachmentMessage.class); am.addAttachment("myAtt", new DataHandler(...));
ルート/エンドポイント
consumer.
プレフィクスの付いたエンドポイントオプションの削除
consumer.
プレフィクスの付いたエンドポイントオプションは廃止されました。今後は、consumer.
プレフィクスを付けずにそのままオプションを指定します。
例)consumer.delay=5000
→ delay=5000
POJOアノテーション
@Consume
、@Produce
、@EndpointInject
のref
属性は削除されました。代わりに、value
属性にrefコンポーネントを使い、以下のようにします(value
は省略可能なことに注意)。
@Consume("ref:myName")
上記にuri
属性を使うこともできますが、uri
属性自体もdeprecatedになっていて、代わりにvalue
属性を使う必要があります。そのため、全般に、@Consume(uri = "jms:cheese")
ではなく@Consume("jms:cheese")
を使います。
複数インプットのあるルート
Camel 2.xでは、実はルートは2つ以上のインプットを持つことが(部分的に)できたのですが、ほとんど使われていませんでした。Camel 3では、この機能を削除し、明示的に1つのルートで1つのインプットしか受け付けないようにしました。
ルートポリシー
org.apache.camel.support.RoutePolicySupport
クラスはcamel-supportに移りました。メソッドstartConsumer()
、stopConsumer()
の戻り値はboolean
からvoid
に変更されました(元々true
しか返していなかったため)。
org.apache.camel.impl.ThrottlingInflightRoutePolicy
クラスはorg.apache.camel.throttling.ThrottlingInflightRoutePolicy
にパッケージが変わりました。
XML DSLのマイグレーション
XML DSLのタグに細かな修正が入っています。
- カスタムロードバランサーEIPのタグが
<custom>
から<customLoadBalancer>
に変更された - XML Securityデータフォーマットで
<secureXML>
タグのkeyOrTrustStoreParametersId
属性がkeyOrTrustStoreParametersRef
に名前変更された <zipFile>
データフォーマットが<zipfile>
に名前変更された
その他の変更
RestEndpoint
クラスのbindingMode
向けのgetter/setterメソッドは、camel-apiのorg.apache.camel.spi.RestConfiguration.RestBindingMode
型を使う形に変更されました。setterメソッドに関しては、String型を使うバージョンも残されてます。RouteBuilder
クラスのincludeRoutes()
メソッドは削除されました。このメソッドはCamel 2.xの頃からdeprecatedでした。
その他のAPI
非推奨API、コンポーネントの削除
Camel 2.xで既にdeprecatedになっていたAPIやコンポーネントは、Camel 3で全部削除されました。
検査例外 vs 非検査例外
Camelのほとんどの例外クラスは非検査例外(RuntimeException
のサブクラス)になりました。
また、Service
およびSuspendableService
のライフサイクルメソッドstart()
、stop()
、suspend()
、resume()
も検査例外を投げないようになりました。
FactoryFinder
クラスのAPIは、検査例外FactoryNotFoundException
やClassNotFoundException
等をスローする代わりに、Optional
型を返すように変更されました。
HelperとSupport
HelperおよびSupportのクラスの変更は以下の通りです。
org.apache.camel.util.AsyncProcessorHelper
(camel-core) →org.apache.camel.support.AsyncProcessorHelper
(camel-support)org.apache.camel.util.AsyncProcessorConverterHelper
(camel-core) →org.apache.camel.support.AsyncProcessorConverterHelper
(camel-support)org.apache.camel.util.CamelContextHelper
(camel-core) →org.apache.camel.support.CamelContextHelper
(camel-support)org.apache.camel.util.EndpointHelper
(camel-core) →org.apache.camel.support.EndpointHelper
(camel-support)org.apache.camel.util.EventHelper
(camel-core) →org.apache.camel.support.EventHelper
(camel-support)org.apache.camel.util.ExchangeHelper
(camel-core) →org.apache.camel.support.ExchangeHelper
(camel-support)org.apache.camel.util.GZIPHelper
(camel-core) →org.apache.camel.support.GZIPHelper
(camel-support)org.apache.camel.util.JsonSchemaHelper
(camel-core) →org.apache.camel.support.JsonSchemaHelper
(camel-support)org.apache.camel.util.MessageHelper
(camel-core) →org.apache.camel.support.MessageHelper
(camel-support)org.apache.camel.util.ObjectHelper
(camel-core) →org.apache.camel.support.ObjectHelper
(camel-support) &org.apache.camel.util.ObjectHelper
(camel-util)- camel-apiに依存したメソッドはcamel-supportに、それ以外はcamel-utilに移動
org.apache.camel.util.PlatformHelper
(camel-core) →org.apache.camel.support.PlatformHelper
(camel-support)org.apache.camel.util.PredicateAssertHelper
(camel-core) →org.apache.camel.support.PredicateAssertHelper
(camel-support)org.apache.camel.util.ResolverHelper
(camel-core) →org.apache.camel.support.ResolverHelper
(camel-support)org.apache.camel.util.ResourceHelper
(camel-core) →org.apache.camel.support.ResourceHelper
(camel-support)org.apache.camel.spi.RestProducerFactoryHelper
(camel-core) →org.apache.camel.support.RestProducerFactoryHelper
(camel-support)org.apache.camel.util.ServiceHelper
(camel-core) →org.apache.camel.support.service.ServiceHelper
(camel-api)org.apache.camel.util.UnitOfWorkHelper
(camel-core) →org.apache.camel.support.UnitOfWorkHelper
(camel-support)org.apache.camel.processor.loadbalancer.SimpleLoadBalancerSupport
は削除されました。代わりにorg.apache.camel.processor.loadbalancer.LoadBalancerSupport
を使います。
冪等リポジトリ
冪等リポジトリ(IdempotentRepository
)クラスも以下のように場所が移動しています。
org.apache.camel.processor.idempotent.FileIdempotentRepository
(camel-core) →org.apache.camel.support.processor.idempotent.FileIdempotentRepository
(camel-support)org.apache.camel.processor.idempotent.MemoryIdempotentRepository
(camel-core) →org.apache.camel.support.processor.idempotent.MemoryIdempotentRepository
(camel-support)
アグリゲーション
XsltAggregationStrategy
クラスは以下のように場所が移動しています。
org.apache.camel.builder.XsltAggregationStrategy
(camel-core) →org.apache.camel.component.xslt.XsltAggregationStrategy
(camel-xslt)
org.apache.camel.builder.AggregationStrategies
クラスのxslt()
メソッドは削除されました。代わりにcamel-xsltのXsltAggregationStrategy
を直接使います。
Aggregate EIPのgroupExchanges()
オプションを使った場合でも、アウトプットがExchange.GROUPED_EXCHANGE
に格納されることはなくなりました。これは、既にCamel 2.13以降deprecatedになっていた挙動でした。
JSSE
org.apache.camel.util.jsse
パッケージのクラスは、org.apache.camel.support.jsse
パッケージに移りました。
フォールバック型コンバータ
@FallbackConverter
は削除されました。代わりに@Converter(fallback = true)
を使います。さらに、@Converter(generateLoader = true)
とすることでCamelが型コンバータをより高速にロードするためのコードを自動生成できるようになりました。
レジストリ
SimpleRegistry
クラスがorg.apache.camel.impl
パッケージからorg.apache.camel.support
パッケージに移動しました。ただし、今後はorg.apache.camel.support.DefaultRegistry
を代わりに使うべきです。さらに、SimpleRegistry
またはDefaultRegistry
にエントリを追加するのに、put()
メソッドでなくbind()
メソッドを使ってください。
CompositeRegistry
、PropertyPlaceholderDelegateRegistry
クラスは共に削除されました。代わりにDefaultRegistry
を使います。
アノテーション
アノテーション関連の細かな変更は以下のとおりです。
org.apache.camel.Constant
アノテーションは削除されました。代わりに@Simple
を使います。org.apache.camel.InvokeOnHeader
/org.apache.camel.InvokeOnHeaders
→org.apache.camel.spi.InvokeOnHeader
/org.apache.camel.spi.InvokeOnHeaders
その他の変更
その他、細かな修正を列挙します。(まだ未分類な変更項目が多いので、後で別のセクションに振り分けるかもしれません。)
breadcrumbの使用はデフォルトで
true
からfalse
に変更されました。CamelContext
がまだ起動していない段階で、ProducerTemplate
やConsumerTemplate
を使おうとすると失敗するようになりました。org.apache.camel.impl
パッケージにあったクラスの大部分は、camel-baseのorg.apache.camel.impl.engine
パッケージに移されました。org.apache.camel.util.jndi.JNDIContext
(camel-core) →org.apache.camel.support.jndi.JNDIContext
(camel-support)org.apache.camel.ThreadPoolRejectedPolicy
→org.apache.camel.util.concurrent.ThreadPoolRejectedPolicy
org.apache.camel.processor.validation.PredicateValidationException
→org.apache.camel.support.processor.validation.PredicateValidationException
org.apache.camel.util.toolbox.AggregationStrategies
→org.apache.camel.builder.AggregationStrategies
org.apache.camel.processor.aggregate.AggregationStrategy
→org.apache.camel.AggregationStrategy
org.apache.camel.management.JmxSystemPropertyKeys
→org.apache.camel.api.management.JmxSystemPropertyKeys
org.apache.camel.builder.xml.XPathBuilder
→org.apache.camel.language.xpath.XPathBuilder
(camel-xpath)org.apache.camel.builder.xml.InvalidXPathExpression
→org.apache.camel.language.xpath.InvalidXPathException
(camel-xpath)org.apache.camel.converter.stream.OutputStreamBuilder
→org.apache.camel.support.builder.OutputStreamBuilder
camel-coreのAPI全般にわたって次のtypoを直しました:
chiper
→cipher
ReloadStrategySupport
、FileWatcherReloadStrategy
クラスは削除されました。MessageHistoryFactory
インタフェースにメッセージをフィルタまたはコピーするオプションが追加され、APIに細かな変更がありました。TypeConverterAware
インタフェースは削除されました。代わりに、型コンバータメソッドへのパラメータとしてExchange
を使います。Component
、DataFormat
インタフェースは、Service
インタフェースを継承するようになりました。コンポーネントやデータフォーマットにもそれらのライフサイクルを管理するサービスコントラクトがあるためです。デフォルトのベースクラスは既にそれらのインタフェースを実装しています。コンポーネント共通の
resolvePropertyPlaceholders
オプションは削除されました。プロパティプレースホルダーの機能はCamel Main、Camel Spring Boot等で既にサポートされています。
EIP
XML DSLの<setHeader>
、<setProperty>
<setHeader>
のheaderName
属性、<setProperty>
のpropertyName
属性は、単にname
に名前変更しました。
Camel 2.x:
<setHeader headerName="foo"><simple>Hello ${body}</simple></setHeader>
Camel 3.0:
<setHeader name="foo"><simple>Hello ${body}</simple></setHeader>
XML DSLの<aggregate>
Aggregate EIPで、相関サイズ/タイムアウト(correlation size/timeout)を表現する条件式(expression)のタグ名が変更されました。XML上の名前衝突を避けるための措置です。
Camel 2.x:
<completionSize> <header>mySize</header> </completionSize>
Camel 3.0:
<completionSizeExpression> <header>mySize</header> </completionSizeExpression>
<completionTimeout>
も同様に<completionTimeoutExpression>
となります。
Hystrix EIP
元々あったHystrix EIPは、より一般的なCircuit Breaker EIPに変更され、他の実装をプラグインできるようになりました。
Java DSL、XML DSLでそれぞれ以下のように書き換える必要があります。
.hysterix()
→.circuitBreaker()
<hystrix>
→<circuitBreaker>
テスト
camel-test
camel-testを使っていて、これまでテスト用のBeanを登録するためにcreateRegistry()
メソッドをオーバーライドしてJndiRegistry
クラスをインスタンス生成していた場合、このテクニックはもう必要なくなりました。代わりに、CamelContext
からRegistry
APIを取得してbind()
メソッドを使うのが推奨の方法になります。
context.getRegistry().bind("myId", myBean);
adviceWith
adviceWith
を使ったテストは以下のように書き換える必要があります。
Camel 2.x:
context.getRouteDefinition("start").adviceWith(camelContext, new AdviceWithRouteBuilder() { ... }
Camel 3.0:
ModelCamelContext mcc = camelContext.adapt(ModelCamelContext.class); RouteReifier.adviceWith(mcc.getRouteDefinition("start"), mcc, new AdviceWithRouteBuilder() { ... }
AdviceWithRouteBuilder
とラムダを使うともっと簡単に書けます。
AdviceWithRouteBuilder.adviceWith(context, "myRoute", a -> { a.replaceFromWith("direct:start"); }
管理/監視
トレーシング
Camelルーティングの詳細なログを出力するTracer機能の実装が、書き換えられました。新しいTracerでは、ログは org.apache.camel.Tracing
ロガー名で出力されます。
JMXでは、 BacklogTracer
はデフォルトで無効になりました。有効にするには、CamelContext
にbacklogTracing=true
をセットします。
JMXイベント
org.apache.camel.management.event
パッケージにあったすべてのイベントクラスは、org.apache.camel.spi.CamelEvent
クラス内にサブクラスとして定義されるようになりました。例えば、CamelContext
の開始イベントはCamelEvent.CamelContextStartedEvent
になります。
EIP、コンポーネント等の参照用JMX APIの削除
EIPやコンポーネント、エンドポイント等を検索し、そのメタ情報を得るためのJMX APIは削除されました。これらのAPIはアプリケーション実行時にはあまり意味がなく、同じ情報は開発時にはcamel-catalogから得られるためです。関連するCamelのKarafコマンドも同様に削除されました。
カスタムコンポーネント/言語
カスタムコンポーネント
カスタムコンポーネントは、今後はcamel-core
ではなくcamel-support
のみに依存するように実装すべきです。
DefaultComponent
、DefaultEndpoint
など、camel-coreにあったカスタムコンポーネントの開発に必要なクラスは、org.apache.camel.impl
パッケージのからcamel-supportのorg.apache.camel.support
パッケージに移されました。
同様に、camel-coreのorg.apache.camel.util.component
パッケージにあった全てのクラスもcamel-supportのorg.apache.camel.support.component
パッケージに移されました。
カスタム言語
@LaunguageAnnotation
アノテーションは、org.apache.camel.language
パッケージからorg.apache.camel.support.language
パッケージへ移されました。
言語
Simple言語からのOUT Messageの削除
OUT Messageのコンセプトが廃止されたのに伴い、Simple言語からも${out.body}
といった用法が削除されました。
Simple言語の開始/終了トークン
これまでSimple言語の開始/終了を表すトークンを変更できたのですが、誰も使っていなかったので最適化のために廃止されました。今後は、デフォルトの${xxx}
または$simple{xxx}
のみが使用可能です。
Simple言語のproperty
Camel 2.xでSimple言語のproperty
はdeprecatedになっていましたが、Camel 3では削除されました。代わりにexchangeProperty
を使います。
Terser言語 → HL7 Terser言語
Terser言語は、terser
→ hl7terser
に名前変更されました。
アノテーション
言語関連のアノテーションの変更は以下のとおりです。
org.apache.camel.language.XPath
→org.apache.camel.language.xpath.XPath
(camel-xpath)org.apache.camel.language.Bean
→org.apache.camel.language.bean.Bean
(camel-bean)org.apache.camel.language.Simple
→org.apache.camel.language.simple.Simple
org.apache.camel.language.SpEL
→org.apache.camel.language.spel.SpEL
(camel-spring)
Camel Mavenプラグイン
camel-maven-pluginが2つに分割されました。
- camel-maven-plugin
- camel-report-maven-plugin
1つめのcamel-maven-pluginがrun
ゴールを持っていて、Camelアプリケーションを素早くスタンドアロン実行できるためのものです。
2つめのcamel-report-maven-pluginはvaludate
、route-coverage
ゴールを持っていて、Camelプロジェクトのバリデーションやカバレッジのレポートを出力するためのものです。
既知の問題
内部のルーティングエンジンをリファクタリングした影響で、MDCロギングとbreadcrumb IDの扱いに一定の状況下で問題が見つかっています。この問題は、camel-zipkinコンポーネントにも影響しています。
最後に
本家のガイドは構成がカオスなので、意味のある構成を見つけ出して再構成するのに一番苦労しました。(その分、本家ガイドよりもこちらの方が参照しやすくなっているはず!)もし気が向いたら、本家ガイドにもこの記事の構成を反映させるかもしれません。
次回は、マイグレーションガイドのコンポーネント編を書く予定です。