SAAJ:抱きたいカンケイ

この記事の執筆時点では、ほとんどのWebサービスは単純なメッセージ交換で構成されています。クライアントはWebサービスに接続し、そのサービスにメッセージを送信します。次に、Webサービスはその要求を処理してから、クライアントに応答を送り返します。この単純な要求/応答パターンは、HTTPプロトコルがクライアント/ Webサーバーの相互作用を促進する方法をモデル化しています。HTTPと同様に、Webサービスのメッセージ交換には、多くの場合、画像、ドキュメント、サウンドクリップなどのバイナリコンテンツを含める必要があります。この記事では、Java用添付API(SAAJ)1.2でSOAP(Simple Object Access Protocol)を使用してバイナリWebサービスコンテンツを送受信する方法を紹介します。

バイナリWebサービスコンテンツの転送の複雑さに飛び込む前に、単純な要求/応答スタイルのWebサービスは、リモートプロシージャコール(RPC)としてクライアント/サーバーの相互作用を行うサービスとは対照的であることを指摘する価値があります。 RPCでは、サーバーはAPIに似たインターフェイスを公開します。次に、クライアントは、サービスのAPIでリモート呼び出しを行い、必要なパラメーターを渡し、呼び出しによって生成される値を受け取ることによって、そのようなサービスを呼び出します。

XMLベースのRPCは、オブジェクト指向(OO)システムでオブジェクトを呼び出す方法に似ています。実際、XMLベースのRPC用のJava API(JAX-RPC)を使用している場合、JavaオブジェクトではなくXMLドキュメントを使用していることに気付くことはめったにありません。 JAX-RPCを使用すると、Java RMI(Remote Method Invocation)の場合と同じように、Webサービスをリモートオブジェクトと見なすことができます。 JAX-RPCランタイムは、高レベルのOOメソッド呼び出しをリモートWebサービスが期待するXMLドキュメントに変換します。 RPCスタイルのWebサービスは、より便利なプログラミングモデルを提供することがよくありますが、RPC呼び出しは、リモート呼び出しを構成するXMLメッセージを交換するために、低レベルのメッセージング層にも依存する必要があります。

一部のWebサービスでは、その下位レベルのメッセージング層に直接プログラミングすると便利なことがよくあります。たとえば、発注書ドキュメントを使用して領収書を返すWebサービスを呼び出す場合、そのドキュメント交換を単一の要求/応答メッセージ交換として簡単にモデル化できます。リモートメソッド呼び出しを行う代わりに、XMLメッセージを作成し、それらのメッセージをWebサービスに直接送信し、サービスのXML応答が存在する場合はそれを処理します。 SOAPはWebサービスメッセージの一般的なメッセージ形式を定義するため、SOAP準拠のメッセージを作成し、サービスが応答したら、それらのSOAP応答メッセージをプログラムが理解できる形式に解析して戻す必要があります。

SAAJは、SOAPメッセージを作成および読み取るための便利なライブラリを提供し、ネットワークを介してSOAPメッセージを送受信することもできます。SAAJは名前空間を定義しますjavax.xml.soap。そのパッケージに存在するクラスは、最初はXMLメッセージング用のJava API(JAXM)の一部を形成していましたが、最近では独自のAPIに分離されました。JAXMは、SOAPメッセージの構築と操作をSAAJに依存し、メッセージの信頼性やXMLメッセージングに固有のその他の機能を追加します。SAAJはJ2EE(Java 2 Platform、Enterprise Edition)1.4の必須コンポーネントですが、JAXMはそうではありません。この記事では、SAAJの最も有用な側面の1つであるSOAPメッセージにバイナリコンテンツを添付する機能に焦点を当てています。

添付ファイルの利点

SOAPのデザインセンターはメッセージ内のXMLドキュメントのカプセル化に重点を置いていますが、SOAPの添付機能はSOAPメッセージを拡張して、図1に示すように、通常のSOAP部分に加えて0個以上の添付ファイルを含めます。各添付ファイルはMIMEタイプによって定義され、バイトストリームとして表される任意のコンテンツを想定できます。

SOAPの添付機能は、クライアントが画像や音声データなどのバイナリデータをWebサービスに送信する場合に最も役立ちます。 SOAP添付ファイルがないと、バイナリデータを送信するのがより困難になります。たとえば、クライアントのSOAPメッセージは、バイナリファイルのURLアドレスを伝えることができます。次に、クライアントはHTTPサーバーを操作して、Webサービスにそのファイルを取得させる必要があります。これは、Webサービスクライアント、特にデジタルカメラやスキャナーなどの限られたリソースのデバイスで実行されているクライアントに過度の負担をかけることになります。 SOAPの添付機能により、SOAPメッセージを送信できるWebサービスクライアントは、バイナリファイルをSOAPメッセージに直接埋め込むことができます。

たとえば、SOAP添付ファイルは、ポータルWebサイトと対話するときに便利です。一元化された不動産検索ポータルに販売用住宅の説明と写真を配布する必要がある不動産業者ネットワークについて考えてみます。ポータルが添付ファイル付きのSOAPメッセージの投稿を許可するサーブレットを運用している場合、不動産業者は、それらの家の写真を含むいくつかのSOAPメッセージでリストを更新できます。SOAPメッセージ本文にはプロパティの説明が埋め込まれている場合があり、SOAP添付ファイルには画像ファイルが含まれている場合があります。そのシナリオでは、ポータルオペレーターのサーブレットがそのようなメッセージを受信すると、ポータルでの投稿の可用性を示す確認文書が返されます。図2は、そのようなWebサービスを示しています。

添付メッセージ付きSOAPの構造

添付ファイル付きのSOAPメッセージW3C(World Wide Web Consortium)注(「参考文献」を参照)は、SOAPに新しい機能を追加しません。むしろ、SOAPメッセージのMIMEタイプを利用して添付ファイルを定義する方法と、SOAP本体内からそれらの添付ファイルを参照する方法を定義します。

MIMEタイプmultipart/relatedは、複数の関連部分で構成されるドキュメントを定義します。添付ファイル付きのSOAPメッセージは、multipart/relatedMIMEタイプに従う必要があります。以下の例はmultipart/related、HTTPプロトコルにバインドされたSOAPメッセージを2つの添付ファイルとともに示しています。

POST / propertyListing HTTP / 1.1ホスト:www.realproperties.comコンテンツタイプ:マルチパート/関連; border = MIME_boundary; type = text / xml; Content-Length:NNNN --MIME_boundary Content-Type:text / xml; charset = UTF-8 Content-Transfer-Encoding:8bit Content-ID:Really Nice Homes、Inc。Add 1234 Main St Pleasantville CA 94323 250000 --MIME_boundary Content-Type:image / jpeg Content-ID:.... JPEG DATA ..... --MIME_boundary Content-Type:image / jpeg Content-ID:.... JPEG DATA ..... --MIME_boundary--

上記のマルチパートメッセージは、一連のMIMEヘッダーと関連データで構成されています。ドキュメントのルートにはSOAP本体があります。SOAP本体にはXMLデータのみが含まれているため、メッセージ全体のMIMEタイプはtext/xmlです。SOAPエンベロープの後には2つの添付ファイルがあり、それぞれがメッセージとともに送信される画像ファイルに対応しています。

コンテンツIDは各添付ファイルを識別します。W3Cノートでは、コンテンツIDまたはコンテンツの場所のいずれかが添付ファイルを参照できますが、前者が優先されます。このようなコンテンツIDは、添付ファイルへのURI(Uniform Resource Identifier)参照として機能します。SOAP 1.1エンコーディングルールは、XMLだけでなく任意のコンテンツを参照できるURIを介してSOAPメッセージ内のリソースを参照する方法を定義します(リソースのSOAP 1.1のセクション5を参照)。SOAPプロセッサは、メッセージを処理するときにこれらのURI参照を解決します。上記の例に基づいて、SOAPプロセッサは、SOAPメッセージ内のfrontImageコンテンツID[email protected]を持つデータセクションに要素を関連付けます。

添付ファイル付きのSOAPメッセージを作成して送信する

SAAJを使用すると、添付ファイルを含め、SOAPメッセージの任意の部分を作成および編集できます。SAAJのほとんどは、各プロバイダーが独自の製品にSAAJを実装できるように、抽象クラスとインターフェースに基づいています。Sun Microsystemsのリファレンス実装には、Java Web Services Developer Pack(JWSDP)が付属しています。

SOAPメッセージはXMLドキュメントの特殊な形式を表しているだけなので、JAASはXML処理用のDocument Object Model(DOM)APIに基づいています。ほとんどのSOAPメッセージコンポーネントjavax.xml.soap.Nodeは、org.w3c.dom.Nodeサブクラスであるインターフェイスから派生しています。SAAJサブクラスNodeは、SOAP固有の構造を追加します。たとえば、特別なNodeSOAPElementは、SOAPメッセージ要素を表します。

SAAJがインターフェイスと抽象クラスに依存している直接の結果は、ファクトリメソッドを介してほとんどのSOAP関連タスクを実行することです。アプリケーションをSAAJAPIに接続するには、最初にSOAPConnectionからを作成しますSOAPConnectionFactory。SOAPメッセージを作成および編集するために、MessageFactoryおよびを初期化することもできますSOAPFactoryMessageFactorySOAPメッセージを作成できSOAPFactory、SOAPメッセージの個々の部分を作成する方法を提供します。

SOAPConnectionFactory spConFactory = SOAPConnectionFactory.newInstance(); SOAPConnection con = spConFactory.createConnection(); SOAPFactory soapFactory = SOAPFactory.newInstance();

これらのツールを使用すると、不動産業者のクライアントがポータルWebサイトにリストの更新を送信するために使用するSOAPメッセージを作成できます。

SAAJは、新しいSOAPメッセージを作成するいくつかの方法を提供します。次の例は、エンベロープとそのエンベロープ内のヘッダーと本文を含む空のSOAPメッセージを作成する最も簡単な方法を示しています。このメッセージにはSOAPヘッダーは必要ないため、メッセージからその要素を削除できます。

SOAPMessageメッセージ= factory.createMessage(); SOAPHeaderヘッダー= message.getSOAPHeader(); header.detachNode();

XML構造をメッセージ本文に追加するのは簡単です。

SOAPBody body = message.getSOAPBody();名前listingElementName = soapFactory.createName( "propertyListing"、 "realProperty"、 "//schemas.realhouses.com/listingSubmission"); SOAPBodyElement ListingElement = body.addBodyElement(listingElementName);名前attname = soapFactory.createName( "id"); ListingElement.addAttribute(attname、 "property_1234"); SOAPElement ListingAgency = ListingElement.addChildElement( "listingAgency"); ListingAgency.addTextNode( "Really Nice Homes、Inc"); SOAPElement ListingType = ListingElement.addChildElement( "listingType"); ListingType.addTextNode( "add"); SOAPElement propertyAddress = ListingElement.addChildElement( "propertyAddress"); SOAPElement street = propertyAddress.addChildElement( "street"); street.addTextNode( "1234 Main St "); SOAPElement city = propertyAddress.addChildElement(" city "); city.addTextNode(" Pleasantville "); SOAPElement state = propertyAddress.addChildElement(" state "); state.addTextNode(" CA "); SOAPElement zip = propertyAddress.addChildElement( "zip"); zip.addTextNode( "94521"); SOAPElement listPrice = ListingElement.addChildElement( "listPrice"); listPrice.addTextNode( "25000");addChildElement( "listPrice"); listPrice.addTextNode( "25000");addChildElement( "listPrice"); listPrice.addTextNode( "25000");

プロパティの一意のIDを属性としてpropertyListing要素に追加することに注意してください。さらに、propertyListing要素をQName、または名前空間対応の名前で修飾します。

添付ファイルは、いくつかの方法でSOAPメッセージに追加できます。この例では、最初に、リストされたプロパティの正面画像と内部画像を示す要素を作成します。それぞれに、href添付ファイルのコンテンツIDを指定する属性があります。

String frontImageID = "[email protected]"; SOAPElement frontImRef = ListingElement.addChildElement( "frontImage"); 名前hrefAttName = soapFactory.createName( "href"); frontImRef.addAttribute(hrefAttName、frontImageID); 文字列interiorID = "[email protected]"; SOAPElement internalImRef = ListingElement.addChildElement( "interiorImage"); internalImRef.addAttribute(hrefAttName、interiorID);

必要な画像ファイルをメッセージに簡単に添付するにはjavax.activation.DataHandler、JavaBeans ActivationFrameworkのオブジェクトを使用します。DataHandler渡されたデータ型を自動的に検出できるため、適切なMIMEコンテンツタイプを添付ファイルに自動的に割り当てることができます。

URL url = new URL( "file:///export/files/pic1.jpg"); DataHandler dataHandler = new DataHandler(url); AttachmentPart att = message.createAttachmentPart(dataHandler); att.setContentId(frontImageID); message.addAttachmentPart(att);

または、Object正しいMIMEタイプとともにをに渡すことができる場合もありますcreateAttachmentPart()。その方法は最初の方法に似ています。内部的には、SAAJ実装はDataContentHandler、指定されたMIMEタイプを処理するためにを探す可能性があります。適切なハンドラーが見つからない場合createAttachmentPart()は、IllegalArgumentException:をスローします。

URL url2 = new URL( "file:///export/files/pic2.jpg"); 画像im = Toolkit.getDefaultToolkit()。createImage(url2); AttachmentPart att2 = message.createAttachmentPart(im、 "image / jpeg"); att2.setContentId(interiorID); message.addAttachmentPart(att2);