SAAJを使用して,SOAPアプリケーションを開発する場合の注意事項について説明します。
RPC形態,メッセージング形態,およびEJB形態のSOAPサービスで,同一のサービス名は指定しないでください。同一のサービス名のSOAPサービスがデプロイされていると,予期しない動作をするおそれがあります。
複数個のAttachmentPartオブジェクトを追加する場合,AttachmentPartオブジェクトを追加する個数分,生成するようにしてください。同一のAttachmentPartオブジェクトをSOAPMessage#addAttachmentPart(AttachmentPart AttachmentPart)メソッドの引数として指定し,処理を複数回実行しても,SOAPメッセージ上には一つしか存在しない場合があります。
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例外は発生しません。
SOAPMessage#setProperty(java.lang.String property,java.lang.Object value)メソッドで指定できるCHARACTER_SET_ENCODING,およびWRITE_XML_DECLARATIONのvalue値には,Stringオブジェクトを指定してください。Stringオブジェクト以外を設定した場合,java.lang.ClassCastException例外が発生することがあります。
MimeHeaderオブジェクト生成時に,引数で,name,およびvalueに非US-ASCII文字列を指定しないでください。MimeHeaderオブジェクト生成時の引数で,name,およびvalueに非US-ASCII文字列を指定しても,java.lang.IllegalArgumentException例外が発生しない場合があります。
各APIに関して不正な引数を与えた場合にスローされる例外を次に示します。
表5-2 各APIに関して不正な引数を与えた場合にスローされる例外
SAAJ仕様書に記載されている各メソッドのthrows:の内容 | 各APIでスローされる例外 |
---|---|
javax.xml.soap.SOAPException | javax.xml.soap.SOAPException |
java.lang.IllegalArgumentException | java.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 |
SOAPPart#setContent(javax.xml.transform.Source source)メソッドの引数には,正しいSOAPメッセージを表すソースオブジェクトを指定してください。正しいSOAPメッセージを表すソースオブジェクトを指定しなかった場合,不正なSOAPメッセージを送信してしまう場合があります。
AttachmentPartオブジェクトのContent-Typeヘッダがtext/plainの場合,送受信できる添付ファイルのサイズの上限は1MBです。1MBより大きいサイズの添付ファイルを受信してAttachmentPartのContentを取得すると,1MBを超えた部分が切り捨てられたStringオブジェクトが返されます。
Webサーバから受け取ったクッキーは,SOAPConnectionオブジェクトが保持します。クッキーを利用する場合,メッセージングサービスを呼び出すたびに,SOAPConnectionオブジェクトを破棄することなく,継続して使用してください。
expires属性で設定したクッキーの有効期限に達しても,SOAPクライアントライブラリは保持しているクッキーを削除しません。
期限切れのクッキーを受け取っても処理できるようにサーバで対処してください。
SAAJの各メソッドは,スレッドセーフではありません。SAAJのオブジェクトをマルチスレッドで共有しないでください。共有した場合には,動作を保障できません。
受信電文のSOAPヘッダおよびSOAPボディの子孫ノードにテキストノードが存在する場合,兄弟ノードのすべてのテキストノードを連結し,そのテキストノードを同じ階層の最後に追加します。
受信電文のBody要素に対するjavax.xml.soap.SOAPElement#getChildElementsおよびorg.w3c.dom.Node#getChildNodesの結果を示します。
<soapenv:Body><a/>△△foo△△<b/>△△bar△△</soapenv:Body>
Iteratorの最初の要素 : Elementノード <a/>
Iteratorの二番目の要素 : Elementノード <b/>
Iteratorの三番目の要素 : Textノード △△foo△△△△bar△△
NodeListの最初のノード : Elementノード <a/>
NodeListの二番目のノード : Elementノード <b/>
NodeListの三番目のノード : Textノード △△foo△△△△bar△△
注 △は半角スペースを表します。
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" ) );
同じ名前空間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>
SOAPMessage#setProperty()メソッドの引数で,CHARACTER_SET_ENCODINGプロパティに指定できる値は"utf-8"だけです。
SOAPMessage#setProperty()メソッドの引数で,CHARACTER_SET_ENCODINGプロパティに"utf-16"を指定してSOAPメッセージを作成し,送信した場合,実際の送信メッセージにあるSOAPメッセージのエンコード方式が"utf-16"と異なることがあります。
SOAPPartクラスから取得したMimeHeaderは有効にならないため,利用しないことを推奨します。
SOAPPart#getAllMimeHeaders()メソッドを発行して値を取得した場合,実際の送信メッセージにあるSOAPメッセージに含まれるMIMEヘッダと異なることがあります。
SOAPPartクラスに対し指定したMimeHeaderは有効にならないため,利用しないでください。
SOAPPart#addMimeHeader()メソッド,SOAPPart#setMimeHeader()メソッドでMIMEヘッダを追加した場合,またはSOAPPart#setContentId()メソッド,SOAPPart#setContentLocation()メソッドで値を指定した場合,実際の送信メッセージにあるSOAPメッセージに含まれるMIMEヘッダに反映されないことがあります。
SOAPFaultクラスのsetFaultCodeメソッドの引数に,"prefix:localName"形式のStringオブジェクトを指定する場合は,SOAPFault#setFaultCode(String faultCode)メソッドではなく,SOAPFault#setFaultCode(Name faultCodeQName)メソッドを使用してください。
SOAPFault#setFaultCode(String faultCode)メソッドの引数に"prefix:localName"形式のStringオブジェクトを指定した場合,javax.xml.soap.SOAPException例外が発生することがあります。
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メッセージが送信されることがあります。
名前空間プレフィクスを引数として渡すメソッドを発行した場合,次の現象が発生することがあります。
メソッドを発行する前に,引数がnullオブジェクトでないことを確認してください。メソッドの引数にnullオブジェクトを指定した場合,次の現象が発生することがあります。
マルチパート形式のSOAPメッセージを受信した場合,SOAPMessage#getProperty()メソッドを使用して,CHARACTER_SET_ENCODINGプロパティの値を取得することはできません。nullオブジェクトが返されます。
SOAPMessage#saveChanges()メソッドおよびSOAPMessage#saveRequired()メソッドを発行しないでください。
SOAPMessage#saveChanges()メソッドおよびSOAPMessage#saveRequired()メソッドを発行した場合,生成されるSOAPメッセージが予期しない形式になることがあります。
SOAPMessage#writeTo()メソッドは発行しないでください。
SOAPMessage#writeTo()メソッドを発行後に,SOAPConnection#call()メソッドを実行した場合,SOAPConnection#call()メソッド発行の延長でjavax.xml.soap.SOAPException例外が発生することがあります。
また,SOAPMessage#writeTo()メソッドの引数に,すでにcloseされたOutputStreamオブジェクトを指定した場合,java.io.IOException例外が発生しないで処理が続行することがあります。
Node#detachNode()メソッドの発行によって,対象オブジェクトが存在しない状態でメソッドを発行すると,例外が発生します。Node#detachNode()メソッドの発行対象となったオブジェクトを包含しているオブジェクトに対してメソッドを発行すると,例外が発生することがあります。
Node#detachNode()メソッドを発行した場合は,包含するオブジェクトを再生成してからメソッドを発行してください。
次に示す表(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資源が枯渇するおそれがあります。
名前空間URIまたは名前空間プレフィクスを引数として指定する場合は,引数がnullオブジェクトまたは""(空文字列)でないことを確認してください。
引数の名前空間URIまたは名前空間プレフィクスとしてnullオブジェクトまたは""(空文字列)を指定した場合,次の現象が発生することがあります。
SOAPElement#addChildElement()メソッドの引数にSOAP名前空間("http://schemas.xmlsoap.org/soap/envelope/")に属するSOAPエンベロープ,SOAPヘッダ,SOAPボディ,および自分自身を含む要素を指定した場合,java.lang.StackOverflowError例外が発生することがあります。
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を抽出して削除してください。
SOAPアプリケーションでは,引数にcloseしたInputStreamオブジェクトを指定しないでください。
MessageFactory#createMessage(MimeHeaders, InputStream)で,closeしたInputStreamオブジェクトを指定すると,java.lang.RuntimeException例外が発生します。
SOAPEnvelopeの子孫ノードに対して,SOAPElement#getVisibleNamespacePrefixes()を発行すると,戻り値のIteratorに名前空間プレフィクスsoapenvが二つ含まれます。二つの名前空間プレフィクスは同じ名前空間URIを指します。
メソッドを使用してContent-Typeヘッダを設定する場合は,添付オブジェクトに対応するContent-Typeを指定してください。
次のメソッドを使用して添付オブジェクトに対応しないContent-Typeを指定した場合,タイムアウト待ちが発生する,または不正なSOAPメッセージが送信されることがあります。
次のメソッドを使用してMIMEヘッダまたはSOAPヘッダを取得する場合,該当するMIMEヘッダまたはSOAPヘッダが存在しないと,nullオブジェクトが返されます。
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で設定した値は付与されません。
クライアントプログラムでは必ずManagementクラスを使用してください。SAAJを利用して添付ファイルを送受信するときに生成される退避ファイルが,削除されないで残ることがあります。
detail entry以外の内容を含むdetail要素を利用しているSOAP Faultの受信メッセージから得られたjavax.xml.soap.SOAPBodyオブジェクト,およびjavax.xml.soap.SOAPFaultオブジェクトに対して,toStringメソッドを呼び出さないでください。toStringメソッドを呼び出した場合,オブジェクトの内容を表現するXML文字列ではなく,オブジェクトのクラス名とハッシュコードから構成される文字列を返すことがあります。