目次


Web サービス・プログラミングのヒントと秘訣: WS-I の wsi:swaRef XML タイプを使用したアタッチメント (添付)

Comments

はじめに

IBM developerWorks では、Web サービス・アタッチメントに送信するためのさまざまなアプローチを記載した記事を提供しています (リンク先は、「参考文献」セクションを参照してください)。 この記事ではさらに、別のメカニズムである、WS-I (Web Service Interoperability) organization のアタッチメント参照タイプ (wsi:swaRef.) 付きの SOAP についても言及します。

なぜ wsi:swaRef か?

アタッチメントに XML タイプが存在しなかったため、WS-I によって作成されました。 WSDL の仕様にはアタッチメントの定義が含まれていますが、以下のいくつかの理由のために、その基準を満たすものではありません。

  • アタッチメントがインターフェースの中で可視でない
  • メッセージ部分しかアタッチメントに含められない
  • アタッチメントと document/literal wrapped がうまくミックスしない

アタッチメントがインターフェースの中で可視でない

アタッチメントは SOAP で定義され、WSDLの仕様では、SOAP アタッチメントを WSDL バインディングにマップします。 このことは、WSDL ドキュメントのインターフェース部分 ( portType, messages, types ) は、アタッチメントを認識しないことを意味します。

例えばリスト1 を見てください。このリストは、記事「Web サービス・プログラミングのヒントと秘訣: JAX-RPC で SOAP 添付」(「参考文献」セクションを参照) からのものです。 バインディングを無視して WSDL のインターフェースだけに注目すると、sendImage と sendOctet という 2 つの操作があることがわかります。 どちらも hexBinary 型の入力があります。 JAX-RPC は、hexBinary 型を Java の byte[] 型にマップします。 この情報だけによれば、この WSDL インターフェースは、 byte[] 型のパラメーターを 1 つ持つ 2 つのメソッドがある Java インタフェースにマップしていると推測するのは当然のことです。 これは良い推測であり、MIME タイプを除けば、正しいことです。 しかし、MIME タイプの場合、実際のパラメーター・タイプを判別するには、バインディングを検査する必要があります。 バインディングでは、操作の入力は、実際には、hexBinary ではなく、MIME コンテンツ・タイプ (image/jpeg および application/octet-stream) であることがわかります。 JAX-RPC は、これらを java.awt.Image と javax.activation.DataHandler にそれぞれマップします。

アタッチメントの場合、WSDL インターフェースでは、Java インターフェースを決定するのに十分ではありません。 これは不幸なことです。 インターフェースとインプリメンテーションの間の境界線がぼやけてしまいます。

リスト1. WS-I の wsi:swaRef の前にアタッチメントがある WSDL
<definitions
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
    targetNamespace="urn:attachment.tip"
    xmlns:tns="urn:attachment.tip">
  <message name="empty"/>
  <message name="imageMsg">
    <part name="image" type="xsd:hexBinary"/>
  </message>
  <message name="octetMsg">
    <part name="octet" type="xsd:hexBinary"/>
  </message>

  <portType name="AttachmentTip">
    <operation name="sendImage">
      <input message="tns:imageMsg"/>
      <output message="tns:empty"/>
    </operation>
    <operation name="sendOctet">
      <input message="tns:octetMsg"/>
      <output message="tns:empty"/>
    </operation>
  </portType>

  <binding name="AttachmentBinding" type="tns:AttachmentTip">
    <soap:binding style="rpc"
                  transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="sendImage">
      <soap:operation soapAction=""/>
      <input>
        <mime:multipartRelated>
          <mime:part>
            <soap:body use="literal"/>
          </mime:part>
          <mime:part>
            <mime:content part="image" type="image/jpeg"/>
          </mime:part>
        </mime:multipartRelated>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
    <operation name="sendOctet">
      <soap:operation soapAction=""/>
      <input>
        <mime:multipartRelated>
          <mime:part>
            <soap:body use="literal"/>
          </mime:part>
          <mime:part>
            <mime:content part="octet" type="application/octet-stream"/>
          </mime:part>
        </mime:multipartRelated>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>

  <service name="AttachmentService">
    <port name="AttachmentTip" binding="tns:AttachmentBinding">
      <soap:address
          location="http://localhost:9080/attachment/services/AttachmentTip"/>
    </port>
  </service>

</definitions>

メッセージ部分しかアタッチメントに含められない

リスト1 では、バインディングは、MIME タイプをメッセージ部分に関連付けていることに注目してください。 これは、すべてのアタッチメントがパーツでなければならず、アタッチメントが、例えば complexType のエレメントであると定義することはできません。 これは、アタッチメントの有用性を非常に制限し、過小評価するものです。

アタッチメントと document/literal wrapped パターン

3 番目の問題は、アタッチメントが、WSDL の document/literal wrapped パターンに対する現在の業界の傾向とうまくフィットしないというものです。 「参考文献」セクションの中でリンクされている記事「Which style of WSDL should I use?」に、この wrapped パターンが解説されています。 一部の人は、アタッチメントが document/literal wrapped パターンにフィットすることはまったくないと信じています。 これに対して異論は唱えませんが、筆者の考えとは無関係に、これらをフィットさせることを試みている仕様はありません。

問題は、document/literal wrapped パターンでは、メッセージ内に 1 つのパートしか可能ではなく、そのパートがラッパー・エレメントを参照していなければならないことです。 アタッチメント・パートをこのモデルにフィットさせる方法はあるのでしょうか。 それはありません。 1 つのメッセージ内に入れられる定義を緩和すればフィットさせることができますが、この緩和を公式化することを試みた人はだれもいません。

WS-I のソリューション

WS-I では、XML アタッチメント・タイプを作成することによって、これらの問題をすべて緩和しています。 wsi:swaRef は、WSDL 「インターフェース」では可視です。 wsi:swaRef の場所はメッセージ・パートに制限されておらず、complexType のエレメントであることが可能です。 1 つの XML タイプとして、wsi:swaRef は document/literal wrapped パターンにうまくフィットします。このためには、パラメーターが complexType のエレメントであることが必要であり、リスト2 では、リスト1 を変更して標準アタッチメントを wsi:swaRef で置き換えています。 また、リスト2 の WSDL を document/literal wrapped の WSDL に変えていることにも注目してください。

リスト2. WS-I の wsi:swaRef アタッチメント・タイプを持つ WSDL
<definitions
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    targetNamespace="urn:attachment.tip"
    xmlns:tns="urn:attachment.tip">
  <types>
    <schema
        targetNamespace="urn:attachment.tip"
        xmlns:tns="urn:attachment.tip"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:wsi="http://ws-i.org/profiles/basic/1.1/xsd">
      <import
          namespace="http://ws-i.org/profiles/basic/1.1/xsd"
          schemaLocation="http://ws-i.org/profiles/basic/1.1/xsd"/>
      <element name="sendImage">
        <complexType>
          <sequence>
            <element name="image" type="wsi:swaRef"/>
          </sequence>
        </complexType>
      </element>
      <element name="sendImageResponse">
        <complexType>
          <sequence/>
        </complexType>
      </element>
      <element name="sendOctet">
        <complexType>
          <sequence>
            <element name="octet" type="wsi:swaRef"/>
          </sequence>
        </complexType>
      </element>
      <element name="sendOctetResponse">
        <complexType>
          <sequence/>
        </complexType>
      </element>
    </schema>
  </types>
  <message name="imageMsg">
    <part name="parameters" element="tns:sendImage"/>
  </message>
  <message name="imageResponseMsg">
    <part name="return" element="tns:sendImageResponse"/>
  </message>
  <message name="octetMsg">
    <part name="parameters" element="tns:sendOctet"/>
  </message>
  <message name="octetResponseMsg">
    <part name="return" element="tns:sendOctetResponse"/>
  </message>

  <portType name="AttachmentTip">
    <operation name="sendImage">
      <input message="tns:imageMsg"/>
      <output message="tns:imageResponseMsg"/>
    </operation>
    <operation name="sendOctet">
      <input message="tns:octetMsg"/>
      <output message="tns:octetResponseMsg"/>
    </operation>
  </portType>

  <binding name="AttachmentBinding" type="tns:AttachmentTip">
    <soap:binding style="document"
                  transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="sendImage">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
    <operation name="sendOctet">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>

  <service name="AttachmentService">
    <port name="AttachmentTip" binding="tns:AttachmentBinding">
      <soap:address
          location="http://localhost:9080/attachment/services/AttachmentTip"/>
    </port>
  </service>

</definitions>

リスト2 では、wsi:swaRef が非常に単純に定義されているのがわかります。 他のプリミティブ XML タイプと同様の動作をします。 しかし、著者の意見としては、これはあまりに単純すぎます。 標準のアタッチメントと違って、アタッチメントの MIME タイプがわかりません。 わかっているのは、アタッチメントが 1 つあるということだけです。 例えば MIME タイプを提供する属性を持った wsi:swaRef が WS-I に定義されていれば便利ですが、WS-I は、仕様を定義する任務を持っておらず、それらの仕様を明確にするだけです。そのため、WS-I は、実際に新しいものを定義するときには、それを最小にしておくことを好みます。

wsi:swaRef と SOAP

リスト2 は、wsi:swaRef が WSDL 定義の中でどのように見えるかを示したものです。 リスト3 はサンプルの SOAP 要求メッセージを示したものです。 これは、リスト2 で WSDL に定義されたサービスの sendImage 操作のメッセージです。リスト内の強調表示された項目から、イメージの wsi:swaRef パラメーターが、実際のイメージ・データのコンテンツ ID とどのように関連しているかが分かります。 通常のアタッチメント・メッセージ付き SOAP とは正確には同じではありませんが、その考え方は似ています。 「参考文献」セクションの記事「ヒント: Web サービスにファイルを渡す」に、アタッチメント・メッセージ付きの SOAP の例が提供されています。

リスト3. wsi:swaRefデータ付きの SOAP メッセージ
 ------=_Part_0_1245231543.1147796620031
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: binary
Content-Id: <89884062647.1147796620016.IBM.WEBSERVICES@ISSW>

<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Header/>
  <soapenv:Body>
   <p985:sendImage xmlns:p985="urn:attachment.tip">
    <image>cid:image=881207433652.1147796619984.IBM.WEBSERVICES@ISSW</image>
   </p985:sendImage>
  </soapenv:Body>
</soapenv:Envelope>
------=_Part_0_1245231543.1147796620031
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
Content-Id: <image=881207433652.1147796619984.IBM.WEBSERVICES@ISSW>

... binary image data ...

wsi:swaRef と Java

これまで、wsi:swaRef の宣言について、そして SOAP メッセージの中の wsi:swaRef のインスタンスについて見てきました。 考慮すべき最後のことは、wsi:swaRef をプログラミング言語にマップする方法です。 筆者は Java ファンなので、Java マッピングで説明することにします。

WS-I は JAX-RPC バージョン 1.1 の仕様が最終決定された後で定義されたので、JAX-RPC はマッピングを提供していません。 しかし、そのヒントは提供してくれます。 WS-I では、未知の MIME タイプは javax.activation.DataHandler にマップされると決められています。wsi:swaRef は実際に未知の MIME タイプであるため、javax.activation.DataHandler にマップされるのは妥当なように思われます。さらに、少し先を見れば、新しい JAX-B 2.0 仕様で実際にこのマッピングが指示されます。 そのため、wsi:swaRef をサポートするどのインプリメンテーションにおいても、wsi:swaRef が javax.activation.DataHandler にマップされるであろうというのは、かなり安全な推測になります。リスト4 では、リスト2 の WSDL 用の Java インターフェースを示しています。

リスト4. wsi:swaRef の Java マッピング
public interface AttachmentTip extends java.rmi.Remote {
  public void sendImage(javax.activation.DataHandler image)
   throws java.rmi.RemoteException;
  public void sendOctet(javax.activation.DataHandler octet)
   throws java.rmi.RemoteException;
}

まとめ

WSDL のアタッチメントの定義にはいくつかの問題があるため、WS-I Organization では、新しいアタッチメント・タイプ wsi:swaRef を作成しました。 これは、標準的な WSDL アタッチメントがするのと似た方法で SOAP メッセージにマップされ、未知の MIME タイプ、すなわち javax.activation.DataHandler として Java にマップされます。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=SOA and web services
ArticleID=245148
ArticleTitle=Web サービス・プログラミングのヒントと秘訣: WS-I の wsi:swaRef XML タイプを使用したアタッチメント (添付)
publish-date=06272006