検索

第75章 CXF

download PDF

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 webservices の susbsystem と統合します。詳細は「 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

オプション

Name

必須

説明

wsdlURL

非対応

WSDL の場所。WSDL はデフォルトでエンドポイントアドレスから取得されます。以下に例を示します。

file://local/wsdl/hello.wsdl or wsdl/hello.wsdl

serviceClass

対応

SEI(Service Endpoint Interface)クラスの名前。このクラスは JSR181 アノテーションを持つことができますが、必須ではありません。  2.0 以降、このオプションは POJO モードでのみ必要です。wsdlURL オプションを指定する場合、serviceClass は PAYLOAD モードおよび MESSAGE モードでは必要ありません。serviceClass なしで wsdlURL オプションを使用すると、serviceName オプションおよび portName オプション(Spring 設定の endpointName)オプションを指定する 必要 があります。

2.0 以降、\# 表記を使用してレジストリーから serviceClass オブジェクトインスタンスを参照できます。

参照されるオブジェクトは、Spring AOP 以外のプロキシーの Object.getClass().getName ()メソッドに依存するため、プロキシー(Spring AOP プロキシーは OK) にすることはできません。

2.8 以降、 PAYLOAD モードおよび MESSAGE モード の wsdlURL および serviceClass オプションの両方を省略することができます。省略すると、CXF の Dispatch Mode を容易にするために、任意の XML 要素を PAYLOAD モードの CxfPayload ボディーに配置できます。

例: org.apache.camel.Hello

serviceName

WSDL に複数の serviceName が存在する場合にのみ

このサービスは実装されているサービス名で、wsdl:service@name にマップされます。以下に例を示します。

{http://org.apache.camel}ServiceName

endpointName

serviceName の下に複数の portName が存在し、camel 2.2 以降 camel-cxf コンシューマーに必要です。

このサービスが実装しているポート名。wsdl:port@name にマッピングします。以下に例を示します。

{http://org.apache.camel}PortName

dataFormat

非対応

CXF エンドポイントがサポートするメッセージデータフォーマット。使用できる値は POJO (デフォルト)PAYLOADMESSAGE です。

relayHeaders

非対応

このオプション relayHeadersオプション の説明セクションを参照してください。CXF エンドポイントがルートを通過する必要があります。現在、dataFormat= POJODefault:trueExample:true,falseの場合にのみ利用できます。

wrapped

非対応

CXF エンドポイントプロデューサーが呼び出す操作の種類。使用できる値は truefalse (デフォルト) です。

wrappedStyle

非対応

2.5.0 以降、SOAP ボディーでパラメーターを表す方法を記述する WSDL スタイル。値が false の場合、CXF は document-literal unwraped スタイルを選択します。値が true の場合、CXF は document-literal ラップされたスタイルを選択します。

setDefaultBus

非対応

deprecated: このエンドポイントにデフォルトの CXF バスを使用するかどうかを指定します。使用できる値は truefalse (デフォルト) です。このオプションは非推奨になっており、Camel 2.16 以降では defaultBus を使用する必要があります。

defaultBus

非対応

deprecated: このエンドポイントにデフォルトの CXF バスを使用するかどうかを指定します。使用できる値は truefalse (デフォルト) です。このオプションは非推奨になっており、Camel 2.16 以降では defaultBus を使用する必要があります。

bus

非対応

\# 表記を使用して、レジストリー(例: bus=\#busName )からバスオブジェクトを参照します。参照オブジェクトは org.apache.cxf.Bus のインスタンスである必要があります。

デフォルトでは、CXF Bus Factory によって作成されたデフォルトのバスを使用します。

cxfBinding

非対応

\# 表記を使用して、レジストリーで CXF バインディングオブジェクトを参照します(例: cxfBinding=\#bindingName )。参照されるオブジェクトは org.apache.camel.component.cxf.CxfBinding のインスタンスである必要があります。

headerFilterStrategy

非対応

\# 表記を使用して、レジストリーでヘッダーフィルターストラテジーオブジェクトを参照します(例: headerFilterStrategy=\#strategyName )。参照オブジェクトは org.apache.camel.spi.HeaderFilterStrategy のインスタンスである必要があります。

loggingFeatureEnabled

非対応

2.3 の新機能。このオプションは、インバウンドおよびアウトバウンド SOAP メッセージをログに書き込む CXF ロギング機能を有効にします。使用できる値は truefalse (デフォルト) です。

defaultOperationName

非対応

2.4 の新機能として、このオプションはリモートサービスを呼び出す CxfProducer によって使用されるデフォルトの operationName を設定します。以下に例を示します。

defaultOperationName=greetMe

defaultOperationNamespace

非対応

2.4 の新機能として、このオプションはリモートサービスを呼び出す CxfProducer によって使用されるデフォルトの operationNamespace を設定します。以下に例を示します。

defaultOperationNamespace=http://apache.org/hello_world_soap_http

同期

非対応

2.5 の新機能、このオプションを使用すると、CXF エンドポイントが sync または async API を使用して基礎となる作業を行うことを決定できるようになりました。デフォルト値は false です。つまり、camel-cxf エンドポイントはデフォルトで async API の使用を試行します。

publishedEndpointUrl

非対応

2.5 の新機能として、このオプションはサービスアドレス URL と ?wsdl を使用してアクセスされる公開された WSDL に表示されるエンドポイント URL を上書きします。以下に例を示します。

publshedEndpointUrl=http://example.com/service

properties.propName

非対応

Camel 2.8: エンドポイント URI にカスタム CXF プロパティーを設定できます。たとえば、properties.mtom-enabled=true を設定して MTOM を有効にします。呼び出しの開始時に CXF がスレッドを切り替えないようにするには、properties.org.apache.cxf.interceptor.OneWayProcessorInterceptor.USE_ORIGINAL_THREAD=true を設定します。

allowStreaming

非対応

2.8.2 の新機能このオプションは、PAYLOAD モードで実行されている場合に CXF コンポーネントを制御します(以下を参照)、受信メッセージを DOM 要素に解析するか、ペイロードを一部のケースでストリーミングできる javax.xml.transform.Source オブジェクトとして解析するかを制御します。

skipFaultLogging

非対応

2.11 の新機能。このオプションは、PhaseInterceptorChain がキャッチするフォールトのロギングをスキップするかどうかを制御します。

cxfEndpointConfigurer

非対応

Camel 2.11 の新機能。このオプションは、プログラムによる CXF エンドポイントの設定をサポートする org.apache.camel.component.cxf.CxfEndpointConfigurer の実装を適用する可能性があります。Camel 2.15.0 以降、 ユーザーは configure{Server を実装して CXF サーバーおよびクライアントを設定できます。

CxfEndpointConfigurer の client} メソッド。

username

非対応

Camel 2.12.3 の新機能。このオプションは、CXF クライアントのユーザー名の基本認証情報を設定するために使用されます。

password

非対応

Camel 2.12.3 の新機能。このオプションは、CXF クライアントのパスワードの基本認証情報を設定するために使用されます。

continuationTimeout

非対応

serviceName および portNameQNames であるため、上記の例に示すように、それらを指定する際に {namespace} のプレフィックスが付けられるようにしてください。

データフォーマットの説明

DataFormat

説明

POJO

POJO(古い Java オブジェクト)は、ターゲットサーバーで呼び出されるメソッドに対する Java パラメーターです。プロトコルおよび論理 JAX-WS ハンドラーの両方がサポートされます。

PAYLOAD

PAYLOAD は、CXF エンドポイントでメッセージ設定が適用された後にメッセージペイロード( soap:bodyの内容)です。Protocol JAX-WS ハンドラーのみがサポートされます。論理 JAX-WS ハンドラーはサポートされていません。

MESSAGE

MESSAGE は、トランスポート層から受信される raw メッセージです。Stream と通信または変更することは推奨されません。このような DataFormat を使用している場合は、camel-cxf コンシューマーと JAX-WS ハンドラーがサポートされないため、CXF インターセプターの一部が削除されます。

CXF_MESSAGE

Camel 2.8.2 の新機能。CXF_MESSAGE により、トランスポート層から未加工 SOAP メッセージにメッセージを変換して CXF インターセプターの完全な機能を呼び出すことが可能になりました。

エクスチェンジプロパティー CamelCXFDataFormat を取得すると、エクスチェンジのデータ形式モードを判別できます。交換キー定数は org.apache.camel.component.cxf.CxfConstants.DATA_FORMAT_PROPERTY で定義されます。

Apache Aries Blueprint を使用した CXF エンドポイントの設定

Camel 2.8 以降、CXF エンドポイントの Aries Blueprint 依存関係インジェクションの使用はサポートされません。スキーマは 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>

現在、endpoint 要素は最初にサポートされている CXF namespacehandler です。

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)に出力します。LoggingOutInterceptorPRE_STREAM フェーズであるため( PRE_STREAM フェーズは MESSAGE モードで削除されています)、LoggingOutInterceptorWRITE フェーズ中に実行されるように設定する必要があります。以下に例を示します。

   <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 -first 開発者 の観点からは、帯域外 および帯域外ヘッダーがあります。

アウト バウンド ヘッダーは、SOAP ヘッダーなどのエンドポイントの WSDL バインディングコントラクトの一部として明示的に定義されるヘッダーです。

アウトバウンド ヘッダーは、ネットワークを介してシリアライズされるヘッダーですが、WSDL バインディングコントラクトの一部ではありません。

ヘッダーのリレー/フィルタリングは双方向です。

ルートに CXF エンドポイントがあり、開発者が SOAP ヘッダーなどの有線ヘッダーを持つ必要がある場合、別の JAXWS エンドポイントによって消費されるルートと一緒にリレーされる必要がある場合は、relayHeaders がデフォルト値の true に設定する必要があります。

POJO モードでのみ利用可能

relayHeaders=true 設定は、ヘッダーをリレーする意図を表します。特定のヘッダーがリレーされるかどうかの実際の決定は、MessageHeadersRelay インターフェースを実装するプラグ可能なインスタンスに委譲されます。MessageHeadersRelay の具体的な実装を参照し、ヘッダーをリレーする必要があるかどうかを判断します。すでに SoapMessageHeadersRelay の実装があり、これはそれ自体をよく知られた SOAP ネームスペースにバインドします。現在、out ofband ヘッダーのみがフィルターされ、relayHeaders=true の場合、Oband ヘッダーは常にリレーされます。ネットワーク上にヘッダーがあり、その名前空間がランタイムに不明な場合は、フォールバックする DefaultMessageHeadersRelay が使用され、すべてのヘッダーをリレーできます。

relayHeaders=false 設定は、すべてのヘッダー、帯域外および帯域外(out ofband)がドロップされることをアサートします。

独自の 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"/>

ヘッダーをリレー/ドロップする方法を示すテストをご覧ください。

link:https://svn.apache.org/repos/asf/camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CxfMessageHeadersRelayTest.java[https://svn.apache.org/repos/asf/camel/branches/camel-1.x/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/soap/headers/CxfMessageHeadersRelayTest.java ]

リリース 2.0 以降の変更

  • POJO および PAYLOAD モードがサポートされます。POJO モードでは、帯域外ヘッダーのみが処理され、CXF のヘッダーリストから削除されたため、フィルタリングにだけ利用できます。アウトバウンドヘッダーは、POJO モードの MessageContentList に組み込まれています。camel-cxf コンポーネントは、MessageContentList から In-band ヘッダーのフィルターが必要な場合に、PAYLOAD モードまたはプラグインを CXF インターセプター/JAXWS Handler で使用してみてください。
  • Message Header Relay メカニズムは 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 のプロパティーです。以下は、ユーザー定義の Message Header フィルターを設定する例です。

    <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 で設定できます。

Name

説明

type

必須?

デフォルト値

relayHeaders

すべてのメッセージヘッダーは、メッセージヘッダーフィルターによって処理されます。

boolean

非対応

true (1.6.1 behavior)

relayAllMessageHeaders

すべてのメッセージヘッダーが伝播されます(メッセージヘッダーフィルターによる処理なし)。

boolean

非対応

false (1.6.1 の動作)

allowFilterNamespaceClash

2 つのフィルターがアクティベーション namespace で重複している場合、プロパティーによって処理される方法が制御されます。値が true の場合、最後の値が優先されます。値が false の場合、例外が発生します。

boolean

非対応

false (1.6.1 の動作)

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 に変更されました。

ルート beans 要素に指定された JAX-WS schemaLocation 属性が含まれるようにしてください。これにより、CXF はファイルを検証でき、必須です。また、< cxf:cxfEndpoint/ > タグの最後にある namespace 宣言にも注意してください。組み合わせた {namespace}localName 構文が存在すると、このタグの属性値に対してはサポートされないためです。

cxf:cxfEndpoint 要素は、多くの追加属性をサポートします。

Name

PortName

このサービスが実装しているエンドポイント名。wsdl:port@name にマッピングします。ns:PORT_NAME の形式では、ns は、このスコープで有効な名前空間プレフィックスです。

serviceName

このサービスは実装されているサービス名で、wsdl:service@name にマップされます。ns:SERVICE_NAME の形式では、ns は、このスコープで有効な namespace プレフィックスです。

wsdlURL

WSDL の場所。クラスパス、ファイルシステム、またはリモートでホストできます。

bindingId

使用するサービスモデルの bindingId

address

サービスの公開アドレス。

bus

JAX-WS エンドポイントで使用されるバス名。

serviceClass

JSR181 アノテーションが含まれる SEI(Service Endpoint Interface)クラスのクラス名。

また、多くの子要素もサポートします。

Name

cxf:inInterceptors

このエンドポイントの受信インターセプター。< bean> または & lt; ref& gt; のリスト。

cxf:inFaultInterceptors

このエンドポイントの受信障害インターセプター。< bean> または & lt; ref& gt; のリスト。

cxf:outInterceptors

このエンドポイントの送信インターセプター。< bean> または & lt; ref& gt; のリスト。

cxf:outFaultInterceptors

このエンドポイントの送信障害インターセプター。< bean> または & lt; ref& gt; のリスト。

cxf:properties

JAX-WS エンドポイントに提供する必要があるプロパティーマップ。以下を参照してください。

cxf:handlers

JAX-WS エンドポイントに提供する JAX-WS ハンドラーリスト。以下を参照してください。

cxf:dataBinding

エンドポイントで使用する DataBinding を指定できます。これは、Spring < bean class="MyDataBinding "/> 構文を使用して指定できます。

cxf:binding

使用するエンドポイントの BindingFactory を指定できます。これは、Spring < bean class="MyBindingFactory "/> 構文を使用して指定できます。

cxf:features

このエンドポイントのインターセプターを保持する機能。< bean> または &lt; ref> sのリスト

cxf:schemaLocations

使用するエンドポイントのスキーマの場所。< schemaLocation> の一覧

cxf:serviceFactory

使用するこのエンドポイントのサービスファクトリー。これは、Spring < bean class="MyServiceFactory"/> 構文を使用して指定できます

インターセプター、プロパティー、およびハンドラーを提供する方法を示すより高度な例は、http://cwiki.apache.org/CXF20DOC/jax-ws-configuration.htmlを参照してください。

注記

CXF:properties を使用して CXF エンドポイントの dataFormat、および Spring 設定ファイルから 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 という名前のクラスパスにファイルを作成します。このファイルには、1 行にコメントがない org.apache.cxf.common.logging.Log4jLogger クラスの完全修飾名を含める必要があります。

How to allow camel-cxf response message with xml start document

PHP などの一部の SOAP クライアントを使用している場合、CXF は XML 開始ドキュメント < ?xml version="1.0" encoding="utf-8"?> を追加しないため、この種のエラーが発生します

Error:sendSms: SoapFault exception: [Client] looks like we got no XML document in [...]

この問題を解決するには、XML 開始ドキュメントを書くように StaxOutInterceptor に指示する必要があります。

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 invoker をベースとしているため、メッセージヘッダーには 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 クライアント API をベースにしています。最初にメッセージヘッダーで操作名を指定し、続いてメソッドパラメーターを一覧に追加し、このパラメーター一覧でメッセージを初期化する必要があります。応答メッセージのボディーは messageContentsList で、そのリストから結果を取得できます。

メッセージヘッダーで操作名を指定しない場合、CxfProducerCxfEndpoint から defaultOperationName の使用を試行します。CxfEndpointdefaultOperationName が設定されていない場合、これは操作一覧から最初の操作名を選択します。

メッセージボディーからオブジェクトアレイを取得する場合は、以下のように 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() は、SOAP メッセージヘッダーおよびボディー要素の getter がある org.apache.camel.component.cxf.CxfPayload オブジェクトを返します。この変更により、Apache Camel メッセージからネイティブ CXF メッセージを分離できます。

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 は、CXF エンドポイントが Camel エクスチェンジを生成または消費するときにデータ形式が Java オブジェクトのリスト であることを意味します。Apache Camel はメッセージボディーをこのモードで POJO として公開しますが、CXF コンポーネントは引き続き SOAP ヘッダーの読み書きへのアクセスを提供します。ただし、CXF インターセプターは処理後にヘッダーリストから In-band SOAP ヘッダーを削除するため、POJO モードで使用できるのは帯域外な SOAP ヘッダーのみです。

以下の例は、SOAP ヘッダーの取得/設定方法を示しています。CXF エンドポイントから別のエンドポイントに転送するルートがあるとします。つまり、SOAP Client Apache Camel CXF サービスです。リクエストが CXF サービスに移動し、応答が SOAP クライアントに戻る前に 2 つのプロセッサーを添付して SOAP ヘッダーを取得/挿入できます。この例のプロセッサー(1)および(2)は InsertRequestOutHeaderProcessor および InsertResponseOutHeaderProcessor です。ルートは以下のようになります。

<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 メッセージヘッダー名は org.apache.cxf.headers.Header.list で、CXF で定義された定数(org.apache.cxf.headers.Header.HEADER_LIST)です。ヘッダーの値は、CXF SoapHeader オブジェクト(org.apache.cxf.binding.soap.SoapHeader)の List <> です。以下のスニペットは InsertResponseOutHeaderProcessor です(レスポンスメッセージに新しい SOAP ヘッダーを挿入します)。InsertResponseOutHeaderProcessorInsertRequestOutHeaderProcessor の両方で 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 メッセージにアクセスする方法 すでに紹介しています( 「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 Client Camel CXF サービス)、SOAP クライアントによって送信される SOAP ヘッダーも CXF サービスに転送されます。ヘッダーの転送を希望しない場合は、org.apache.cxf.headers.Header.list Camel ヘッダーから削除します。

SOAP ヘッダーが MESSAGE モードで利用できない

SOAP 処理はスキップされるため、SOAP ヘッダーは MESSAGE モードでは使用できません。

Apache Camel から SOAP Fault をスローする方法

CXF エンドポイントを使用して SOAP リクエストを消費する場合は、Camel コンテキストから SOAP Fault をスローする必要がある場合があります。基本的に、throwFault DSL を使用してこれを行うことができます。POJOPAYLOAD、および 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 Fault メッセージを設定し、メッセージヘッダーにレスポンスコードを設定できます。

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 Fault を設定し、以下のように 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 クライアント 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 and MTOM の両方がサポートされます(MTOM を有効にするための Payload Mode の例を参照してください)。 ただし、SOAP with Attachment はテストされていません。 アタッチメントはマーシャリングされ、POJO にアンマーシャリングされるため、ユーザーは通常添付ファイルを扱う必要はありません。 アタッチメントは 2.1 以降、Camel メッセージの添付ファイルに伝播されます。 そのため、Camel Message API による再試行添付が可能です。

DataHandler Message.getAttachment(String id)

.

ペイロードモード: MTOM は 2.1 以降サポートされます。アタッチメントは、上記の Camel Message API によって取得できます。このモードでは SOAP 処理がないため、SOAP with Attachment はサポートされません。

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>

Payload モードの CXF エンドポイントに送信する attachment のある Camel メッセージを生成できます。

Exchange exchange = context.createProducerTemplate().send("direct:testEndpoint", new Processor() {

    public void process(Exchange exchange) throws Exception {
        exchange.setPattern(ExchangePattern.InOut);
        List&lt;Source> elements = new ArrayList&lt;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());

Payload モードの 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&lt;Source> elements = new ArrayList&lt;Source>();
        elements.add(new DOMSource(DOMUtils.readXml(new StringReader(MtomTestHelper.RESP_MESSAGE)).getDocumentElement()));
        CxfPayload&lt;SoapHeader> sbody = new CxfPayload&lt;SoapHeader>(new ArrayList&lt;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")));

    }
}

Message Mode: 接続は、メッセージをまったく処理しないため、サポートされていません。

CXF_MESSAGE Mode: MTOM はサポートされ、上記の Camel Message API によって接続を取得できます。マルチパート(MTOM)メッセージを受信すると、デフォルトの SOAPMessage to String コンバーターはボディーに完全なマルチパートペイロードを提供することに注意してください。SOAP XML を String としてのみ必要な場合は、メッセージボディーを message.getSOAPPart() で設定でき、Camel convert は残りの作業を行うことができます。

スタックトレース情報を伝播させる方法

Java の例外がサーバー側で発生したときに、例外のスタックトレースがフォールトメッセージにマーシャリングされてクライアントに返されるように、CXF エンドポイントを設定することができます。この機能を有効にするには、以下のように cxfEndpoint 要素で、dataFormatPAYLOAD に設定し、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 として残ることができます。ペイロードが変更されていない場合は、ターゲットの宛先に直接ストリーミングすることができます。一般的な「simple proxy」のユースケース(例: from("cxf:…​").to("cxf:…​")については、パフォーマンスが大幅に向上し、メモリーの要件が大幅に低下する可能性があります。

ただし、ストリーミングが適切でない場合もあります。ストリーミングの性質上、無効な受信 XML が処理チェーンの後半までキャッチされないことがあります。また、特定のアクションでは、メッセージを DOM に解析(WS-Security やメッセージトレースなど)する必要があります。この場合、ストリーミングの利点は制限されます。この時点で、ストリーミングを制御する 2 つの方法があります。

  • エンドポイントプロパティー: "allowStreaming=false" をエンドポイントプロパティーとして追加し、ストリーミングのオン/オフをオン/オフにできます。
  • コンポーネントプロパティー: CxfComponent オブジェクトには、コンポーネントから作成されるエンドポイントのデフォルトを設定できる allowStreaming プロパティーもあります。
  • グローバルシステムプロパティー: オフの場合は、"org.apache.camel.component.cxf.streaming" のシステムプロパティーを "false" に追加して有効にすることができます。これはグローバルデフォルトを設定しますが、上記のエンドポイントプロパティーを設定すると、そのエンドポイントのこの値が上書きされます。

汎用 CXF Dispatch モードの使用

2.8.0 以降、camel-cxf コンポーネントは、任意の構造のメッセージを転送できる汎用 CXF ディスパッチモード をサポートします(つまり、特定の XML スキーマにバインドされません)。このモードを使用するには、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(case-insensitive)キーを使用して Camel ヘッダーに提供されます。

75.1. JBoss Enterprise Application Platform での CXF コンシューマー

JBoss Enterprise Application Platform での camel-cxf コンシューマーの設定は、スタンドアロン Camel とは異なります。プロデューサーエンドポイントは通常どおり機能します。

JBoss Enterprise Application Platform では、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 socket-binding によって指定されたインターフェース/ポートをリッスンするように設定されます。デフォルトでは、これは 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 としてパッケージ化する 必要があり ます。以前の Fuse on JBoss EAP リリースでは、JAR などの他のタイプのアーカイブの使用は許可されますが、サポート対象外になりました。

75.1.1. 代替ポートの設定

代替ポートが許可される場合は、JBoss Enterprise Application Platform サブシステム設定を使用して設定する必要があります。詳細は、サーバーのドキュメントで説明されています。

https://access.redhat.com/documentation/ja-jp/red_hat_jboss_enterprise_application_platform/7.1/html/configuration_guide/configuring_the_web_server_undertow

75.1.2. SSL の設定

SSL を設定するには、JBoss Enterprise Application Platform の『SSL 設定ガイド』を参照してください。

https://access.redhat.com/documentation/ja-jp/red_hat_jboss_enterprise_application_platform/7.1/html-single/how_to_configure_server_security/#configure_one_way_and_two_way_ssl_tls_for_application

75.1.3. Elytron を使用したセキュリティー設定

Fuse on JBoss EAP は、Elytron セキュリティーフレームワークでの camel-cxf コンシューマーエンドポイントのセキュア化をサポートします。

75.1.3.1. セキュリティードメインの設定

Elytron で Fuse on JBoss EAP アプリケーションをセキュアにするには、WAR デプロイメントの WEB-INF/jboss-web.xml 内でアプリケーションセキュリティードメインを参照する必要があります。

<jboss-web>
  <security-domain>my-application-security-domain</security-domain>
</jboss-web>

&lt ;security-domain> 設定は、Undertow サブシステムによって定義される < application-security-domain& gt; の名前を参照します。たとえば、Undertow サブシステム < application-security-domain > は、以下のように JBoss Enterprise Application Platform サーバーの 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>

&lt ;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>

Servlet Specification で定義された < url-pattern > は Web アプリケーションのコンテキストパスに相対することに注意してください。アプリケーションが my-app.war としてパッケージされている場合、JBoss Enterprise Application Platform はコンテキストパス /my-app でアクセスできるようになり、< url-patternpattern > /webservices/*/my-app への相対パスに適用されます。

たとえば、http://my-server/my-app/webservices/my-endpoint に対するリクエストは /webservices/* パターンと一致しますが、http://my-server/webservices/my-endpoint は一致しません。

これは、Fuse on JBoss EAP ではベースパスがホスト Web アプリケーションコンテキストパス外にある camel-cxf エンドポイントコンシューマーを作成することができるため重要です。たとえば、my-app.war 内に http://my-server/webservices/my-endpoint の camel-cxf コンシューマーを作成できます。

このようなコンテキストエンドポイントのセキュリティー制約を定義するために、Fuse on JBoss EAP はカスタム 標準以外 の <url-pattern & gt; 規則をサポートします。たとえば、my-app.war 内で http://my-server/webservices/my-endpoint をセキュアにするには、以下の設定を 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>
Red Hat logoGithubRedditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

© 2024 Red Hat, Inc.