第75章 CXF
CXF コンポーネント
cxf: コンポーネントは、CXF でホストされている JAX-WS サービスに接続するための Apache CXF との統合を提供します。
Maven ユーザーは、このコンポーネントの pom.xml
に以下の依存関係を追加する必要があります。
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-cxf</artifactId> <version>x.x.x</version> <!-- use the same version as your Camel core version --> </dependency>
CXF の依存関係について知りたい場合は、WHICH-JARS
テキストファイルを参照してください。
ストリーミングモードで CXF を使用する場合 (DataFormat オプションを参照)、Stream caching についてもお読みください。
Camel on EAP デプロイメント
このコンポーネントは、Red Hat JBoss Enterprise Application Platform (JBoss EAP) コンテナー上で簡素化されたデプロイメントモデルを提供する Camel on EAP (Wildfly Camel) フレームワークによってサポートされます。
CXF コンポーネントは、Apache CXF も使用する JBoss EAP Web サービス
サブシステムと統合します。詳細については、JAX-WS を参照してください。
現在、Camel on EAP サブシステムは CXF または Restlet コンシューマーをサポートしてい ません。ただし、CamelProxy
を使用して、CXF コンシューマーの動作を模倣することは可能です。
URI 形式
cxf:bean:cxfEndpoint[?options]
cxfEndpoint は、Spring Bean レジストリー内の Bean を参照する Bean ID を表します。この URI 形式では、ほとんどのエンドポイントの詳細が Bean 定義で指定されます。
cxf://someAddress[?options]
someAddress は、CXF エンドポイントのアドレスを指定します。この URI 形式では、ほとんどのエンドポイントの詳細がオプションを使用して指定されます。
上記のどちらのスタイルでも、次のように URI にオプションを追加できます。
cxf:bean:cxfEndpoint?wsdlURL=wsdl/hello_world.wsdl&dataFormat=PAYLOAD
オプション
名前 | 必須 | 説明 |
| いいえ | WSDL のロケーション。デフォルトでは、WSDL はエンドポイントアドレスから取得されます。以下に例を示します。
|
| ○ | SEI (Service Endpoint Interface) クラスの名前。このクラスには、JSR181 アノテーションを含めることができますが、必須ではありません。 2.0 以降、 このオプションは POJO モードでのみ必要です。wsdlURL オプションが指定されている場合、PAYLOAD および MESSAGE モードでは serviceClass は必要ありません。wsdlURL オプションが serviceClass なしで使用される場合、serviceName および portName (Spring 設定のエンドポイント名) オプションを指定する 必要があり ます。
2.0 以降、
非 Spring AOP プロキシーの 2.8 以降、 PAYLOAD および MESSAGE モードの wsdlURL および serviceClass オプションの両方を省略できます。それらを省略すると、任意の XML 要素を PAYLOAD モードで CxfPayload の本体に配置して、CXF ディスパッチモードを容易にすることができます。
例: |
|
WSDL に複数の |
このサービスが実装しているサービス名で、
|
|
|
このサービスが実装しているポート名で、
|
| いいえ |
CXF エンドポイントがサポートするメッセージデータ形式。可能な値は、 |
| いいえ |
このオプションについては、 |
| いいえ |
CXF エンドポイントプロデューサーが呼び出す操作の種類。設定可能な値は次のとおりです: |
| いいえ |
2.5.0 以降 パラメーターが SOAP ボディーでどのように表現されるかを記述する WSDL スタイル。値が |
| いいえ |
非推奨: このエンドポイントにデフォルトの CXF バスを使用するかどうかを指定します。設定可能な値は次のとおりです: |
| いいえ |
非推奨: このエンドポイントにデフォルトの CXF バスを使用するかどうかを指定します。設定可能な値は次のとおりです: |
| いいえ |
レジストリーからバスオブジェクトを参照するには、 デフォルトでは、CXF Bus Factory によって作成されたデフォルトバスを使用します。 |
| いいえ |
|
| いいえ |
|
| いいえ |
2.3 の新機能であるこのオプションは、インバウンドおよびアウトバウンドの SOAP メッセージをログに書き込む CXF ログ機能を有効にします。設定可能な値は次のとおりです: |
| いいえ |
2.4 の新機能であるこのオプションは、リモートサービスを呼び出す
|
| いいえ | 2.4 の新機能であるこのオプションは、リモートサービスを呼び出す CxfProducer によって使用されるデフォルトの operationNamespace を設定します。以下に例を示します。
|
| いいえ |
2.5 の新機能であるこのオプションにより、CXF エンドポイントは同期または非同期 API を使用して基礎となる作業を行うことを決定できます。デフォルト値は |
| いいえ |
2.5 の新機能であるこのオプションは、サービスアドレス URL と
|
| いいえ |
Camel 2.8: エンドポイント URI でカスタム CXF プロパティーを設定できます。たとえば、MTOM を有効にするには、 |
| いいえ | 2.8.2 の新機能。このオプションは、CXF コンポーネントが PAYLOAD モードで実行されている場合に (以下を参照してください)、着信メッセージを DOM 解析して DOM 要素にするか、場合によってはストリーミングを許可する javax.xml.transform.Source オブジェクトとしてペイロードを保持するかを制御します。 |
| いいえ | 2.11 の新機能。このオプションは、PhaseInterceptorChain がキャッチした Fault のログ記録をスキップするかどうかを制御します。 |
| いいえ |
Camel 2.11 の新機能。このオプションは、プログラムによる方法での CXF エンドポイントの設定をサポートする |
| いいえ | Camel 2.12.3 の新機能。このオプションは、CXF クライアントのユーザー名の基本認証情報を設定するために使用されます。 |
| いいえ | Camel 2.12.3 の新機能。このオプションは、CXF クライアントのパスワードの基本認証情報を設定するために使用されます。 |
| いいえ | Camel 2.14.0 の新機能。このオプションは、CXF サーバーが Jetty またはサーブレットトランスポートを使用している場合にデフォルトで CxfConsumer で使用できる CXF 継続タイムアウトを設定するために使用されます。(Camel 2.14.0 より前では、CxfConsumer は継続タイムアウトを 0 に設定するだけでした。これは、継続中断操作がタイムアウトしないことを意味します。) デフォルト:30000 例:continuation=80000 |
serviceName
と portName
は QNames であるため、これらを指定する場合は、上記の例に示すように {namespace}
を前に付けてください。
データ形式の説明
DataFormat | 説明 |
| POJO (plain old Java objects) は、ターゲットサーバーで呼び出されるメソッドへの Java パラメーターです。プロトコル JAX-WS ハンドラーと論理 JAX-WS ハンドラーの両方がサポートされています。 |
|
|
|
|
|
Camel 2.8.2 の新機能。 |
交換プロパティー CamelCXFDataFormat
を取得することで、交換のデータ形式モードを判別できます。エクスチェンジキー定数は org.apache.camel.component.cxf.CxfConstants.DATA_FORMAT_PROPERTY
で定義されています。
Apache Aries ブループリントを使用した CXF エンドポイントの設定。
Camel 2.8 以降、CXF エンドポイントに Aries ブループリント依存性注入を使用するためのサポートがあります。スキーマは Spring スキーマに非常に似ているため、移行はかなり透過的です。
以下に例を示します。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0" xmlns:camel-cxf="http://camel.apache.org/schema/blueprint/cxf" xmlns:cxfcore="http://cxf.apache.org/blueprint/core" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> <camel-cxf:cxfEndpoint id="routerEndpoint" address="http://localhost:9001/router" serviceClass="org.apache.servicemix.examples.cxf.HelloWorld"> <camel-cxf:properties> <entry key="dataFormat" value="MESSAGE"/> </camel-cxf:properties> </camel-cxf:cxfEndpoint> <camel-cxf:cxfEndpoint id="serviceEndpoint" address="http://localhost:9000/SoapContext/SoapPort" serviceClass="org.apache.servicemix.examples.cxf.HelloWorld"> </camel-cxf:cxfEndpoint> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <route> <from uri="routerEndpoint"/> <to uri="log:request"/> </route> </camelContext> </blueprint>
現在、エンドポイント要素は、サポートされている最初の CXF 名前空間ハンドラーです。
Spring と同じように Bean 参照を使用することもできます
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0" xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws" xmlns:cxf="http://cxf.apache.org/blueprint/core" xmlns:camel="http://camel.apache.org/schema/blueprint" xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf" xsi:schemaLocation=" http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd "> <camelcxf:cxfEndpoint id="reportIncident" address="/camel-example-cxf-blueprint/webservices/incident" wsdlURL="META-INF/wsdl/report_incident.wsdl" serviceClass="org.apache.camel.example.reportincident.ReportIncidentEndpoint"> </camelcxf:cxfEndpoint> <bean id="reportIncidentRoutes" class="org.apache.camel.example.reportincident.ReportIncidentRoutes" /> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <routeBuilder ref="reportIncidentRoutes"/> </camelContext> </blueprint>
MESSAGE モードで CXF の LoggingOutInterceptor を有効にする方法
CXF の LoggingOutInterceptor
は、ロギングシステム (java.util.logging
) に送信されるアウトバウンドメッセージを出力します。LoggingOutInterceptor
は PRE_STREAM
フェーズにあるため (ただし、PRE_STREAM
フェーズは MESSAGE
モードでは削除されます)、WRITE
フェーズ中に実行されるように LoggingOutInterceptor
を設定する必要があります。以下に例を示します。
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"> <!-- it really should have been user-prestream but CXF does have such phase! --> <constructor-arg value="target/write"/> </bean> <cxf:cxfEndpoint id="serviceEndpoint" address="http://localhost:9002/helloworld" serviceClass="org.apache.camel.component.cxf.HelloService"> <cxf:outInterceptors> <ref bean="loggingOutInterceptor"/> </cxf:outInterceptors> <cxf:properties> <entry key="dataFormat" value="MESSAGE"/> </cxf:properties> </cxf:cxfEndpoint>
RelayHeaders オプションの説明
JAXWS WSDL ファーストの開発者の観点から見ると、帯域内 ヘッダーと 帯域外 ヘッダーがあります。
インバンド ヘッダーは、SOAP ヘッダーなどのエンドポイントの WSDL バインディングコントラクトの一部として明示的に定義されるヘッダーです。
アウトオブバンド ヘッダーは、ネットワーク経由でシリアル化されるヘッダーですが、明示的に WSDL バインディングコントラクトの一部ではありません。
ヘッダーの中継/フィルタリングは双方向です。
ルートに CXF エンドポイントがあり、開発者が SOAP ヘッダーなどのオンザワイヤヘッダーをルートに沿ってリレーして、たとえば別の JAXWS エンドポイントで消費する必要がある場合、relayHeaders
を true
に設定する必要があります。デフォルト値。
POJO モードでのみ使用可能
relayHeaders=true
設定は、ヘッダーをリレーする意図を表します。特定のヘッダーが中継されるかどうかの実際の決定は、MessageHeadersRelay
インターフェイスを実装するプラグ可能なインスタンスに委譲されます。MessageHeadersRelay
の具体的な実装を調べて、ヘッダーを中継する必要があるかどうかを判断します。既知の SOAP 名前空間にバインドする SoapMessageHeadersRelay
の実装がすでにあります。現在、帯域外ヘッダーのみがフィルタリングされ、relayHeaders=true
の場合、帯域内ヘッダーは常に中継されます。ネームスペースがランタイムに不明なヘッダーがワイヤ上にある場合、フォールバック DefaultMessageHeadersRelay
が使用されます。これにより、すべてのヘッダーの中継が単純に許可されます。
RelayHeaders=false
設定は、帯域内および帯域外のすべてのヘッダーがドロップされることを表明します。
独自の MessageHeadersRelay
実装をプラグインして、リレーのリストをオーバーライドまたは追加することができます。プリロードされたリレーインスタンスをオーバーライドするには、MessageHeadersRelay
実装がオーバーライドしようとしている名前空間と同じ名前空間を提供していることを確認してください。また、オーバーライドするリレーは、オーバーライドしようとしているすべての名前空間にサービスを提供する必要があることに注意してください。そうしないと、インスタンスマッピングをリレーする名前空間にあいまいさが生じるため、ルートの起動時に実行時例外が出力されます。
<cxf:cxfEndpoint ...> <cxf:properties> <entry key="org.apache.camel.cxf.message.headers.relays"> <list> <ref bean="customHeadersRelay"/> </list> </entry> </cxf:properties> </cxf:cxfEndpoint> <bean id="customHeadersRelay" class="org.apache.camel.component.cxf.soap.headers.CustomHeadersRelay"/>
ここでヘッダーをリレー/ドロップする方法を示すテストを見てください。
リリース 2.0 以降の変更点
-
POJO
およびPAYLOAD
モードがサポートされています。POJO
モードでは、CXF によってインバンドヘッダーが処理され、ヘッダーリストから削除されているため、フィルタリングに使用できるのはアウトオブバンドメッセージヘッダーのみです。インバンドヘッダーは、POJO
モードでMessageContentList
に組み込まれます。camel-cxf
コンポーネントは、MessageContentList
からインバンドヘッダーを削除しようとします。インバンドヘッダーのフィルタリングが必要な場合は、PAYLOAD
モードを使用するか、(非常に簡単な) CXF インターセプター/JAXWS ハンドラーを CXF エンドポイントにプラグインしてください。 メッセージヘッダーリレーメカニズムは
CxfHeaderFilterStrategy
にマージされました。relayHeaders
オプション、そのセマンティクス、およびデフォルト値は同じままですが、CxfHeaderFilterStrategy
のプロパティーです。以下はその設定例です。<bean id="dropAllMessageHeadersStrategy" class="org.apache.camel.component.cxf.common.header.CxfHeaderFilterStrategy"> <!-- Set relayHeaders to false to drop all SOAP headers --> <property name="relayHeaders" value="false"/> </bean>
その後、エンドポイントは
CxfHeaderFilterStrategy
を参照できます。<route> <from uri="cxf:bean:routerNoRelayEndpoint?headerFilterStrategy=#dropAllMessageHeadersStrategy"/> <to uri="cxf:bean:serviceNoRelayEndpoint?headerFilterStrategy=#dropAllMessageHeadersStrategy"/> </route>
MessageHeadersRelay
インターフェイスがわずかに変更され、名前がMessageHeaderFilter
に変更されました。CxfHeaderFilterStrategy
のプロパティーです。ユーザー定義のメッセージヘッダーフィルターを設定する例を次に示します。<bean id="customMessageFilterStrategy" class="org.apache.camel.component.cxf.common.header.CxfHeaderFilterStrategy"> <property name="messageHeaderFilters"> <list> <!-- SoapMessageHeaderFilter is the built in filter. It can be removed by omitting it. --> <bean class="org.apache.camel.component.cxf.common.header.SoapMessageHeaderFilter"/> <!-- Add custom filter here --> <bean class="org.apache.camel.component.cxf.soap.headers.CustomHeaderFilter"/> </list> </property> </bean>
-
RelayHeaders
以外に、CxfHeaderFilterStrategy
で設定できる新しいプロパティーがあります。
名前 | 説明 | type | 必須 ? | デフォルト値 |
| すべてのメッセージヘッダーは、メッセージヘッダーフィルターによって処理されます。 |
| いいえ |
|
| すべてのメッセージヘッダーが伝達されます (メッセージヘッダーフィルターによる処理なし)。 |
| いいえ |
|
|
アクティベーション名前空間で 2 つのフィルターが重複する場合、プロパティーはその処理方法を制御します。値が |
| いいえ |
|
Spring で CXF エンドポイントを設定する
以下に示す Spring 設定ファイルを使用して CXF エンドポイントを設定できます。また、エンドポイントを camelContext
タグに埋め込むこともできます。サービスエンドポイントを呼び出すときに、operationName
ヘッダーと operationNamespace
ヘッダーを設定して、呼び出す操作を明示的に指定できます。
注記 Camel 2.x では、CXF エンドポイントのターゲット名前空間として http://camel.apache.org/schema/cxf
を使用するように変更します。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://camel.apache.org/schema/cxf" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> ...
Apache Camel 2.x では、http://activemq.apache.org/camel/schema/cxfEndpoint
名前空間が http://camel.apache.org/schema/cxf
に変更されました。
ルート Bean 要素で指定された JAX-WS schemaLocation
属性を必ず含めてください。これにより、CXF はファイルを検証できるようになります。これは必須です。<cxf:cxfEndpoint/>
タグの末尾にある名前空間の宣言にも注意してください。これは、結合された {namespace} localName
構文が現在、このタグの属性値に対してサポートされていないため必要です。
cxf:cxfEndpoint
要素は、多くの追加属性をサポートしています。
名前 | 値 |
|
このサービスが実装しているエンドポイント名で、 |
|
このサービスが実装しているサービス名で、 |
| WSDL のロケーション。クラスパス、ファイルシステム、またはリモートでホストできます。 |
|
使用するサービスモデルの |
| サービス公開アドレス。 |
| JAX-WS エンドポイントで使用されるバス名。 |
| JSR181 アノテーションを持つかどうかにかかわらず、SEI (Service Endpoint Interface) クラスのクラス名。 |
また、多くの子要素もサポートしています。
名前 | 値 |
|
このエンドポイントの着信インターセプター。 |
|
このエンドポイントの着信障害インターセプター。 |
|
このエンドポイントの発信インターセプター。 |
|
このエンドポイントの送信障害インターセプター。 |
| JAX-WS エンドポイントに提供する必要があるプロパティーマップ。以下を参照してください。 |
| JAX-WS エンドポイントに提供する必要がある JAX-WS ハンドラーリスト。以下を参照してください。 |
|
エンドポイントで使用する |
|
このエンドポイントが使用する |
|
このエンドポイントのインターセプターを保持する機能。 |
|
エンドポイントが使用するスキーマのロケーション。 |
|
このエンドポイントが使用するサービスファクトリー。これは、Spring |
インターセプター、プロパティー、およびハンドラーを提供する方法を示すより高度な例をここで見つけることができます: http://cwiki.apache.org/CXF20DOC/jax-ws-configuration.html
次のように、CXF:properties を使用して、Spring 設定ファイルから CXF エンドポイントの dataFormat
および setDefaultBus
プロパティーを設定できます。
<cxf:cxfEndpoint id="testEndpoint" address="http://localhost:9000/router" serviceClass="org.apache.camel.component.cxf.HelloService" endpointName="s:PortName" serviceName="s:ServiceName" xmlns:s="http://www.example.com/test"> <cxf:properties> <entry key="dataFormat" value="MESSAGE"/> <entry key="setDefaultBus" value="true"/> </cxf:properties> </cxf:cxfEndpoint>
camel-cxf コンポーネントで java.util.logging の代わりに log4j を使用する方法
CXF のデフォルトのロガーは java.util.logging
です。log4j
に変更する場合は、次の手順を実行します。クラスパスに META-INF/cxf/org.apache.cxf.logger
という名前のファイルを作成します。このファイルには、クラスの完全修飾名 org.apache.cxf.common.logging.Log4jLogger
がコメントなしで 1 行に含まれている必要があります。
xml で camel-cxf レスポンスメッセージを開始ドキュメントにする方法
PHP などの SOAP クライアントを使用している場合、CXF は XML 開始ドキュメント <?xml version="1.0" encoding="utf-8"?>
を追加しないため、この種のエラーが発生します。
Error:sendSms: SoapFault exception: [Client] looks like we got no XML document in [...]
この問題を解決するには、StaxOutInterceptor に XML 開始ドキュメントを作成するよう指示するだけです。
public class WriteXmlDeclarationInterceptor extends AbstractPhaseInterceptor<SoapMessage> { public WriteXmlDeclarationInterceptor() { super(Phase.PRE_STREAM); addBefore(StaxOutInterceptor.class.getName()); } public void handleMessage(SoapMessage message) throws Fault { message.put("org.apache.cxf.stax.force-start-document", Boolean.TRUE); } }
このようなカスタマーインターセプターを追加して、camel-cxf
エンドポイントに設定できます。
<cxf:cxfEndpoint id="routerEndpoint" address="http://localhost:${CXFTestSupport.port2}/CXFGreeterRouterTest/CamelContext/RouterPort" serviceClass="org.apache.hello_world_soap_http.GreeterImpl" skipFaultLogging="true"> <cxf:outInterceptors> <!-- This interceptor will force the CXF server send the XML start document to client --> <bean class="org.apache.camel.component.cxf.WriteXmlDeclarationInterceptor"/> </cxf:outInterceptors> <cxf:properties> <!-- Set the publishedEndpointUrl which could override the service address from generated WSDL as you want --> <entry key="publishedEndpointUrl" value="http://www.simple.com/services/test" /> </cxf:properties> </cxf:cxfEndpoint>
または、Camel 2.4 を使用している場合は、このようにメッセージヘッダーを追加します。
// set up the response context which force start document Map<String, Object> map = new HashMap<String, Object>(); map.put("org.apache.cxf.stax.force-start-document", Boolean.TRUE); exchange.getOut().setHeader(Client.RESPONSE_CONTEXT, map);
POJO データ形式の camel-cxf エンドポイントからのメッセージを使用する方法
camel-cxf
エンドポイントコンシューマー POJO
データ形式は cxf インボーカー に基づいているため、メッセージヘッダーには CxfConstants.OPERATION_NAME
という名前のプロパティーがあり、メッセージ本文は SEI メソッドパラメーターのリストです。
public class PersonProcessor implements Processor { private static final transient Logger LOG = LoggerFactory.getLogger(PersonProcessor.class); @SuppressWarnings("unchecked") public void process(Exchange exchange) throws Exception { LOG.info("processing exchange in camel"); BindingOperationInfo boi = (BindingOperationInfo)exchange.getProperty(BindingOperationInfo.class.toString()); if (boi != null) { LOG.info("boi.isUnwrapped" + boi.isUnwrapped()); } // Get the parameters list which element is the holder. MessageContentsList msgList = (MessageContentsList)exchange.getIn().getBody(); Holder<String> personId = (Holder<String>)msgList.get(0); Holder<String> ssn = (Holder<String>)msgList.get(1); Holder<String> name = (Holder<String>)msgList.get(2); if (personId.value == null || personId.value.length() == 0) { LOG.info("person id 123, so throwing exception"); // Try to throw out the soap fault message org.apache.camel.wsdl_first.types.UnknownPersonFault personFault = new org.apache.camel.wsdl_first.types.UnknownPersonFault(); personFault.setPersonId(""); org.apache.camel.wsdl_first.UnknownPersonFault fault = new org.apache.camel.wsdl_first.UnknownPersonFault("Get the null value of person name", personFault); // Since camel has its own exception handler framework, we can't throw the exception to trigger it // We just set the fault message in the exchange for camel-cxf component handling and return exchange.getOut().setFault(true); exchange.getOut().setBody(fault); return; } name.value = "Bonjour"; ssn.value = "123"; LOG.info("setting Bonjour as the response"); // Set the response message, first element is the return value of the operation, // the others are the holders of method parameters exchange.getOut().setBody(new Object[] {null, personId, ssn, name}); } }
POJO データ形式で camel-cxf エンドポイントのメッセージを準備する方法
camel-cxf
エンドポイントプロデューサーは、cxf client API に基づいています。まず、メッセージヘッダーでオペレーション名を指定し、次にメソッドパラメーターをリストに追加し、このパラメーターリストでメッセージを初期化する必要があります。レスポンスメッセージボディーは messageContentsList
であり、そのリストから結果を取得できます。
メッセージヘッダーで操作名を指定しない場合、CxfProducer
は CxfEndpoint
の defaultOperationName
を使用しようとします。CxfEndpoint
に defaultOperationName
が設定されていない場合、操作リストから最初の操作名が取得されます。
メッセージボディーからオブジェクト配列を取得する場合は、次のように message.getbody (Object.class)
を使用してボディーを取得できます。
Exchange senderExchange = new DefaultExchange(context, ExchangePattern.InOut); final List<String> params = new ArrayList<String>(); // Prepare the request message for the camel-cxf procedure params.add(TEST_MESSAGE); senderExchange.getIn().setBody(params); senderExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, ECHO_OPERATION); Exchange exchange = template.send("direct:EndpointA", senderExchange); org.apache.camel.Message out = exchange.getOut(); // The response message's body is an MessageContentsList which first element is the return value of the operation, // If there are some holder parameters, the holder parameter will be filled in the reset of List. // The result will be extract from the MessageContentsList with the String class type MessageContentsList result = (MessageContentsList)out.getBody(); LOG.info("Received output text: " + result.get(0)); Map<String, Object> responseContext = CastUtils.cast((Map<?, ?>)out.getHeader(Client.RESPONSE_CONTEXT)); assertNotNull(responseContext); assertEquals("We should get the response context here", "UTF-8", responseContext.get(org.apache.cxf.message.Message.ENCODING)); assertEquals("Reply body on Camel is wrong", "echo " + TEST_MESSAGE, result.get(0));
PAYLOAD データ形式の camel-cxf エンドポイントのメッセージを処理する方法
Apache Camel 2.0 の場合: CxfMessage.getBody()
は、org.apache.camel.component.cxf.CxfPayload
オブジェクトを返します。このオブジェクトには、SOAP メッセージヘッダーと Body 要素の getter があります。この変更により、ネイティブ CXF メッセージを Apache Camel メッセージから切り離すことができます。
protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { public void configure() { from(SIMPLE_ENDPOINT_URI + "&dataFormat=PAYLOAD").to("log:info").process(new Processor() { @SuppressWarnings("unchecked") public void process(final Exchange exchange) throws Exception { CxfPayload<SoapHeader> requestPayload = exchange.getIn().getBody(CxfPayload.class); List<Source> inElements = requestPayload.getBodySources(); List<Source> outElements = new ArrayList<Source>(); // You can use a customer toStringConverter to turn a CxfPayLoad message into String as you want String request = exchange.getIn().getBody(String.class); XmlConverter converter = new XmlConverter(); String documentString = ECHO_RESPONSE; Element in = new XmlConverter().toDOMElement(inElements.get(0)); // Just check the element namespace if (!in.getNamespaceURI().equals(ELEMENT_NAMESPACE)) { throw new IllegalArgumentException("Wrong element namespace"); } if (in.getLocalName().equals("echoBoolean")) { documentString = ECHO_BOOLEAN_RESPONSE; checkRequest("ECHO_BOOLEAN_REQUEST", request); } else { documentString = ECHO_RESPONSE; checkRequest("ECHO_REQUEST", request); } Document outDocument = converter.toDOMDocument(documentString); outElements.add(new DOMSource(outDocument.getDocumentElement())); // set the payload header with null CxfPayload<SoapHeader> responsePayload = new CxfPayload<SoapHeader>(null, outElements, null); exchange.getOut().setBody(responsePayload); } }); } }; }
POJO モードで SOAP ヘッダーを取得および設定する方法
POJO
は、camel-cxf エンドポイントが Camel エクスチェンジを生成または消費するときのデータ形式が Java オブジェクトのリスト であることを意味します。Apache Camel はこのモードでメッセージボディーを POJO として公開しますが、CXF コンポーネントは引き続き SOAP ヘッダーの読み取りと書き込みへのアクセスを提供します。ただし、CXF インターセプターはインバンド SOAP ヘッダーを処理後にヘッダーリストから削除するため、POJO モードではアウトオブバンド SOAP ヘッダーのみを使用できます。
次の例は、SOAP ヘッダーを取得/設定する方法を示しています。ある CXF エンドポイントから別のエンドポイントに転送するルートがあるとします。つまり、SOAP クライアント
<route> <from uri="cxf:bean:routerRelayEndpointWithInsertion"/> <process ref="InsertRequestOutHeaderProcessor" /> <to uri="cxf:bean:serviceRelayEndpointWithInsertion"/> <process ref="InsertResponseOutHeaderProcessor" /> </route>
2.x では、SOAP ヘッダーは Apache Camel Message ヘッダーとの間で伝播されます。Apache Camel メッセージヘッダー名は、CXF (org.apache.cxf.headers.Header.HEADER_LIST
) で定義されている定数である org.apache.cxf.headers.Header.list
です。ヘッダー値は、CXF SoapHeader
オブジェクト (org.apache.cxf.binding.soap.SoapHeader
) の List<>
です。次のスニペットは、InsertResponseOutHeaderProcessor
(応答メッセージに新しい SOAP ヘッダーを挿入する) です。InsertResponseOutHeaderProcessor
と InsertRequestOutHeaderProcessor
の両方で SOAP ヘッダーにアクセスする方法は、実際には同じです。2 つのプロセッサーの唯一の違いは、挿入される SOAP ヘッダーの方向を設定することです。
public static class InsertResponseOutHeaderProcessor implements Processor { @SuppressWarnings("unchecked") public void process(Exchange exchange) throws Exception { // You should be able to get the header if exchange is routed from camel-cxf endpoint List<SoapHeader> soapHeaders = CastUtils.cast((List<?>)exchange.getIn().getHeader(Header.HEADER_LIST)); if (soapHeaders == null) { // we just create a new soap headers in case the header is null soapHeaders = new ArrayList<SoapHeader>(); } // Insert a new header String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><outofbandHeader " + "xmlns=\"http://cxf.apache.org/outofband/Header\" hdrAttribute=\"testHdrAttribute\" " + "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" soap:mustUnderstand=\"1\">" + "<name>New_testOobHeader</name><value>New_testOobHeaderValue</value></outofbandHeader>"; SoapHeader newHeader = new SoapHeader(soapHeaders.get(0).getName(), DOMUtils.readXml(new StringReader(xml)).getDocumentElement()); // make sure direction is OUT since it is a response message. newHeader.setDirection(Direction.DIRECTION_OUT); //newHeader.setMustUnderstand(false); soapHeaders.add(newHeader); } }
PAYLOAD モードで SOAP ヘッダーを取得および設定する方法
PAYLOAD
モードで SOAP メッセージ (CxfPayload
オブジェクト) にアクセスする方法はすでに示しました (「PAYLOAD データ形式の camel-cxf エンドポイントのメッセージを処理する方法」)。
CxfPayload
オブジェクトを取得したら、DOM 要素 (SOAP ヘッダー) の List
を返す CxfPayload.getHeaders()
メソッドを呼び出すことができます。
from(getRouterEndpointURI()).process(new Processor() { @SuppressWarnings("unchecked") public void process(Exchange exchange) throws Exception { CxfPayload<SoapHeader> payload = exchange.getIn().getBody(CxfPayload.class); List<Source> elements = payload.getBodySources(); assertNotNull("We should get the elements here", elements); assertEquals("Get the wrong elements size", 1, elements.size()); Element el = new XmlConverter().toDOMElement(elements.get(0)); elements.set(0, new DOMSource(el)); assertEquals("Get the wrong namespace URI", "http://camel.apache.org/pizza/types", el.getNamespaceURI()); List<SoapHeader> headers = payload.getHeaders(); assertNotNull("We should get the headers here", headers); assertEquals("Get the wrong headers size", headers.size(), 1); assertEquals("Get the wrong namespace URI", ((Element)(headers.get(0).getObject())).getNamespaceURI(), "http://camel.apache.org/pizza/types"); } }) .to(getServiceEndpointURI());
Camel 2.16.0 以降では、「POJO モードで SOAP ヘッダーを取得および設定する方法」 で説明したのと同じ方法でSOAPヘッダを設定または取得することが可能です。org.apache.cxf.headers.Header.list
ヘッダーを使用して、SOAP ヘッダーのリストを取得および設定できるようになりました。これは、ある Camel CXF エンドポイントから別のエンドポイント (SOAP クライアント org.apache.cxf.headers.Header.list
Camel ヘッダーからヘッダーを削除します。
SOAP ヘッダーは MESSAGE モードでは使用できません
SOAP 処理がスキップされるため、SOAP ヘッダーは MESSAGE
モードでは使用できません。
Apache Camel から SOAP 障害を出力する方法
CXF エンドポイントを使用して SOAP リクエストを使用している場合は、camel コンテキストから SOAP Fault
を出力する必要がある場合があります。基本的に、これを行うには throwFault
DSL を使用できます。POJO
、PAYLOAD
、および MESSAGE
データ形式で機能します。SOAP 障害は次のように定義できます。
SOAP_FAULT = new SoapFault(EXCEPTION_MESSAGE, SoapFault.FAULT_CODE_CLIENT); Element detail = SOAP_FAULT.getOrCreateDetail(); Document doc = detail.getOwnerDocument(); Text tn = doc.createTextNode(DETAIL_TEXT); detail.appendChild(tn);
あとは好きなように投げてください
from(routerEndpointURI).setFaultBody(constant(SOAP_FAULT));
CXF エンドポイントが MESSAGE
データ形式で動作している場合、メッセージボディーに SOAP 障害メッセージを設定し、メッセージヘッダーにレスポンスコードを設定できます。
from(routerEndpointURI).process(new Processor() { public void process(Exchange exchange) throws Exception { Message out = exchange.getOut(); // Set the message body with the out.setBody(this.getClass().getResourceAsStream("SoapFaultMessage.xml")); // Set the response code here out.setHeader(org.apache.cxf.message.Message.RESPONSE_CODE, new Integer(500)); } });
同じことが POJO データ形式にも当てはまります。次のように、Out 本文に SOAP 障害を設定し、Message.setFault (true)
を呼び出すことでそれがエラーであることを示すこともできます。
from("direct:start").onException(SoapFault.class).maximumRedeliveries(0).handled(true) .process(new Processor() { public void process(Exchange exchange) throws Exception { SoapFault fault = exchange .getProperty(Exchange.EXCEPTION_CAUGHT, SoapFault.class); exchange.getOut().setFault(true); exchange.getOut().setBody(fault); } }).end().to(serviceURI);
CXF エンドポイントのリクエストとレスポンスのコンテキストを伝播する方法
cxf client API は、要求と応答のコンテキストで操作を呼び出す方法を提供します。CXF エンドポイントプロデューサーを使用して外部 Web サービスを呼び出す場合は、次のコードを使用して、リクエストコンテキストを設定し、レスポンスコンテキストを取得できます。
CxfExchange exchange = (CxfExchange)template.send(getJaxwsEndpointUri(), new Processor() { public void process(final Exchange exchange) { final List<String> params = new ArrayList<String>(); params.add(TEST_MESSAGE); // Set the request context to the inMessage Map<String, Object> requestContext = new HashMap<String, Object>(); requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, JAXWS_SERVER_ADDRESS); exchange.getIn().setBody(params); exchange.getIn().setHeader(Client.REQUEST_CONTEXT , requestContext); exchange.getIn().setHeader(CxfConstants.OPERATION_NAME, GREET_ME_OPERATION); } }); org.apache.camel.Message out = exchange.getOut(); // The output is an object array, the first element of the array is the return value Object\[\] output = out.getBody(Object\[\].class); LOG.info("Received output text: " + output\[0\]); // Get the response context form outMessage Map<String, Object> responseContext = CastUtils.cast((Map)out.getHeader(Client.RESPONSE_CONTEXT)); assertNotNull(responseContext); assertEquals("Get the wrong wsdl opertion name", "{http://apache.org/hello_world_soap_http}greetMe", responseContext.get("javax.xml.ws.wsdl.operation").toString());
アタッチメントサポート
POJO モード: SOAP with Attachment と MTOM の両方がサポートされています (MTOM を有効にするためのペイロードモードの例を参照してください)。 ただし、SOAP with Attachment はテストされていません。 添付は POJO にマーシャリングおよびアンマーシャリングされるため、通常、ユーザーは添付自体を処理する必要はありません。 2.1 以降、添付は Camel メッセージの添付に伝播されます。 そのため、Camel Message API で添付を取得することができます。
DataHandler Message.getAttachment(String id)
をクリックします。
ペイロードモード: MTOM は 2.1 以降でサポートされています。添付は、上記の Camel Message API によって取得できます。アタッチメント付きの SOAP は、このモードでは SOAP 処理がないため、サポートされていません。
MTOM を有効にするには、CXF エンドポイントプロパティー mtom_enabled を true に設定します。(Spring でしかできません。)
<cxf:cxfEndpoint id="routerEndpoint" address="http://localhost:${CXFTestSupport.port1}/CxfMtomRouterPayloadModeTest/jaxws-mtom/hello" wsdlURL="mtom.wsdl" serviceName="ns:HelloService" endpointName="ns:HelloPort" xmlns:ns="http://apache.org/camel/cxf/mtom_feature"> <cxf:properties> <!-- enable mtom by setting this property to true --> <entry key="mtom-enabled" value="true"/> <!-- set the camel-cxf endpoint data fromat to PAYLOAD mode --> <entry key="dataFormat" value="PAYLOAD"/> </cxf:properties>
ペイロードモードで CXF エンドポイントに送信する添付付きの Camel メッセージを生成できます。
Exchange exchange = context.createProducerTemplate().send("direct:testEndpoint", new Processor() { public void process(Exchange exchange) throws Exception { exchange.setPattern(ExchangePattern.InOut); List<Source> elements = new ArrayList<Source>(); elements.add(new DOMSource(DOMUtils.readXml(new StringReader(MtomTestHelper.REQ_MESSAGE)).getDocumentElement())); CxfPayload<SoapHeader> body = new CxfPayload<SoapHeader>(new ArrayList<SoapHeader>(), elements, null); exchange.getIn().setBody(body); exchange.getIn().addAttachment(MtomTestHelper.REQ_PHOTO_CID, new DataHandler(new ByteArrayDataSource(MtomTestHelper.REQ_PHOTO_DATA, "application/octet-stream"))); exchange.getIn().addAttachment(MtomTestHelper.REQ_IMAGE_CID, new DataHandler(new ByteArrayDataSource(MtomTestHelper.requestJpeg, "image/jpeg"))); } }); // process response CxfPayload<SoapHeader> out = exchange.getOut().getBody(CxfPayload.class); Assert.assertEquals(1, out.getBody().size()); Map<String, String> ns = new HashMap<String, String>(); ns.put("ns", MtomTestHelper.SERVICE_TYPES_NS); ns.put("xop", MtomTestHelper.XOP_NS); XPathUtils xu = new XPathUtils(ns); Element oute = new XmlConverter().toDOMElement(out.getBody().get(0)); Element ele = (Element)xu.getValue("//ns:DetailResponse/ns:photo/xop:Include", oute, XPathConstants.NODE); String photoId = ele.getAttribute("href").substring(4); // skip "cid:" ele = (Element)xu.getValue("//ns:DetailResponse/ns:image/xop:Include", oute, XPathConstants.NODE); String imageId = ele.getAttribute("href").substring(4); // skip "cid:" DataHandler dr = exchange.getOut().getAttachment(photoId); Assert.assertEquals("application/octet-stream", dr.getContentType()); MtomTestHelper.assertEquals(MtomTestHelper.RESP_PHOTO_DATA, IOUtils.readBytesFromStream(dr.getInputStream())); dr = exchange.getOut().getAttachment(imageId); Assert.assertEquals("image/jpeg", dr.getContentType()); BufferedImage image = ImageIO.read(dr.getInputStream()); Assert.assertEquals(560, image.getWidth()); Assert.assertEquals(300, image.getHeight());
ペイロードモードで CXF エンドポイントから受信した Camel メッセージを使用することもできます。
public static class MyProcessor implements Processor { @SuppressWarnings("unchecked") public void process(Exchange exchange) throws Exception { CxfPayload<SoapHeader> in = exchange.getIn().getBody(CxfPayload.class); // verify request assertEquals(1, in.getBody().size()); Map<String, String> ns = new HashMap<String, String>(); ns.put("ns", MtomTestHelper.SERVICE_TYPES_NS); ns.put("xop", MtomTestHelper.XOP_NS); XPathUtils xu = new XPathUtils(ns); Element body = new XmlConverter().toDOMElement(in.getBody().get(0)); Element ele = (Element)xu.getValue("//ns:Detail/ns:photo/xop:Include", body, XPathConstants.NODE); String photoId = ele.getAttribute("href").substring(4); // skip "cid:" assertEquals(MtomTestHelper.REQ_PHOTO_CID, photoId); ele = (Element)xu.getValue("//ns:Detail/ns:image/xop:Include", body, XPathConstants.NODE); String imageId = ele.getAttribute("href").substring(4); // skip "cid:" assertEquals(MtomTestHelper.REQ_IMAGE_CID, imageId); DataHandler dr = exchange.getIn().getAttachment(photoId); assertEquals("application/octet-stream", dr.getContentType()); MtomTestHelper.assertEquals(MtomTestHelper.REQ_PHOTO_DATA, IOUtils.readBytesFromStream(dr.getInputStream())); dr = exchange.getIn().getAttachment(imageId); assertEquals("image/jpeg", dr.getContentType()); MtomTestHelper.assertEquals(MtomTestHelper.requestJpeg, IOUtils.readBytesFromStream(dr.getInputStream())); // create response List<Source> elements = new ArrayList<Source>(); elements.add(new DOMSource(DOMUtils.readXml(new StringReader(MtomTestHelper.RESP_MESSAGE)).getDocumentElement())); CxfPayload<SoapHeader> sbody = new CxfPayload<SoapHeader>(new ArrayList<SoapHeader>(), elements, null); exchange.getOut().setBody(sbody); exchange.getOut().addAttachment(MtomTestHelper.RESP_PHOTO_CID, new DataHandler(new ByteArrayDataSource(MtomTestHelper.RESP_PHOTO_DATA, "application/octet-stream"))); exchange.getOut().addAttachment(MtomTestHelper.RESP_IMAGE_CID, new DataHandler(new ByteArrayDataSource(MtomTestHelper.responseJpeg, "image/jpeg"))); } }
メッセージモード: メッセージをまったく処理しないため、添付はサポートされていません。
CXF_MESSAGE モード: MTOM がサポートされ、添付は上記の Camel Message API によって取得できます。マルチパート (つまり MTOM) メッセージを受信する場合、デフォルトの SOAPMessage
から String
へのコンバーターは、本文で完全なマルチパートペイロードを提供することに注意してください。String
として SOAP XML だけが必要な場合は、message.getSOAPPart()
でメッセージボディーを設定でき、Camel convert が残りの作業を実行できます。
スタックトレース情報を伝播させる方法
Java の例外がサーバー側で発生したときに、例外のスタックトレースがフォールトメッセージにマーシャリングされてクライアントに返されるように、CXF エンドポイントを設定することができます。この機能を有効にするには、以下のように cxfEndpoint
要素で、dataFormat
を PAYLOAD
に設定し、faultStackTraceEnabled
プロパティーを true
に設定します。
<cxf:cxfEndpoint id="router" address="http://localhost:9002/TestMessage"
wsdlURL="ship.wsdl"
endpointName="s:TestSoapEndpoint"
serviceName="s:TestService"
xmlns:s="http://test">
<cxf:properties>
<!-- enable sending the stack trace back to client; the default value is false-->
<entry key="faultStackTraceEnabled" value="true" /> <entry key="dataFormat" value="PAYLOAD" />
</cxf:properties>
</cxf:cxfEndpoint>
セキュリティー上の理由から、スタックトレースには原因となる例外 (つまりスタックトレースの Caused by
以降の部分) は含まれません。スタックトレースに原因となる例外を含めたい場合は、以下のように cxfEndpoint
要素の exceptionMessageCauseEnabled
プロパティーを true
に設定します。
<cxf:cxfEndpoint id="router" address="http://localhost:9002/TestMessage"
wsdlURL="ship.wsdl"
endpointName="s:TestSoapEndpoint"
serviceName="s:TestService"
xmlns:s="http://test">
<cxf:properties>
<!-- enable to show the cause exception message and the default value is false -->
<entry key="exceptionMessageCauseEnabled" value="true" />
<!-- enable to send the stack trace back to client, the default value is false-->
<entry key="faultStackTraceEnabled" value="true" />
<entry key="dataFormat" value="PAYLOAD" />
</cxf:properties>
</cxf:cxfEndpoint>
exceptionMessageCauseEnabled
フラグは、テストおよび診断目的でのみ有効にしてください。サーバーにおいて例外の元の原因を隠すことで、敵対的なユーザーがサーバーを調査しにくくするのが、通常の実践的なやり方です。
PAYLOAD モードでのストリーミングのサポート
2.8.2 では、camel-cxf コンポーネントは、PAYLOAD モードの使用時に受信メッセージのストリーミングをサポートするようになりました。以前は、着信メッセージは完全に DOM 解析されていました。大きなメッセージの場合、これには時間がかかり、大量のメモリーが使用されます。2.8.2 以降、着信メッセージは、ルーティング中に javax.xml.transform.Source のままにすることができ、何もペイロードを変更しない場合は、ターゲットの宛先に直接ストリーミングできます。一般的な単純なプロキシーの使用例 (例: from ("cxf:…").to ("cxf:…")) では、これによりパフォーマンスが大幅に向上するだけでなく、メモリー要件が大幅に削減されます。
ただし、ストリーミングが適切でない、または望ましくない場合があります。ストリーミングの性質上、無効な着信 XML は、処理チェーンの後半までキャッチされない場合があります。また、特定のアクションでは、とにかくメッセージを DOM 解析する必要がある場合があります (WS-Security やメッセージトレースなど)。この場合、ストリーミングの利点は制限されます。この時点で、ストリーミングを制御する方法は 2 つあります。
- エンドポイントプロパティー: "allowStreaming=false" をエンドポイントプロパティーとして追加して、ストリーミングのオン/オフを切り替えることができます。
- Component プロパティー: CxfComponent オブジェクトには、そのコンポーネントから作成されたエンドポイントのデフォルトを設定できる allowStreaming プロパティーもあります。
- グローバルシステムプロパティー: org.apache.camel.component.cxf.streaming のシステムプロパティーを false に追加してオフにすることができます。これによりグローバルなデフォルトが設定されますが、上記のエンドポイントプロパティーを設定すると、そのエンドポイントのこの値がオーバーライドされます。
一般的な CXF ディスパッチモードの使用
2.8.0 から、camel-cxf コンポーネントは、任意の構造 (つまり、特定の XML スキーマにバインドされていない) のメッセージを転送できるジェネリック CXF ディスパッチモード をサポートしています。このモードを使用するには、CXF エンドポイントの wsdlURL および serviceClass 属性の指定を省略します。
<cxf:cxfEndpoint id="testEndpoint" address="http://localhost:9000/SoapContext/SoapAnyPort"> <cxf:properties> <entry key="dataFormat" value="PAYLOAD"/> </cxf:properties> </cxf:cxfEndpoint>
デフォルトの CXF ディスパッチクライアントは、特定の SOAPAction ヘッダーを送信しないことに注意してください。したがって、ターゲットサービスが特定の SOAPAction 値を必要とする場合、キー SOAPAction (大文字と小文字を区別しない) を使用して Camel ヘッダーで提供されます。
75.1. {wildfly} の CXF コンシューマー
{wildfly} の camel-cxf コンシューマーの設定は、スタンドアロンの Camel の設定とは異なります。プロデューサーエンドポイントは通常どおりに機能します。
{wildfly} では、camel-cxf コンシューマーは、コンテナーによって提供されるデフォルトの Undertow HTTP サーバーを利用します。サーバーは undertow サブシステム設定内で定義されます。以下は、standalone.xml からのデフォルト設定の抜粋です。
<subsystem xmlns="urn:jboss:domain:undertow:4.0"> <buffer-cache name="default" /> <server name="default-server"> <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true" /> <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true" /> <host name="default-host" alias="localhost"> <location name="/" handler="welcome-content" /> <filter-ref name="server-header" /> <filter-ref name="x-powered-by-header" /> <http-invoker security-realm="ApplicationRealm" /> </host> </server> </subsystem>
この例では、Undertow は、http および https ソケットバインディングで指定されたインターフェイス/ポートをリッスンするように設定されています。デフォルトでは、これは http の場合はポート 8080、https の場合は 8443 です。
たとえば、異なるホストまたはポートの組み合わせを使用してエンドポイントコンシューマーを設定すると、サーバーログファイル内に警告が表示されます。たとえば、次のホストとポートの設定は無視されます。
<cxf:rsServer id="cxfRsConsumer" address="http://somehost:1234/path/to/resource" serviceClass="org.example.ServiceClass" />
<cxf:cxfEndpoint id="cxfWsConsumer" address="http://somehost:1234/path/to/resource" serviceClass="org.example.ServiceClass" />
[org.wildfly.extension.camel] (pool-2-thread-1) Ignoring configured host: http://somehost:1234/path/to/resource
ただし、コンシューマーはデフォルトのホストとポート localhost:8080 または localhost:8443 で引き続き利用できます。
camel-cxf コンシューマーを使用するアプリケーションは、WAR としてパッケージ化する 必要があります。以前の {wildfly-camel} リリースでは、JAR などの他のタイプのアーカイブが許可されていましたが、これはサポートされなくなりました。
75.1.1. 代替ポートの設定
代替ポートを受け入れる場合は、{wildfly} サブシステム設定を介してこれらを設定する必要があります。これは、サーバーのドキュメントで説明されています。
75.1.2. SSL の設定
SSL を設定するには、{wildfly} SSL 設定ガイドを参照してください。
75.1.3. Elytron を使用したセキュリティーの設定
{wildfly-camel} は、Elytron セキュリティーフレームワークを使用して camel-cxf コンシューマーエンドポイントを保護することをサポートしています。
75.1.3.1. セキュリティードメインの設定
Elytron を使用して {wildfly-camel} アプリケーションを保護するには、WAR デプロイメントの WEB-INF/jboss-web.xml
内でアプリケーションセキュリティードメインを参照する必要があります。
<jboss-web> <security-domain>my-application-security-domain</security-domain> </jboss-web>
<security-domain>
設定は、Undertow サブシステムによって定義された <application-security-domain>
の名前を参照します。たとえば、Undertow サブシステム <application-security-domain>
は、{wildfly} サーバーの standalone.xml
設定ファイル内で次のように設定されます。
<subsystem xmlns="urn:jboss:domain:undertow:6.0"> ... <application-security-domains> <application-security-domain name="my-application-security-domain" http-authentication-factory="application-http-authentication"/> </application-security-domains> </subsystem>
<http-authentication-factory>
application-http-authentication
は、Elytron サブシステム内で定義されています。application-http-authentication
は、デフォルトで、standalone.xml
および standalone-full.xml
サーバー設定ファイルの両方で使用できます。以下に例を示します。
<subsystem xmlns="urn:wildfly:elytron:1.2"> ... <http> ... <http-authentication-factory name="application-http-authentication" http-server-mechanism-factory="global" security-domain="ApplicationDomain"> <mechanism-configuration> <mechanism mechanism-name="BASIC"> <mechanism-realm realm-name="Application Realm" /> </mechanism> <mechanism mechanism-name="FORM" /> </mechanism-configuration> </http-authentication-factory> <provider-http-server-mechanism-factory name="global" /> </http> ... </subsystem>
application-http-authentication
という名前の <http-authentication-factory>
は、ApplicationDomain
と呼ばれる Elytron セキュリティードメインへの参照を保持します。
Elytron サブシステムの設定方法について詳しくは、Elytron のドキュメント を参照してください。
75.1.3.2. セキュリティー制約、認証方法、およびセキュリティーロールの設定
camel-cxf コンシューマーエンドポイントのセキュリティー制約、認証方法、およびセキュリティーロールは、WAR デプロイメント WEB-INF/web.xml
内で設定できます。たとえば、BASIC 認証を設定するには、次のようにします。
<web-app> <security-constraint> <web-resource-collection> <web-resource-name>secure</web-resource-name> <url-pattern>/webservices/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>my-role</role-name> </auth-constraint> </security-constraint> <security-role> <description>The role that is required to log in to /webservices/*</description> <role-name>my-role</role-name> </security-role> <login-config> <auth-method>BASIC</auth-method> <realm-name>my-realm</realm-name> </login-config> </web-app>
サーブレット仕様で定義されている <url-pattern>
は、Web アプリケーションのコンテキストパスに対して相対的であることに注意してください。アプリケーションが my-app.war
としてパッケージ化されている場合、{wildfly} はコンテキストパス /my-app
でアクセスできるようにし、<url-patternpattern>
/webservices/*
が /my-app
への相対パスに適用されます。
たとえば、http://my-server/my-app/webservices/my-endpoint
に対するリクエストは /webservices/*
パターンに一致しますが、http://my-server/webservices/my-endpoint
は一致しません。
{wildfly-camel} では、ベースパスがホスト Web アプリケーションコンテキストパスの外部にある camel-cxf エンドポイントコンシューマーを作成できるため、これは重要です。たとえば、my-app.war
内に http://my-server/webservices/my-endpoint
の camel-cxf コンシューマーを作成することができます。
このようなアウトオブコンテキストエンドポイントのセキュリティー制約を定義するために、{wildfly-camel} はカスタム の非標準の<url-pattern>
規則をサポートします。この規則では、パターンの前に 3 つのスラッシュ ///
を付けると、サーバーホスト名への絶対パスとして解釈されます。たとえば、http://my-server/webservices/my-endpoint
を my-app.war
内でセキュリティー保護するには、次の設定を web.xml
に追加します。
<web-app> <security-constraint> <web-resource-collection> <web-resource-name>secure</web-resource-name> <url-pattern>///webservices/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>my-role</role-name> </auth-constraint> </security-constraint> <security-role> <description>The role that is required to log in to /webservices/*</description> <role-name>my-role</role-name> </security-role> <login-config> <auth-method>BASIC</auth-method> <realm-name>my-realm</realm-name> </login-config> </web-app>