5.4 SAAJを使用したSOAPアプリケーション開発時の注意事項

SAAJを使用して,SOAPアプリケーションを開発する場合の注意事項について説明します。

<この節の構成>
(1) SOAPアプリケーションのサービス名に関する注意
(2) 複数個のAttachmentPartオブジェクトを追加する場合の注意
(3) setPropertyメソッドで指定するプロパティのデフォルト値
(4) setPropertyメソッドで指定するプロパティ値に関する注意
(5) MimeHeaderオブジェクトで指定できる文字コードに関する注意
(6) 各メソッドで発生する例外
(7) SOAPPartクラスのsetContentメソッドの引数に関する注意
(8) AttachmentPartオブジェクトのContent-Typeヘッダがtext/plainの場合の上限サイズ
(9) クッキーについて
(10) クッキーの有効期限について
(11) マルチスレッドでの動作について
(12) 受信電文のSOAPヘッダおよびSOAPボディの子孫ノードにテキストノードが存在する場合の注意
(13) 名前空間に属さない要素を追加する場合の注意
(14) SOAPメッセージの要素の名前空間プレフィクスに関する注意
(15) setPropertyメソッドで指定したエンコード方式に関する注意
(16) SOAPPartクラスから取得したMimeHeaderに関する注意
(17) MIMEヘッダに関する注意
(18) SOAPFaultクラスのsetFaultCodeメソッドの引数に関する注意
(19) AttachmentPartクラスのsetContentメソッドの引数に関する注意
(20) 名前空間プレフィクスを引数として渡すメソッドを発行した場合の注意
(21) 引数にnullオブジェクトを指定した場合の注意
(22) CHARACTER_SET_ENCODINGプロパティの値の取得に関する注意
(23) SOAPMessageクラスのsaveChangesメソッドおよびsaveRequiredメソッドの発行に関する注意
(24) SOAPMessageクラスのwriteToメソッドの発行に関する注意
(25) NodeクラスのdetachNodeメソッドの発行に関する注意
(26) 添付ファイルの削除に関する注意
(27) 引数の名前空間URIまたは名前空間プレフィクスの指定に関する注意
(28) SOAPElementクラスのaddChildElementメソッドの指定に関する注意
(29) SOAPHeaderクラスのexamineHeaderElementsメソッドおよびextractHeaderElementsメソッドの実行に関する注意
(30) MessageFactoryクラスのcreateMessageメソッドの引数に関する注意
(31) SOAPElementクラスのgetVisibleNamespacePrefixesメソッドの指定に関する注意
(32) 添付オブジェクトに対応するContent-Typeヘッダの設定に関する注意
(33) MIMEヘッダまたはSOAPヘッダを取得するメソッドに関する注意
(34) 送信メッセージのHTTPヘッダについて
(35) Managementクラスの使用に関する注意事項
(36) toStringメソッドの使用に関する注意事項

(1) SOAPアプリケーションのサービス名に関する注意

RPC形態,メッセージング形態,およびEJB形態のSOAPサービスで,同一のサービス名は指定しないでください。同一のサービス名のSOAPサービスがデプロイされていると,予期しない動作をするおそれがあります。

(2) 複数個のAttachmentPartオブジェクトを追加する場合の注意

複数個のAttachmentPartオブジェクトを追加する場合,AttachmentPartオブジェクトを追加する個数分,生成するようにしてください。同一のAttachmentPartオブジェクトをSOAPMessage#addAttachmentPart(AttachmentPart AttachmentPart)メソッドの引数として指定し,処理を複数回実行しても,SOAPメッセージ上には一つしか存在しない場合があります。

(3) setPropertyメソッドで指定するプロパティのデフォルト値

SOAPMessage#setProperty(java.lang.String property,java.lang.Object value)メソッドで指定できるプロパティは次の二つだけです。

CHARACTER_SET_ENCODINGのデフォルト値は"utf-8",WRITE_XML_DECLARATIONのデフォルト値は"false"です。CHARACTER_SET_ENCODING,WRITE_XML_DECLARATION以外をプロパティとして指定しても,javax.xml.soap.SOAPException例外は発生しません。

(4) setPropertyメソッドで指定するプロパティ値に関する注意

SOAPMessage#setProperty(java.lang.String property,java.lang.Object value)メソッドで指定できるCHARACTER_SET_ENCODING,およびWRITE_XML_DECLARATIONのvalue値には,Stringオブジェクトを指定してください。Stringオブジェクト以外を設定した場合,java.lang.ClassCastException例外が発生することがあります。

(5) MimeHeaderオブジェクトで指定できる文字コードに関する注意

MimeHeaderオブジェクト生成時に,引数で,name,およびvalueに非US-ASCII文字列を指定しないでください。MimeHeaderオブジェクト生成時の引数で,name,およびvalueに非US-ASCII文字列を指定しても,java.lang.IllegalArgumentException例外が発生しない場合があります。

(6) 各メソッドで発生する例外

各APIに関して不正な引数を与えた場合にスローされる例外を次に示します。

表5-2 各APIに関して不正な引数を与えた場合にスローされる例外

SAAJ仕様書に記載されている各メソッドのthrows:の内容各APIでスローされる例外
javax.xml.soap.SOAPExceptionjavax.xml.soap.SOAPException
java.lang.IllegalArgumentExceptionjava.lang.IllegalArgumentException
javax.xml.soap.SOAPException
java.lang.IllegalArgumentException
java.lang.IllegalArgumentException
javax.xml.soap.SOAPException
java.lang.IllegalArgumentException以外
javax.xml.soap.SOAPException
記述なしjava.lang.IllegalArgumentException

(7) SOAPPartクラスのsetContentメソッドの引数に関する注意

SOAPPart#setContent(javax.xml.transform.Source source)メソッドの引数には,正しいSOAPメッセージを表すソースオブジェクトを指定してください。正しいSOAPメッセージを表すソースオブジェクトを指定しなかった場合,不正なSOAPメッセージを送信してしまう場合があります。

(8) AttachmentPartオブジェクトのContent-Typeヘッダがtext/plainの場合の上限サイズ

AttachmentPartオブジェクトのContent-Typeヘッダがtext/plainの場合,送受信できる添付ファイルのサイズの上限は1MBです。1MBより大きいサイズの添付ファイルを受信してAttachmentPartのContentを取得すると,1MBを超えた部分が切り捨てられたStringオブジェクトが返されます。

(9) クッキーについて

Webサーバから受け取ったクッキーは,SOAPConnectionオブジェクトが保持します。クッキーを利用する場合,メッセージングサービスを呼び出すたびに,SOAPConnectionオブジェクトを破棄することなく,継続して使用してください。

(10) クッキーの有効期限について

expires属性で設定したクッキーの有効期限に達しても,SOAPクライアントライブラリは保持しているクッキーを削除しません。

期限切れのクッキーを受け取っても処理できるようにサーバで対処してください。

(11) マルチスレッドでの動作について

SAAJの各メソッドは,スレッドセーフではありません。SAAJのオブジェクトをマルチスレッドで共有しないでください。共有した場合には,動作を保障できません。

(12) 受信電文のSOAPヘッダおよびSOAPボディの子孫ノードにテキストノードが存在する場合の注意

受信電文のSOAPヘッダおよびSOAPボディの子孫ノードにテキストノードが存在する場合,兄弟ノードのすべてのテキストノードを連結し,そのテキストノードを同じ階層の最後に追加します。

受信電文のBody要素に対するjavax.xml.soap.SOAPElement#getChildElementsおよびorg.w3c.dom.Node#getChildNodesの結果を示します。

注 △は半角スペースを表します。

(13) 名前空間に属さない要素を追加する場合の注意

SOAPボディの子要素以下の要素(SOAPボディの子要素を含む)に,その子要素として名前空間に属さない要素を追加する場合,javax.xml.soap.SOAPFactoryクラスのcreateElementメソッドでjavax.xml.soap.SOAPElementオブジェクトを生成し,生成したオブジェクトを指定して,javax.xml.soap.SOAPElementクラスのaddChildElementメソッドを呼び出してください。例を次に示します。

SOAPFactory soapFactory = SOAPFactory.newInstance();

// 名前空間に属さない"entry"という要素名の要素をsoapElementに追加する例
// soapElementは,子要素を追加するSOAPボディの子要素以下の要素(SOAPボディの子要素を含む)
soapElement.addChildElement( soapFactory.createElement( "entry" ) );

(14) SOAPメッセージの要素の名前空間プレフィクスに関する注意

同じ名前空間URIで異なる名前空間プレフィクスは使用しないでください。

要素の名前空間プレフィクスに,同じ名前空間URIで異なる名前空間プレフィクスを付けたメッセージを作成した場合,送信されるSOAPメッセージ内の要素の名前空間プレフィクスが作成時と異なることがあります(いちばん近い名前空間宣言の名前空間プレフィクスが付けられます)。作成したメッセージと送信されるSOAPメッセージの例を次に示します。

<作成したメッセージ>
<prefix01:elm1 xmlns:prefix01="http://localhost">
<prefix02:elm2 xmlns:prefix02="http://localhost">
<prefix01:elm3>
<prefix02:elm4/>
</prefix01:elm3>
</prefix02:elm2>
</prefix01:elm1>

<送信されるSOAPメッセージ>
<prefix01:elm1 xmlns:prefix01="http://localhost">
<prefix02:elm2 xmlns:prefix02="http://localhost">
<prefix02:elm3>
<prefix02:elm4/>
</prefix02:elm3>
</prefix02:elm2>
</prefix01:elm1>

(15) setPropertyメソッドで指定したエンコード方式に関する注意

SOAPMessage#setProperty()メソッドの引数で,CHARACTER_SET_ENCODINGプロパティに指定できる値は"utf-8"だけです。

SOAPMessage#setProperty()メソッドの引数で,CHARACTER_SET_ENCODINGプロパティに"utf-16"を指定してSOAPメッセージを作成し,送信した場合,実際の送信メッセージにあるSOAPメッセージのエンコード方式が"utf-16"と異なることがあります。

(16) SOAPPartクラスから取得したMimeHeaderに関する注意

SOAPPartクラスから取得したMimeHeaderは有効にならないため,利用しないことを推奨します。

SOAPPart#getAllMimeHeaders()メソッドを発行して値を取得した場合,実際の送信メッセージにあるSOAPメッセージに含まれるMIMEヘッダと異なることがあります。

(17) MIMEヘッダに関する注意

SOAPPartクラスに対し指定したMimeHeaderは有効にならないため,利用しないでください。

SOAPPart#addMimeHeader()メソッド,SOAPPart#setMimeHeader()メソッドでMIMEヘッダを追加した場合,またはSOAPPart#setContentId()メソッド,SOAPPart#setContentLocation()メソッドで値を指定した場合,実際の送信メッセージにあるSOAPメッセージに含まれるMIMEヘッダに反映されないことがあります。

(18) SOAPFaultクラスのsetFaultCodeメソッドの引数に関する注意

SOAPFaultクラスのsetFaultCodeメソッドの引数に,"prefix:localName"形式のStringオブジェクトを指定する場合は,SOAPFault#setFaultCode(String faultCode)メソッドではなく,SOAPFault#setFaultCode(Name faultCodeQName)メソッドを使用してください。

SOAPFault#setFaultCode(String faultCode)メソッドの引数に"prefix:localName"形式のStringオブジェクトを指定した場合,javax.xml.soap.SOAPException例外が発生することがあります。

(19) AttachmentPartクラスのsetContentメソッドの引数に関する注意

AttachmentPart#setContent(Object object, String contentType)メソッドの引数objectには,JAF仕様に準拠する型のオブジェクトを指定し,引数contentTypeには,RFC2045に準拠するContent-Typeヘッダの値を指定してください。

AttachmentPart#setContent(Object object, String contentType)メソッドの引数objectにJAF仕様に準拠する型のオブジェクト以外を指定した場合,または引数contentTypeにRFC2045に準拠するContent-Typeヘッダの値以外を指定した場合,タイムアウト待ちが発生し,不正なSOAPメッセージが送信されることがあります。

(20) 名前空間プレフィクスを引数として渡すメソッドを発行した場合の注意

名前空間プレフィクスを引数として渡すメソッドを発行した場合,次の現象が発生することがあります。

(21) 引数にnullオブジェクトを指定した場合の注意

メソッドを発行する前に,引数がnullオブジェクトでないことを確認してください。メソッドの引数にnullオブジェクトを指定した場合,次の現象が発生することがあります。

(22) CHARACTER_SET_ENCODINGプロパティの値の取得に関する注意

マルチパート形式のSOAPメッセージを受信した場合,SOAPMessage#getProperty()メソッドを使用して,CHARACTER_SET_ENCODINGプロパティの値を取得することはできません。nullオブジェクトが返されます。

(23) SOAPMessageクラスのsaveChangesメソッドおよびsaveRequiredメソッドの発行に関する注意

SOAPMessage#saveChanges()メソッドおよびSOAPMessage#saveRequired()メソッドを発行しないでください。

SOAPMessage#saveChanges()メソッドおよびSOAPMessage#saveRequired()メソッドを発行した場合,生成されるSOAPメッセージが予期しない形式になることがあります。

(24) SOAPMessageクラスのwriteToメソッドの発行に関する注意

SOAPMessage#writeTo()メソッドは発行しないでください。

SOAPMessage#writeTo()メソッドを発行後に,SOAPConnection#call()メソッドを実行した場合,SOAPConnection#call()メソッド発行の延長でjavax.xml.soap.SOAPException例外が発生することがあります。

また,SOAPMessage#writeTo()メソッドの引数に,すでにcloseされたOutputStreamオブジェクトを指定した場合,java.io.IOException例外が発生しないで処理が続行することがあります。

(25) NodeクラスのdetachNodeメソッドの発行に関する注意

Node#detachNode()メソッドの発行によって,対象オブジェクトが存在しない状態でメソッドを発行すると,例外が発生します。Node#detachNode()メソッドの発行対象となったオブジェクトを包含しているオブジェクトに対してメソッドを発行すると,例外が発生することがあります。

Node#detachNode()メソッドを発行した場合は,包含するオブジェクトを再生成してからメソッドを発行してください。

(26) 添付ファイルの削除に関する注意

次に示す表(MIMEヘッダのコンテントタイプの分類)の項番1~3の場合を除いて,AttachmentPart#getContent()メソッド発行後に,取得した入力ストリームをユーザプログラムで閉じていない場合,添付ファイルを削除できなくなることがあります。

なお,AttachmentPart#getDataHandler()メソッドの延長で,java.io.InputStreamオブジェクトを取得した場合も同様です。

表5-3 MIMEヘッダのコンテントタイプの分類

項番MIMEヘッダの
コンテントタイプ
AttachmentPart#getContent()
メソッドの戻り値
入力ストリームを明示的にユーザプログラムで閉じる必要の有無
1"text/plain"java.lang.String×
2"image/gif"java.awt.Image×
3"image/jpeg"java.awt.Image×
4"text/xml"javax.xml.transform.stream.StreamSource
5上記以外java.io.InputStream
(凡例)
×:入力ストリームを明示的にユーザプログラムで閉じる必要はありません。
○:入力ストリームを明示的にユーザプログラムで閉じる必要があります。

添付ファイルを削除できない場合,J2EEサーバを停止後,手動でファイルを削除してください。なお,入力ストリームを閉じないで連続稼働した場合,ファイルディスクリプタなどのOS資源が枯渇するおそれがあります。

(27) 引数の名前空間URIまたは名前空間プレフィクスの指定に関する注意

名前空間URIまたは名前空間プレフィクスを引数として指定する場合は,引数がnullオブジェクトまたは""(空文字列)でないことを確認してください。

引数の名前空間URIまたは名前空間プレフィクスとしてnullオブジェクトまたは""(空文字列)を指定した場合,次の現象が発生することがあります。

(28) SOAPElementクラスのaddChildElementメソッドの指定に関する注意

SOAPElement#addChildElement()メソッドの引数にSOAP名前空間("http://schemas.xmlsoap.org/soap/envelope/")に属するSOAPエンベロープ,SOAPヘッダ,SOAPボディ,および自分自身を含む要素を指定した場合,java.lang.StackOverflowError例外が発生することがあります。

(29) SOAPHeaderクラスのexamineHeaderElementsメソッドおよびextractHeaderElementsメソッドの実行に関する注意

SOAPHeader#examineHeaderElements()メソッドおよびSOAPHeader#extractHeaderElements()メソッドを実行すると,次のSOAPHeaderElementオブジェクトを含むIteratorが返されます。

SOAPHeader#examineHeaderElements()メソッドの場合,取得したIteratorの各要素から要求するactorを持つSOAPHeaderElementを抽出してください。

SOAPHeader#extractHeaderElements()メソッドの場合,引数で指定したactorを持つSOAPHeaderElementオブジェクト以外に,actorとして"http://schemas.xmlsoap.org/soap/actor/next"を持つSOAPHeaderElementオブジェクト,およびactor属性が存在しないSOAPHeaderElementオブジェクトが,SOAPHeaderオブジェクトから削除されます。指定したactorを持つSOAPHeaderElementオブジェクトだけを削除するには,いったんSOAPHeader#examineHeaderElements()メソッドでIteratorを取得後,要求するactorを持つSOAPHeaderElementを抽出して削除してください。

(30) MessageFactoryクラスのcreateMessageメソッドの引数に関する注意

SOAPアプリケーションでは,引数にcloseしたInputStreamオブジェクトを指定しないでください。

MessageFactory#createMessage(MimeHeaders, InputStream)で,closeしたInputStreamオブジェクトを指定すると,java.lang.RuntimeException例外が発生します。

(31) SOAPElementクラスのgetVisibleNamespacePrefixesメソッドの指定に関する注意

SOAPEnvelopeの子孫ノードに対して,SOAPElement#getVisibleNamespacePrefixes()を発行すると,戻り値のIteratorに名前空間プレフィクスsoapenvが二つ含まれます。二つの名前空間プレフィクスは同じ名前空間URIを指します。

(32) 添付オブジェクトに対応するContent-Typeヘッダの設定に関する注意

メソッドを使用してContent-Typeヘッダを設定する場合は,添付オブジェクトに対応するContent-Typeを指定してください。

次のメソッドを使用して添付オブジェクトに対応しないContent-Typeを指定した場合,タイムアウト待ちが発生する,または不正なSOAPメッセージが送信されることがあります。

(33) MIMEヘッダまたはSOAPヘッダを取得するメソッドに関する注意

次のメソッドを使用してMIMEヘッダまたはSOAPヘッダを取得する場合,該当するMIMEヘッダまたはSOAPヘッダが存在しないと,nullオブジェクトが返されます。

(34) 送信メッセージのHTTPヘッダについて

Content-Lengthヘッダ,およびContent-Typeヘッダの値は自動で付与されます。Content-Typeヘッダのcharsetに文字コードを設定する場合は,javax.xml.soap.SOAPMessage#setPropertyメソッドを使用して,CHARACTER_SET_ENCODINGを設定してください。

javax.xml.soap.SOAPMessageオブジェクトのMimeHeadersにContent-Lengthヘッダ,およびContent-Typeヘッダを設定していても,送信されるメッセージのHTTPヘッダにはMimeHeadersで設定した値は付与されません。

(35) Managementクラスの使用に関する注意事項

クライアントプログラムでは必ずManagementクラスを使用してください。SAAJを利用して添付ファイルを送受信するときに生成される退避ファイルが,削除されないで残ることがあります。

(36) toStringメソッドの使用に関する注意事項

detail entry以外の内容を含むdetail要素を利用しているSOAP Faultの受信メッセージから得られたjavax.xml.soap.SOAPBodyオブジェクト,およびjavax.xml.soap.SOAPFaultオブジェクトに対して,toStringメソッドを呼び出さないでください。toStringメソッドを呼び出した場合,オブジェクトの内容を表現するXML文字列ではなく,オブジェクトのクラス名とハッシュコードから構成される文字列を返すことがあります。