原文: Migrating from Camel Karaf to Camel Spring Boot or Quarkus By Claus lbsen(@davsclaus) Dec 9, 2024
この記事は、Camel 4 への移行支援に関するブログシリーズ第2段です。
第1段の記事は、移行に関する一般原則に注目して書かれています。 今回の記事は、Apache Karaf OSGi Blueprint から Camel 4 への移行に注目しています。
移行作業
Camel Karaf および OSGi Blueprint から Camel 4 への移行は、些細な移行作業ではありません。
移行は、以下の主要な作業から構成されます:
- Camel 2.x/3.x から Camel 4.x へのアップグレード
- Java 17 か 21 へのアップグレード
- Kafka(OSGi) と Spring Boot、Quarkus、Standalone Camel などへの置き換え
- あたなの Camel インテグレーションの移行
はじめはこれらの作業量を膨大に感じるかもしれませんが、慌てないでください。
Camel Karaf から Camel 4 への移行
came-karaf ベースの Camel インテグレーションを移行するには、以下の移行が必要です:
- Javaコードを、Camel 3.x/3.x から Camel 4.x へ
- OSGi Blueprint XML ファイルを、Camel 4 XML/YAML DSL へ
camel-kafka の例を使い、どのような作業が必要かご紹介します。
最初の例題を移行
どれほど状況が悪いか簡単に確認する為、camel-jbang を使い例題を実行し、実行結果を確認します:
cd examples/camel-example-sql-blueprint
camel run pom.xml
camel-jbang は pom.xml を使い、既存 Mavenプロジェクトにて Camel がベストエフォートで実行するようなっています。この方法は、Mavenや Camelの実行方法の代替にはなりません。しかし、移行作業においては有用です。
例題を実行した際、何もエラーが出力されず動作することに気がつくでしょう。
何が起きたかというと、camel-jbang が OSGi blueprint XML ファイルを読み込むことができ、<bean> や <camelContext> を解析し、モダンな Camel 4 上で実行しています。これは、例題の移行作業が最小限であることを意味します。
Blueprint XML ファイルの移行
OSGi Blueprint XML ファイルを、XML か YAML DSL へ移行する必要があります。以下のように camel-jbang の transform コマンドで実施可能です:
camel transform route pom.xml
UI Designer
YAML DSL は、以下のスクリーンショットにある Apache Camel Karavan や Kaoto といった Camel designer で編集可能です。
この例題の移行には XMLを使うので、以下のように --format=xml を指定します:
camel transform route pom.xml --format=xml
ダンプをファイルへ書き出す
コンソールへプリントするのではなく、camel transform route コマンドを使いファイルやディレクトリーへ書き出すこともできます。
camel transform route pom.xml --format=xml --output=code
このコマンドで、code ディレクトリー配下に移行されたファイルが出力されます。
camel transform route --help を使い、このコマンドの詳細についてご確認ください。
次の移行作業は、生成されたファイルをご利用予定の runtime (Spring Boot、Quarkus、Camel Main など)へ出力します。
重要: 出力機能は、1回で移行および変換作業をサポートしません。つまり、変換された OSGi Blueprint ファイルを、適切なディレクトリーへ手動でコピーする必要があります。
Spring Boot へのエクスポート
以下のように、Spring Boot へエクスポートできます:
camel export pom.xml --gav=com.mycompany:myproject:1.0 --runtime=spring-boot --dir=code
Quarkus へのエクスポートはこのようになります:
camel export pom.xml --gav=com.mycompany:myproject:1.0 --runtime=quarkus --dir=code
移行の完了
エクスポート機能は Camel Karafベースのプロジェクトをフルサポートしていませんので、エクスポート終了後、プロジェクトを少し掃除する必要があります。
cd code
変換したルート(前回の作業)を、src/main/resources/camel ディレクトリー配下へコピーし、古い OSGi blueprint ファイルを削除する必要があるでしょう。
PS: 変換作業を忘れた場合、変換をやり直して以下のようなフォルダーへ直接出力できます:
cd ..
camel transform route pom.xml --format=xml --output=code/src/main/resources/camel
cd code
また、karaf feature.xml ファイルも削除すべきです。
その他、エクスポート ツールは application.properties で定義されている値のみをサポートするため、sql.properties から値をコピーする必要があります。つまり、値を sql.properties から code/src/main/resources/application.properties にコピーします。
Spring Boot で実行する場合は、 Web サーバーを使用するのがベスト プラクティスであるため、次のように pom.xml に依存関係を追加する必要があります:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
前述した作業後、プロジェクトをコンパイルし Spring Boot を実行できます:
mvn package spring-boot:run
アプリケーションは Spring Boot 上で実行し、無事に移行できました。
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.4.0)
2024-12-04T08:24:19.113+01:00 INFO 45359 --- [ main] c.mycompany.myproject.CamelApplication : Starting CamelApplication using Java 17.0.11 with PID 45359 (/Users/davsclaus/workspace/camel-karaf-examples/examples/camel-example-sql-blueprint/code/target/classes started by davsclaus in /Users/davsclaus/workspace/camel-karaf-examples/examples/camel-example-sql-blueprint/code)
2024-12-04T08:24:19.114+01:00 INFO 45359 --- [ main] c.mycompany.myproject.CamelApplication : No active profile set, falling back to 1 default profile: "default"
2024-12-04T08:24:19.679+01:00 INFO 45359 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
2024-12-04T08:24:19.685+01:00 INFO 45359 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-12-04T08:24:19.685+01:00 INFO 45359 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.33]
2024-12-04T08:24:19.708+01:00 INFO 45359 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-12-04T08:24:19.709+01:00 INFO 45359 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 574 ms
2024-12-04T08:24:19.897+01:00 WARN 45359 --- [ main] o.a.c.i.e.DefaultCamelBeanPostProcessor : No CamelContext defined yet so cannot inject into bean: startupConditionStrategy
2024-12-04T08:24:20.160+01:00 INFO 45359 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 1 endpoint beneath base path '/actuator'
2024-12-04T08:24:20.231+01:00 INFO 45359 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
2024-12-04T08:24:20.289+01:00 INFO 45359 --- [ main] o.apache.camel.example.sql.DatabaseBean : Creating table orders ...
2024-12-04T08:24:20.509+01:00 INFO 45359 --- [ main] o.apache.camel.example.sql.DatabaseBean : ... created table orders
2024-12-04T08:24:20.613+01:00 INFO 45359 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Apache Camel 4.9.0 (camel-example-sql-blueprint) is starting
2024-12-04T08:24:20.619+01:00 INFO 45359 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Routes startup (total:2)
2024-12-04T08:24:20.619+01:00 INFO 45359 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Started generateOrder-route (timer://foo)
2024-12-04T08:24:20.619+01:00 INFO 45359 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Started processOrder-route (sql://select%20*%20from%20orders%20where%20processed%20=%20false)
2024-12-04T08:24:20.619+01:00 INFO 45359 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Apache Camel 4.9.0 (camel-example-sql-blueprint) started in 6ms (build:0ms init:0ms start:6ms boot:715ms)
2024-12-04T08:24:20.620+01:00 INFO 45359 --- [ main] c.mycompany.myproject.CamelApplication : Started CamelApplication in 1.653 seconds (process running for 1.782)
2024-12-04T08:24:21.685+01:00 INFO 45359 --- [2 - timer://foo] generateOrder-route : Inserted new order 0
2024-12-04T08:24:22.187+01:00 INFO 45359 --- [sed%20=%20false] processOrder-route : Processed order id 0 item 222 of 10 copies of ActiveMQ in Action
それでは、次にもう少し複雑で追加作業が必要な例題を移行します。
より困難な移行
まずはこちらを実行しましょう:
cd camel-example-openapi-osgi
camel run pom.xml
実行すると、次のようなエラーが表示されます。
org.apache.camel.xml.io.XmlPullParserLocationException: Unexpected attribute '{}apiContextListing'
in file:src/main/resources/OSGI-INF/blueprint/camel.xml, line 42, column 42:
enableCORS="true">
^
Camel 4 への移行には DSL の変更が必要になる可能性があるため、これは予想されます。この例では、apiContextListing が削除されているため、src/main/resources/OSGI-INF/blueprint/camel.xml ファイル内の行を手動で修正する必要があります:
- apiContextPath="api-docs" apiContextListing="true"
+ apiContextPath="api-docs"
次に、camel run pom.xml を使用して再度実行してみます。
次のエラーは、description に関するものです:
org.apache.camel.xml.io.XmlPullParserLocationException: Unexpected element '{http://www.osgi.org/xmlns/blueprint/v1.0.0}description'
in file:src/main/resources/OSGI-INF/blueprint/camel.xml, line 58, column 20:
<description>User rest service</description>
<description> は属性に移行する必要があります。したがって、src/main/resources/OSGI-INF/blueprint/camel.xml 内のすべての <description> に対して修正を行う必要があります。この後、再度実行すると、別のエラーが発生します。
org.apache.camel.xml.io.XmlPullParserLocationException: Unexpected attribute '{}uri'
in file:src/main/resources/OSGI-INF/blueprint/camel.xml, line 60, column 99:
<get uri="/{id}" outType="org.apache.camel.example.rest.User" description="Find user by id">
GET、PUT、POST などのすべての REST 動詞については、次に示すように uri 属性の名前を path に変更する必要があります:
- <get uri="/{id}" outType="org.apache.camel.example.rest.User" description="Find user by id">
+ <get path="/{id}" outType="org.apache.camel.example.rest.User" description="Find user by id">
もうすぐそこまで来ましたが、最後のエラーが 1 つあります。
org.apache.camel.xml.io.XmlPullParserLocationException: Unexpected element '{http://www.osgi.org/xmlns/blueprint/v1.0.0}route'
in file:src/main/resources/OSGI-INF/blueprint/camel.xml, line 64, column 16:
<route>
Rest DSL では、インライン化された <route> はサポートされなくなり、これらのインライン化されたルートを別のルートに移動し、direct エンドポイント経由で呼び出す必要があります。
修正前:
<get path="/{id}" outType="org.apache.camel.example.rest.User" description="Find user by id">
<param name="id" type="path" description="The id of the user to get" dataType="integer"/>
<responseMessage message="The user that was found"/>
<responseMessage code="404" message="User not found"/>
<route>
<to uri="bean:userService?method=getUser(${header.id})"/>
<filter>
<simple>${body} == null</simple>
<setHeader name="Exchange.HTTP_RESPONSE_CODE">
<constant>404</constant>
</setHeader>
</filter>
</route>
</get>
修正後:
<get path="/{id}" outType="org.apache.camel.example.rest.User" description="Find user by id">
<param name="id" type="path" description="The id of the user to get" dataType="integer"/>
<responseMessage message="The user that was found"/>
<responseMessage code="404" message="User not found"/>
<to uri="direct:getUser"/>
</get>
<route>
<from uri="direct:getUser"/>
<to uri="bean:userService?method=getUser(${header.id})"/>
<filter>
<simple>${body} == null</simple>
<setHeader name="Exchange.HTTP_RESPONSE_CODE">
<constant>404</constant>
</setHeader>
</filter>
</route>
ついにアプリケーションが Camel 4 で実行できるようになりました。
$ camel run pom.xml
2024-12-04 08:43:40.809 INFO 45721 --- [ main] org.apache.camel.main.MainSupport : Apache Camel (JBang) 4.9.0 is starting
2024-12-04 08:43:40.917 INFO 45721 --- [ main] org.apache.camel.main.MainSupport : Using Java 17.0.11 with PID 45721. Started by davsclaus in /Users/davsclaus/workspace/camel-karaf-examples/examples/camel-example-openapi-osgi
2024-12-04 08:43:43.599 INFO 45721 --- [ main] .main.download.MavenDependencyDownloader : Resolved: org.apache.camel:camel-spring:4.9.0 (took: 2s678ms)
2024-12-04 08:43:47.734 INFO 45721 --- [ main] .main.download.MavenDependencyDownloader : Resolved: org.apache.camel:camel-openapi-java:4.9.0 (took: 2s219ms)
2024-12-04 08:43:47.761 INFO 45721 --- [ main] org.apache.camel.main.BaseMainSupport : Properties location: file:src/main/resources/log4j2.properties
2024-12-04 08:43:47.794 INFO 45721 --- [ main] org.apache.camel.main.ProfileConfigurer : The application is starting with profile: dev
2024-12-04 08:43:53.110 INFO 45721 --- [ main] .main.download.MavenDependencyDownloader : Resolved: org.apache.camel:camel-xml-io-dsl:4.9.0 (took: 2s79ms)
2024-12-04 08:43:53.540 INFO 45721 --- [ main] n.xml.blueprint.BlueprintXmlBeansHandler : Discovered 1 OSGi XML beans
2024-12-04 08:43:53.649 INFO 45721 --- [ main] he.camel.cli.connector.LocalCliConnector : Camel JBang CLI enabled
2024-12-04 08:43:54.710 INFO 45721 --- [ main] e.camel.impl.engine.AbstractCamelContext : Apache Camel 4.9.0 (myCamel) is starting
2024-12-04 08:43:54.982 INFO 45721 --- [ main] org.eclipse.jetty.server.Server : jetty-12.0.15; built: 2024-11-05T19:44:57.623Z; git: 8281ae9740d4b4225e8166cc476bad237c70213a; jvm 17.0.11+9-LTS
2024-12-04 08:43:55.001 INFO 45721 --- [ main] ipse.jetty.server.handler.ContextHandler : Started oeje10s.ServletContextHandler@10a064bd{ROOT,/,b=null,a=AVAILABLE,h=oeje10s.ServletHandler@2de7fe0e{STARTED}}
2024-12-04 08:43:55.003 INFO 45721 --- [ main] jetty.ee10.servlet.ServletContextHandler : Started oeje10s.ServletContextHandler@10a064bd{ROOT,/,b=null,a=AVAILABLE,h=oeje10s.ServletHandler@2de7fe0e{STARTED}}
2024-12-04 08:43:55.010 INFO 45721 --- [ main] g.eclipse.jetty.server.AbstractConnector : Started ServerConnector@26f11b40{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2024-12-04 08:43:55.011 INFO 45721 --- [ main] org.eclipse.jetty.server.Server : Started oejs.Server@3883b5e9{STARTING}[12.0.15,sto=0] @15508ms
2024-12-04 08:43:55.092 INFO 45721 --- [ main] e.camel.impl.engine.AbstractCamelContext : Routes startup (total:3 rest-dsl:2)
2024-12-04 08:43:55.092 INFO 45721 --- [ main] e.camel.impl.engine.AbstractCamelContext : Started route2 (direct://getUser)
2024-12-04 08:43:55.092 INFO 45721 --- [ main] e.camel.impl.engine.AbstractCamelContext : Started route1 (rest-api://api-docs)
2024-12-04 08:43:55.092 INFO 45721 --- [ main] e.camel.impl.engine.AbstractCamelContext : Started route3 (rest://get:/echo:/ping)
2024-12-04 08:43:55.092 INFO 45721 --- [ main] e.camel.impl.engine.AbstractCamelContext : Apache Camel 4.9.0 (myCamel) started in 381ms (build:0ms init:0ms start:381ms boot:13s900ms)
Camel Quarkus への移行
この例題では、Spring Boot ではなく Camel Quarkus に移行します。
camel export pom.xml --gav=com.mycompany:myproject:1.0 --runtime=quarkus --dir=code
異なるエラーが出力されます:
Generating fresh run data
Running using Quarkus v3.17.2 (preparing and downloading files)
org.apache.camel.FailedToStartRouteException: Failed to start route route3 because of Component jetty is not a RestConsumerFactory
これは、古い Karaf の例が、Rest DSL サービスをホストするための HTTP サーバーとして Jetty を使用しているからです。これを削除し、Quarkus (または Spring Boot) に付属するデフォルトの platform-http を Camel で使用できるようにする必要があります。
したがって、次のように XML ファイルを修正します:
<restConfiguration bindingMode="json"
contextPath="rest" port="8080"
apiContextPath="api-docs"
enableCORS="true"
inlineRoutes="false">
重要: Rest DSL を使用する場合、Camel JBang がルートを変換できるようにルートを分離する必要があるため、inlineRoutes="false" を設定する必要があります。この問題は、Camel 4.10 以降では自動的に修正される可能性があります。
export を再度実行します。
次に、Blueprint XML ファイルを移行し、以下のように src/main/resources/camel ディレクトリーへ直接出力します:
camel transform route pom.xml --format=xml --output=code/src/main/resources/camel
次に、Camel 4 on Quarkus へ完全に移行するため、プロジェクトを掃除する必要があります。
pom.xml で、camel-jetty と Camel-spring の依存関係を削除します。
また、src/main/resources/camel.xml ファイルに <restConfiguration> を追加する必要があります。これらは、camel transform route コマンドに自動で含まれないためです。
よって、ファイル先頭の <camel> ルート タグ配下に、これを追加します:
<restConfiguration bindingMode="json"
contextPath="rest" port="8080"
apiContextPath="api-docs"
enableCORS="true"
inlineRoutes="false">
<!-- we want json output in pretty mode -->
<dataFormatProperty key="prettyPrint" value="true"/>
<!-- setup openapi api descriptions -->
<apiProperty key="base.path" value="rest"/>
<apiProperty key="api.version" value="1.2.3"/>
<apiProperty key="api.title" value="User Services"/>
<apiProperty key="api.description" value="Camel Rest Example with OpenApi that provides an User REST service"/>
<apiProperty key="api.contact.name" value="The Apache Camel team"/>
</restConfiguration>
この作業後、次のように移行したサンプルをコンパイルし、 Camel Quarkus で実行できるようになります:
$ mvn package quarkus:run
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2024-12-04 11:09:03,974 INFO [org.apa.cam.qua.cor.CamelBootstrapRecorder] (main) Apache Camel Quarkus 3.16.0 is starting
2024-12-04 11:09:03,979 INFO [org.apa.cam.mai.MainSupport] (main) Apache Camel (Main) 4.8.1 is starting
2024-12-04 11:09:04,066 INFO [org.apa.cam.mai.BaseMainSupport] (main) Auto-configuration summary
2024-12-04 11:09:04,066 INFO [org.apa.cam.mai.BaseMainSupport] (main) [MicroProfilePropertiesSource] camel.main.routesIncludePattern = camel/camel.xml
2024-12-04 11:09:04,066 INFO [org.apa.cam.mai.BaseMainSupport] (main) [MicroProfilePropertiesSource] camel.main.name = camel-example-openapi-osgi
2024-12-04 11:09:04,158 INFO [org.apa.cam.imp.eng.AbstractCamelContext] (main) Apache Camel 4.8.1 (camel-example-openapi-osgi) is starting
2024-12-04 11:09:04,463 INFO [org.apa.cam.imp.eng.AbstractCamelContext] (main) Routes startup (total:5 rest-dsl:4)
2024-12-04 11:09:04,463 INFO [org.apa.cam.imp.eng.AbstractCamelContext] (main) Started route2 (direct://getUser)
2024-12-04 11:09:04,463 INFO [org.apa.cam.imp.eng.AbstractCamelContext] (main) Started route1 (rest-api://api-docs)
2024-12-04 11:09:04,464 INFO [org.apa.cam.imp.eng.AbstractCamelContext] (main) Started route3 (rest://get:/user:/%7Bid%7D)
2024-12-04 11:09:04,464 INFO [org.apa.cam.imp.eng.AbstractCamelContext] (main) Started route4 (rest://put:/user)
2024-12-04 11:09:04,464 INFO [org.apa.cam.imp.eng.AbstractCamelContext] (main) Started route5 (rest://get:/user:/findAll)
2024-12-04 11:09:04,465 INFO [org.apa.cam.imp.eng.AbstractCamelContext] (main) Apache Camel 4.8.1 (camel-example-openapi-osgi) started in 305ms (build:0ms init:0ms start:305ms)
2024-12-04 11:09:04,567 INFO [io.quarkus] (main) myproject 1.0 on JVM (powered by Quarkus 3.17.2) started in 0.989s. Listening on: http://0.0.0.0:8080
2024-12-04 11:09:04,567 INFO [io.quarkus] (main) Profile prod activated.
2024-12-04 11:09:04,568 INFO [io.quarkus] (main) Installed features: [camel-attachments, camel-bean, camel-core, camel-direct, camel-jackson, camel-microprofile-health, camel-openapi-java, camel-platform-http, camel-rest, camel-xml-io-dsl, cdi, smallrye-context-propagation, smallrye-health, vertx]
そして、次のような Rest サービスを呼び出すことができるはずです:
curl http://0.0.0.0:8080/rest/user/123
{
"id" : 123,
"name" : "John Doe"
}
ふー、これは少し大変でした。
まとめ
Camel JBang ツールは、OSGi Blueprint XML ファイルを最新の Camel へ移行するのに役立つツールです。特殊な OSGi 機能を使用するより複雑な OSGi アプリケーションを構築している場合は、手動で移行する必要があります。
Camel 4 では、従来の Apache Karaf よりもはるかに大きなコミュニティとユーザー ベースを持つ Spring Boot または Quarkus の最新スタック上で動作するので、将来のアップグレードは、はるかに簡単になります。
Rest DSL から YAML DSL への変換はまだサポートされていないことに注意してください。たとえば、Rest を使用して移行した最後の例では、YAML DSL の REST 要素を自動生成することはできません。これは将来的に実装される予定です。
詳細については、Camel 3.x/4.x の移行およびアップグレード ガイドを参照してください。移行に関するほとんどの問題は、ガイド (上記) に記載されています。
Camel JBang ツールは、このブログ投稿に示されているように、既存プロジェクトの移行をすぐ試すのに役立ちます。
移行ツールに関するフィードバックは大歓迎です。頑張ってください。モダンな Camel 4 の世界で会いましょう。
0 件のコメント:
コメントを投稿