第295章 Camel SCR (非推奨)
Camel 2.15 以降で利用可能
SCR は Service Component Runtime の略で、OSGi Declarative Services 仕様の実装です。SCR を使用すると、定型コードを使用せずに、プレーンな古い Java オブジェクトで OSGi サービスを公開して使用できます。
OSGi フレームワークは、通常は org.apache.felix:maven-scr-plugin
などのプラグインによって Java アノテーションから生成されるバンドル内の SCR 記述子ファイルを調べることで、オブジェクトを認識します。
SCR バンドルで Camel を実行することは、Spring DM および Blueprint ベースのソリューションの優れた代替手段であり、OSGi フレームワークとの間のコード行が大幅に少なくなります。SCR を使用すると、バンドルは完全に Java の世界にとどまることができます。XML またはプロパティーファイルを編集する必要はありません。これにより、すべてを完全に制御でき、選択した IDE がプロジェクトで何が起こっているかを正確に認識できることを意味します。
295.1. Camel SCR サポート
Camel-scr バンドルは 2.15.0 より前の Apache Camel バージョンには含まれていませんが、アーティファクト自体は 2.12.0 以降のすべての Camel バージョンで使用できます。
org.apache.camel/camel-scr
バンドルは、Camel コンテキストを管理する基本クラス AbstractCamelRunner
と、単体テストで SCR プロパティーを使用するためのヘルパークラス ScrHelper
を提供します。Apache Karaf の Camel-scr 機能は、SCR バンドルで Camel を実行するために必要なすべての機能とバンドルを定義します。
AbstractCamelRunner
クラスは、CamelContext のライフサイクルをサービスコンポーネントのライフサイクルに結び付け、Camel の PropertiesComponent を使用して設定を処理します。Java クラスからサービスコンポーネントを作成するために必要なのは、それを AbstractCamelRunner
から拡張し、クラスレベルで次の org.apache.felix.scr.annotations
を追加することだけです。
必要なアノテーションを追加する
@Component @References({ @Reference(name = "camelComponent",referenceInterface = ComponentResolver.class, cardinality = ReferenceCardinality.MANDATORY_MULTIPLE, policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, bind = "gotCamelComponent", unbind = "lostCamelComponent") })
次に、実行する Camel ルートを返す getRouteBuilders()
メソッドを実装します。
Implement getRouteBuilders()
@Override protected List<RoutesBuilder> getRouteBuilders() { List<RoutesBuilder> routesBuilders = new ArrayList<>(); routesBuilders.add(new YourRouteBuilderHere(registry)); routesBuilders.add(new AnotherRouteBuilderHere(registry)); return routesBuilders; }
最後に、デフォルト設定を次のように指定します。
アノテーションのデフォルト設定
@Properties({ @Property(name = "camelContextId", value = "my-test"), @Property(name = "active", value = "true"), @Property(name = "...", value = "..."), ... })
以上です。そして、camel-archetype-scr
を使用してプロジェクトを生成した場合、これはすべてすでに処理されています。
以下は、camel-archetype-scr:
によって生成された完全なサービスコンポーネントクラスの例です。
CamelScrExample.java
// This file was generated from org.apache.camel.archetypes/camel-archetype-scr/2.15-SNAPSHOT package example; import java.util.ArrayList; import java.util.List; import org.apache.camel.scr.AbstractCamelRunner; import example.internal.CamelScrExampleRoute; import org.apache.camel.RoutesBuilder; import org.apache.camel.spi.ComponentResolver; import org.apache.felix.scr.annotations.*; @Component(label = CamelScrExample.COMPONENT_LABEL, description = CamelScrExample.COMPONENT_DESCRIPTION, immediate = true, metatype = true) @Properties({ @Property(name = "camelContextId", value = "camel-scr-example"), @Property(name = "camelRouteId", value = "foo/timer-log"), @Property(name = "active", value = "true"), @Property(name = "from", value = "timer:foo?period=5000"), @Property(name = "to", value = "log:foo?showHeaders=true"), @Property(name = "messageOk", value = "Success: {{from}} -> {{to}}"), @Property(name = "messageError", value = "Failure: {{from}} -> {{to}}"), @Property(name = "maximumRedeliveries", value = "0"), @Property(name = "redeliveryDelay", value = "5000"), @Property(name = "backOffMultiplier", value = "2"), @Property(name = "maximumRedeliveryDelay", value = "60000") }) @References({ @Reference(name = "camelComponent",referenceInterface = ComponentResolver.class, cardinality = ReferenceCardinality.MANDATORY_MULTIPLE, policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, bind = "gotCamelComponent", unbind = "lostCamelComponent") }) public class CamelScrExample extends AbstractCamelRunner { public static final String COMPONENT_LABEL = "example.CamelScrExample"; public static final String COMPONENT_DESCRIPTION = "This is the description for camel-scr-example."; @Override protected List<RoutesBuilder> getRouteBuilders() { List<RoutesBuilder> routesBuilders = new ArrayList<>(); routesBuilders.add(new CamelScrExampleRoute(registry)); return routesBuilders; } }
CamelContextId
と active
プロパティーは、CamelContext の名前 (デフォルトは "camel-runner-default") と、それを開始するかどうか (デフォルトは "false") をそれぞれ制御します。これらに加えて、好きなだけプロパティーを追加して使用できます。Camel の PropertiesComponent は、再帰的なプロパティーとフォールバックの接頭辞を問題なく処理します。
AbstractCamelRunner
は、Camel の PropertiesComponent を使用して、これらのプロパティーを RouteBuilders で利用できるようにし、名前が一致する場合、サービスコンポーネントと RouteBuilder のフィールドにもこれらの値を注入します。フィールドは任意の可視性レベルで宣言でき、多くの型がサポートされています (String、int、boolean、URL など)。
以下は camel-archetype-scr
によって生成された RouteBuilder クラスの例です:
CamelScrExampleRoute.java
// This file was generated from org.apache.camel.archetypes/camel-archetype-scr/2.15-SNAPSHOT package example.internal; import org.apache.camel.LoggingLevel; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.SimpleRegistry; import org.apache.commons.lang.Validate; public class CamelScrExampleRoute extends RouteBuilder { SimpleRegistry registry; // Configured fields private String camelRouteId; private Integer maximumRedeliveries; private Long redeliveryDelay; private Double backOffMultiplier; private Long maximumRedeliveryDelay; public CamelScrExampleRoute(final SimpleRegistry registry) { this.registry = registry; } @Override public void configure() throws Exception { checkProperties(); // Add a bean to Camel context registry registry.put("test", "bean"); errorHandler(defaultErrorHandler() .retryAttemptedLogLevel(LoggingLevel.WARN) .maximumRedeliveries(maximumRedeliveries) .redeliveryDelay(redeliveryDelay) .backOffMultiplier(backOffMultiplier) .maximumRedeliveryDelay(maximumRedeliveryDelay)); from("{{from}}") .startupOrder(2) .routeId(camelRouteId) .onCompletion() .to("direct:processCompletion") .end() .removeHeaders("CamelHttp*") .to("{{to}}"); from("direct:processCompletion") .startupOrder(1) .routeId(camelRouteId + ".completion") .choice() .when(simple("${exception} == null")) .log("{{messageOk}}") .otherwise() .log(LoggingLevel.ERROR, "{{messageError}}") .end(); } } public void checkProperties() { Validate.notNull(camelRouteId, "camelRouteId property is not set"); Validate.notNull(maximumRedeliveries, "maximumRedeliveries property is not set"); Validate.notNull(redeliveryDelay, "redeliveryDelay property is not set"); Validate.notNull(backOffMultiplier, "backOffMultiplier property is not set"); Validate.notNull(maximumRedeliveryDelay, "maximumRedeliveryDelay property is not set"); } }
CamelScrExampleRoute
をさらに詳しく見てみましょう。
// Configured fields private String camelRouteId; private Integer maximumRedeliveries; private Long redeliveryDelay; private Double backOffMultiplier; private Long maximumRedeliveryDelay;
これらのフィールドの値は、名前を一致させることにより、プロパティからの値で設定されます。
// Add a bean to Camel context registry registry.put("test", "bean");
ルート用にいくつかの Bean を CamelContext のレジストリーに追加する必要がある場合は、次のように実行できます。
public void checkProperties() { Validate.notNull(camelRouteId, "camelRouteId property is not set"); Validate.notNull(maximumRedeliveries, "maximumRedeliveries property is not set"); Validate.notNull(redeliveryDelay, "redeliveryDelay property is not set"); Validate.notNull(backOffMultiplier, "backOffMultiplier property is not set"); Validate.notNull(maximumRedeliveryDelay, "maximumRedeliveryDelay property is not set"); }
ルートの開始を許可する前に、必要なパラメーターが設定されていて、それらに意味のある値があることを確認することをお勧めします。
from("{{from}}") .startupOrder(2) .routeId(camelRouteId) .onCompletion() .to("direct:processCompletion") .end() .removeHeaders("CamelHttp*") .to("{{to}}"); from("direct:processCompletion") .startupOrder(1) .routeId(camelRouteId + ".completion") .choice() .when(simple("${exception} == null")) .log("{{messageOk}}") .otherwise() .log(LoggingLevel.ERROR, "{{messageError}}") .end();
ルートのほとんどすべてがプロパティーで設定されていることに注意してください。これにより、基本的に RouteBuilder がテンプレートになります。SCR を使用すると、代替設定を提供するだけで、ルートのインスタンスをさらに作成できます。詳細については、Camel SCR バンドルをテンプレートとして使用する セクションを参照してください。