46.3. 生成されたコンポーネントサブプロジェクト
概要
新しいコンポーネントのビルド用の Maven サブプロジェクトは camel-api-example/camel-api-example-component
プロジェクトディレクトリーの下にあります。このセクションでは、生成されたサンプルコードの詳細と、その動作を説明します。
コンポーネント POM での Java API の提供
Java API はコンポーネント POM の依存関係として提供される必要があります。たとえば、サンプル Java API は、以下のようにコンポーネント POM ファイルの依存関係 camel-api-example-component/pom.xml
として定義されます。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> ... <dependencies> ... <dependency> <groupId>org.jboss.fuse.example</groupId> <artifactId>camel-api-example-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> ... </dependencies> ... </project>
コンポーネント POM での Javadoc メタデータの提供
Java API のすべてのまたは一部に Javadoc メタデータを使用している場合は、コンポーネント POM の依存関係として Javadoc を指定する必要があります。この依存関係に関して注意することが 2 つあります。
Javadoc の Maven コーディネートは Java API の Maven コーディネートとほぼ同じですが、以下のように
classifier
要素も指定する必要があります。<classifier>javadoc</classifier>
以下のように、
provided
スコープを持つよう Javadoc を宣言する必要があります。<scope>provided</scope>
たとえば、コンポーネント POM では、Javadoc 依存関係は以下のように定義されます。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> ... <dependencies> ... <!-- Component API javadoc in provided scope to read API signatures --> <dependency> <groupId>org.jboss.fuse.example</groupId> <artifactId>camel-api-example-api</artifactId> <version>1.0-SNAPSHOT</version> <classifier>javadoc</classifier> <scope>provided</scope> </dependency> ... </dependencies> ... </project>
サンプルファイル Hello のファイルメタデータの定義
ExampleFileHello
のメタデータは署名ファイルで提供されます。通常、このファイルは手動で作成する必要がありますが、メソッド署名のリスト (各行に 1 つずつ) で構成される非常にシンプルな形式です。このサンプルコードは camel-api-example-component/signatures
ディレクトリーに以下の内容を含む署名ファイル file-sig-api.txt
を提供します。
public String sayHi(); public String greetMe(String name); public String greetUs(String name1, String name2);
署名ファイル形式の詳細は、「署名ファイルメタデータ」 を参照してください。
API マッピングの設定
API コンポーネントフレームワークの主な機能の 1 つは、API マッピング を実行するコードを自動的に生成することです。つまり、エンドポイント URI を Java API のメソッド呼び出しにマッピングするスタブコードを生成します。API マッピングへの基本的な入力は、Java API、Javadoc メタデータ、署名ファイルのメタデータなどです。
API マッピングを実行するコンポーネントは、コンポーネント POM で設定された camel-api-component-maven-plugin
Maven プラグインです。コンポーネント POM からの以下の抜粋は、camel-api-component-maven-plugin
プラグインの設定方法を示しています。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> ... <build> <defaultGoal>install</defaultGoal> <plugins> ... <!-- generate Component source and test source --> <plugin> <groupId>org.apache.camel</groupId> <artifactId>camel-api-component-maven-plugin</artifactId> <executions> <execution> <id>generate-test-component-classes</id> <goals> <goal>fromApis</goal> </goals> <configuration> <apis> <api> <apiName>hello-file</apiName> <proxyClass>org.jboss.fuse.example.api.ExampleFileHello</proxyClass> <fromSignatureFile>signatures/file-sig-api.txt</fromSignatureFile> </api> <api> <apiName>hello-javadoc</apiName> <proxyClass>org.jboss.fuse.example.api.ExampleJavadocHello</proxyClass> <fromJavadoc/> </api> </apis> </configuration> </execution> </executions> </plugin> ... </plugins> ... </build> ... </project>
プラグインは、Java API のクラスを設定するための単一の apis
子要素が含まれる configuration
要素によって設定されます。各 API クラスは以下のように api
要素によって設定されます。
apiName
API name は、API クラスの短縮名で、エンドポイント URI の
endpoint-prefix
として使用されます。注記API が単一の Java クラスのみで構成される場合は、
apiName
要素を空のままにすることができます。これにより、endpoint-prefix
は冗長になります。その後、「単一 API クラスの URI 形式」 に示す形式を使用して、エンドポイント URI を指定できます。proxyClass
- このプロキシークラスの要素は、API クラスの完全修飾名を指定します。
fromJavadoc
-
API クラスに Javadoc メタデータが付随する場合、それを示すために
fromJavadoc
要素を含める必要があります。provided
依存関係として、Javadoc 自体も Maven ファイルで指定する必要があります (「コンポーネント POM での Javadoc メタデータの提供」を参照)。 fromSignatureFile
API クラスに署名ファイルのメタデータが付随する場合、これを示すために
fromSignatureFile
要素を含める必要があります。この要素の内容で署名ファイルの場所を指定します。注記署名ファイルは、実行時ではなくビルド時にのみ必要であるため、Maven によってビルドされた最終パッケージには含まれません。
生成されたコンポーネントの実装
API コンポーネントは、camel-api-example-component/src/main/java
ディレクトリー下において以下のコアクラス (Camel コンポーネントすべてに実装する必要がある) から構成されます。
ExampleComponent
-
コンポーネント自体を表します。このクラスは、エンドポイントインスタンスのファクトリーとして機能します (例:
ExampleEndpoint
のインスタンス) 。 ExampleEndpoint
-
エンドポイント URI を表します。このクラスは、コンシューマーエンドポイント (例:
ExampleConsumer
) のファクトリーとして機能し、またプロデューサーエンドポイント (例:ExampleProducer
) のファクトリーとして機能します。 ExampleConsumer
- エンドポイント URI で指定された場所からメッセージを消費できるコンシューマーエンドポイントの具象インスタンスを表します。
ExampleProducer
- プロデューサーエンドポイントの具象インスタンスを表します。これは、エンドポイント URI で指定された場所にメッセージを送信できます。
ExampleConfiguration
エンドポイント URI オプションを定義するために使用できます。この設定クラスによって定義される URI オプションは特定の API クラスには関連付けられません。つまり、これらの URI オプションを API クラスまたはメソッドのいずれかと組み合わせることができます。これは、たとえば、リモートサービスへの接続にユーザー名およびパスワードの認証情報を宣言する必要がある場合などに役立ちます。
ExampleConfiguration
クラスの主な目的は、API クラスまたは API インターフェイスを実装するクラスに必要なパラメーターの値を提供することです。たとえば、これらはコンストラクターパラメーターや、ファクトリーメソッドまたはクラスのパラメーター値になります。このクラスで URI オプション
option
を実装するために必要なのは、アクセッサーメソッドのペアgetOption
andsetOption
を実装することだけです。コンポーネントフレームワークはエンドポイント URI を自動的に解析し、実行時にオプション値を挿入します。
ExampleComponent クラス
生成された ExampleComponent
クラスは、以下のように定義されます。
// Java package org.jboss.fuse.example; import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.util.component.AbstractApiComponent; import org.jboss.fuse.example.internal.ExampleApiCollection; import org.jboss.fuse.example.internal.ExampleApiName; /** * Represents the component that manages {@link ExampleEndpoint}. */ @UriEndpoint(scheme = "example", consumerClass = ExampleConsumer.class, consumerPrefix = "consumer") public class ExampleComponent extends AbstractApiComponent<ExampleApiName, ExampleConfiguration, ExampleApiCollection> { public ExampleComponent() { super(ExampleEndpoint.class, ExampleApiName.class, ExampleApiCollection.getCollection()); } public ExampleComponent(CamelContext context) { super(context, ExampleEndpoint.class, ExampleApiName.class, ExampleApiCollection.getCollection()); } @Override protected ExampleApiName getApiName(String apiNameStr) throws IllegalArgumentException { return ExampleApiName.fromValue(apiNameStr); } @Override protected Endpoint createEndpoint(String uri, String methodName, ExampleApiName apiName, ExampleConfiguration endpointConfiguration) { return new ExampleEndpoint(uri, this, apiName, methodName, endpointConfiguration); } }
このクラスの重要なメソッドは createEndpoint
で、これは新しいエンドポイントインスタンスを作成します。通常、コンポーネントクラスのデフォルトコードを変更する必要はありません。ただし、このコンポーネントのライフサイクルと同じオブジェクトが存在する場合は、これらのオブジェクトをコンポーネントクラスから利用できるようにすることができます (例: メソッドを追加してこれらのオブジェクトを作成、これらのオブジェクトをコンポーネントに注入)。
ExampleEndpoint クラス
生成された ExampleEndpoint
クラスは以下のように定義されます。
// Java package org.jboss.fuse.example; import java.util.Map; import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.util.component.AbstractApiEndpoint; import org.apache.camel.util.component.ApiMethod; import org.apache.camel.util.component.ApiMethodPropertiesHelper; import org.jboss.fuse.example.api.ExampleFileHello; import org.jboss.fuse.example.api.ExampleJavadocHello; import org.jboss.fuse.example.internal.ExampleApiCollection; import org.jboss.fuse.example.internal.ExampleApiName; import org.jboss.fuse.example.internal.ExampleConstants; import org.jboss.fuse.example.internal.ExamplePropertiesHelper; /** * Represents a Example endpoint. */ @UriEndpoint(scheme = "example", consumerClass = ExampleConsumer.class, consumerPrefix = "consumer") public class ExampleEndpoint extends AbstractApiEndpoint<ExampleApiName, ExampleConfiguration> { // TODO create and manage API proxy private Object apiProxy; public ExampleEndpoint(String uri, ExampleComponent component, ExampleApiName apiName, String methodName, ExampleConfiguration endpointConfiguration) { super(uri, component, apiName, methodName, ExampleApiCollection.getCollection().getHelper(apiName), endpointConfiguration); } public Producer createProducer() throws Exception { return new ExampleProducer(this); } public Consumer createConsumer(Processor processor) throws Exception { // make sure inBody is not set for consumers if (inBody != null) { throw new IllegalArgumentException("Option inBody is not supported for consumer endpoint"); } final ExampleConsumer consumer = new ExampleConsumer(this, processor); // also set consumer.* properties configureConsumer(consumer); return consumer; } @Override protected ApiMethodPropertiesHelper<ExampleConfiguration> getPropertiesHelper() { return ExamplePropertiesHelper.getHelper(); } protected String getThreadProfileName() { return ExampleConstants.THREAD_PROFILE_NAME; } @Override protected void afterConfigureProperties() { // TODO create API proxy, set connection properties, etc. switch (apiName) { case HELLO_FILE: apiProxy = new ExampleFileHello(); break; case HELLO_JAVADOC: apiProxy = new ExampleJavadocHello(); break; default: throw new IllegalArgumentException("Invalid API name " + apiName); } } @Override public Object getApiProxy(ApiMethod method, Map<String, Object> args) { return apiProxy; } }
API コンポーネントフレームワークのコンテキストでは、エンドポイントクラスによって実行される主なステップの 1 つは、API プロキシー を作成することです。API プロキシーは、ターゲット Java API からのインスタンスで、メソッドがエンドポイントによって呼び出されます。通常、Java API は多くのクラスで構成されるため、URI に表示される endpoint-prefix
を基にして、適切な API クラスを選択する必要があります (URI の一般形式は scheme://endpoint-prefix/endpoint
であることに留意してください)。
ExampleConsumer クラス
生成された ExampleConsumer
クラスは以下のように定義されます。
// Java package org.jboss.fuse.example; import org.apache.camel.Processor; import org.apache.camel.util.component.AbstractApiConsumer; import org.jboss.fuse.example.internal.ExampleApiName; /** * The Example consumer. */ public class ExampleConsumer extends AbstractApiConsumer<ExampleApiName, ExampleConfiguration> { public ExampleConsumer(ExampleEndpoint endpoint, Processor processor) { super(endpoint, processor); } }
ExampleProducer クラス
生成された ExampleProducer
クラスは以下のように定義されます。
// Java package org.jboss.fuse.example; import org.apache.camel.util.component.AbstractApiProducer; import org.jboss.fuse.example.internal.ExampleApiName; import org.jboss.fuse.example.internal.ExamplePropertiesHelper; /** * The Example producer. */ public class ExampleProducer extends AbstractApiProducer<ExampleApiName, ExampleConfiguration> { public ExampleProducer(ExampleEndpoint endpoint) { super(endpoint, ExamplePropertiesHelper.getHelper()); } }
ExampleConfiguration クラス
生成された ExampleConfiguration
クラスは以下のように定義されます。
// Java package org.jboss.fuse.example; import org.apache.camel.spi.UriParams; /** * Component configuration for Example component. */ @UriParams public class ExampleConfiguration { // TODO add component configuration properties }
このクラスに URI オプション option
を追加するには、適切なタイプのフィールドを定義し、対応するアクセッサーメソッド (getOption
および setOption
) のペアを実装します。コンポーネントフレームワークはエンドポイント URI を自動的に解析し、実行時にオプション値を挿入します。
このクラスは、すべての API メソッドと組み合わせることができる 一般的な URI オプションを定義するために使用されます。特定の API メソッドに関連する URI オプションを定義するには、API コンポーネント Maven プラグインに 追加のオプション を設定します。詳細は、「追加オプション」 を参照してください。
URI 形式
API コンポーネント URI の一般的な形式を取ります。
scheme://endpoint-prefix/endpoint?Option1=Value1&...&OptionN=ValueN
通常、URI は Java API の特定のメソッド呼び出しにマッピングされます。たとえば、API メソッド ExampleJavadocHello.greetMe("Jane Doe")
を呼び出す場合、以下のように URI が作成されます。
- scheme
-
Maven archetype でコードを生成した時に指定される API コンポーネントスキーム。この場合、スキームは
example
です。 - endpoint-prefix
camel-api-component-maven-plugin
Maven プラグイン設定で定義される API クラスにマップする API 名。ExampleJavadocHello
クラスの場合、関連する設定は以下のとおりです。<configuration> <apis> <api> <apiName>hello-javadoc</apiName> <proxyClass>org.jboss.fuse.example.api.ExampleJavadocHello</proxyClass> <fromJavadoc/> </api> ... </apis> </configuration>
これは、必要な
endpoint-prefix
がhello-javadoc
であることを示しています。- endpoint
-
endpoint
は、メソッド名greetMe
にマップします。 - Option1=Value1
-
URI オプションはメソッドパラメーターを指定します。
greetMe(String name)
メソッドは、name=Jane%20Doe
として指定できる単一のパラメーターname
を取ります。オプションのデフォルト値を定義する場合は、interceptProperties
メソッドを上書きしてこれを行うことができます (「プログラミングモデル」 を参照)。
URI の一部をまとめると、以下の URI で ExampleJavadocHello.greetMe("Jane Doe")
を呼び出しできることがわかります。
example://hello-javadoc/greetMe?name=Jane%20Doe
デフォルトのコンポーネントインスタンス
example
URI スキームをデフォルトのコンポーネントインスタンスにマッピングするために、Maven archetype は camel-api-example-component
サブプロジェクトに以下のファイルを作成します。
src/main/resources/META-INF/services/org/apache/camel/component/example
このリソースファイルは、Camel コアが example
URI スキームに関連付けられたコンポーネントを特定できるようにします。ルートで example://
URI を使用するたびに、Camel はクラスパスを検索し、対応する example
リソースファイルを探します。この example
ファイルには、以下のコンテンツが含まれます。
class=org.jboss.fuse.example.ExampleComponent
これにより、Camel コアは ExampleComponent
コンポーネントのデフォルトインスタンスを作成できます。このファイルを編集する必要があるのは、コンポーネントクラスの名前をリファクタリングする場合のみです。