レベル: 中級 Russell Butek (butek@us.ibm.com), Certified IT Specialist, IBM Nicholas Gallardo (nlgallar@us.ibm.com), Advisory Software Engineer, IBM
2007年 11月 15日 JAX-RPC (Java™ API for XML-based RPC) は Sw/A (SOAP with Attachments) 仕様をサポートしていますが、JAX-WS (Java API for XML Web Services) は Sw/A と共に、新しい MTOM (Message Transmission Optimization Mechanism) 仕様もサポートしています。このシリーズの 5 回目である今回はこの 2 つの添付モデルを比較し、WSDL (Web Services Description Language) の例と、マッピングされた Java インターフェースの例を検証します。
はじめに
JAX-RPC の添付モデルは Sw/A ですが、JAX-RPC が作成されて以来初めての新しい添付モデルが登場しました。それが MTOM です。JAX-WS は JAX-RPC 同様 Sw/A をサポートしていますが、MTOM のサポートも追加しています。JAX-WS は JAXB (Java Architecture for XML Binding) 仕様によって MTOM をサポートしており、JAXB 仕様には Sw/A と MTOM の両方の添付をマーシャリングおよびアンマーシャリングするための API が含まれています。このヒントでは、この両方の添付モデルを、例を通して検証します。注意: このヒントでは、WSDL と Java プログラミング・モデルのみを比較します。ワイヤー・レベルのメッセージの比較は読者への課題とします。
JAX-RPC と Sw/A の例
リスト 1 は、数年前に書かれた、添付に関するヒントの記事から引用した WSDL を示しています (「参考文献」を参照)。リスト 2 は、この WSDL から JAX-RPC マッピングによって作成される Java インターフェースを示しています。
リスト 1. JAX-RPC での、Sw/A による WSDL
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://attachment.tip/">
<types/>
<message name="sendImage">
<part name="image" type="xsd:base64Binary"/>
</message>
<message name="sendImageResponse"/>
<message name="sendOctet">
<part name="octet" type="xsd:base64Binary"/>
</message>
<message name="sendOctetResponse"/>
<portType name="AttachmentTip">
<operation name="sendImage">
<input message="tns:sendImage"/>
<output message="tns:sendImageResponse"/>
</operation>
<operation name="sendOctet">
<input message="tns:sendOctet"/>
<output message="tns:sendOctetResponse"/>
</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 parts="" namespace="http://attachment.tip/" use="literal"/>
</mime:part>
<mime:part>
<mime:content part="image" type="image/jpeg"/>
</mime:part>
</mime:multipartRelated>
</input>
<output>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</output>
</operation>
<operation name="sendOctet">
<soap:operation soapAction=""/>
<input>
<mime:multipartRelated>
<mime:part>
<soap:body parts="" namespace="http://attachment.tip/" use="literal"/>
</mime:part>
<mime:part>
<mime:content part="octet" type="application/octet-stream"/>
</mime:part>
</mime:multipartRelated>
</input>
<output>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</output>
</operation>
</binding>
<service name="AttachmentService">
<port binding="tns:AttachmentBinding" name="AttachmentTip">
<soap:address location="http://localhost:9080/SwAService/services/AttachmentTip"/>
</port>
</service>
</definitions> |
リスト 2. JAX-RPC での、Sw/A による Java インターフェース
package tip.attachment;
import java.awt.Image;
import java.rmi.Remote;
import java.rmi.RemoteException;
import javax.activation.DataHandler;
public interface AttachmentTip extends Remote {
public void sendImage(Image image) throws RemoteException;
public void sendOctet(DataHandler octet) throws RemoteException;
}
|
この WSDL からの Java インターフェース・マッピングは非常に単純です。sendImage 操作の image/jpeg 部分は java.awt.Image パラメーターにマッピングされ、sendOctet 操作の application/octet-stream は javax.activation.DataHandler パラメーターにマッピングされます。しかし、このマッピングにはコストがかかります。WSDL のインターフェース部分 (portType、message、types セクション) には MIME (Multipurpose Internet Mail Extensions) タイプの情報が含まれていないため、バインディングの中を調べて MIME 情報を見つける必要があるからです。これは残念なことです。同じ WSDL インターフェースであってもバインディングが異なれば、型も別になり、異なる Java インターフェースにマッピングされる可能性があるからです。WSDL インターフェースから Java インターフェースへのマッピングは 1 対 1 の方が望ましく、複数のバインディングがある場合でも、それぞれのバインディングは 1 つの実装にマッピングされ、それらのバインディングのすべてから同じ Java インターフェースが実装されます。しかし Sw/A では、そうすることはできません。WSDL から Java インターフェースへのマッピングが 1 対 1 ではないからです。
Sw/A での、もう 1 つの問題は、document/literal でラップされた WSDL に関する業界の慣習に Sw/A がうまく合わないことです (リスト 1 の WSDL が rpc/literal WSDL であることに注意してください)。document/literal でラップされたメッセージに Sw/A コンテンツを追加するためには、1 つの操作ラッパーに加えて、さらにメッセージ部分を指定する必要があります。
MTOM は、こうした問題には対応しているのでしょうか。次のセクションでそれを調べてみましょう。
JAX-WS と MTOM の例
リスト 3 では、リスト 1 の Sw/A による WSDL を変更し、これと等価な、MTOM による WSDL を作成しています。
リスト 3. JAX-WS での、MTOM による WSDL
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://attachment.tip/">
<types/>
<message name="sendImage">
<part name="image" type="xsd:base64Binary"/>
</message>
<message name="sendImageResponse"/>
<message name="sendOctet">
<part name="octet" type="xsd:base64Binary"/>
</message>
<message name="sendOctetResponse"/>
<portType name="AttachmentTip">
<operation name="sendImage">
<input message="tns:sendImage"/>
<output message="tns:sendImageResponse"/>
</operation>
<operation name="sendOctet">
<input message="tns:sendOctet"/>
<output message="tns:sendOctetResponse"/>
</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>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</input>
<output>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</output>
</operation>
<operation name="sendOctet">
<soap:operation soapAction=""/>
<input>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</input>
<output>
<soap:body namespace="http://attachment.tip/" use="literal"/>
</output>
</operation>
</binding>
<service name="AttachmentService">
<port binding="tns:AttachmentBinding" name="AttachmentTip">
<soap:address location="http://localhost:9080/MTOMService/services/AttachmentTip"/>
</port>
</service>
</definitions>
|
リスト 3 の MTOM による WSDL と、リスト 1 の Sw/A による WSDL との唯一の実際の違いは、バインディングです。MTOM バインディングは MIME 情報を含んでいません。実際、添付を処理していることを WSDL から判断することはできず、WSDL のバインディングは通常のバインディングと同じように見えます。
リスト 4 は、この WSDL から JAX-WS マッピングが作成する Java インターフェースを示しています。
リスト 4. JAX-WS での、MTOM による Java インターフェース
package tip.attachment;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface AttachmentTip {
@WebMethod
public void sendImage(
@WebParam(name = "image", partName = "image")
byte[] image);
@WebMethod
public void sendOctet(
@WebParam(name = "octet", partName = "octet")
byte[] octet);
}
|
この WSDL は通常の WSDL と同じように見え、添付を示すものが何もないため、Java インターフェースもそれを反映したものになります。base64Binary 型 (または hexBinary 型) の part が与えられると、JAX-WS はそれを byte[] 型のパラメーターにマッピングします。MTOM では、MIME であることを示す型はすべて WSDL から抜き去られており、コンテンツを適切にフォーマット設定する負荷はクライアント・ランタイムまたはサーバー・ランタイムが負うことになります。
Sw/A と MTOM の比較
JAX-RPC と Sw/A についてのセクションでは、Sw/A の欠点として下記の 2 つを挙げました。
- MIME タイプの情報が WSDL バインディングの中にあり、WSDL インターフェースの中にはない。
- document/literal でラップされた添付 WSDL を作成することが難しい。
まず、document/literal でラップされたスタイルについて説明しましょう。
document/literal でラップされたスタイルと添付
リスト 3 では比較のために、MTOM による WSDL を rpc/literal WSDL のままにしました。しかし、この WSDL を document/literal でラップされた WSDL に変えるのは簡単なことです。次のセクションのリスト 5 は、リスト 3 の WSDL と等価な、document/literal でラップされた WSDL を示しています (さまざまな WSDL のスタイル間の違いについては「参考文献」を参照してください)。
バインディングの中の MIME タイプ情報
MTOM による WSDL のバインディングは MIME 情報を持たないため、part の型を判断するためにバインディングの中を調べる必要はありません。Java インターフェースを生成するために必要なものは、すべて WSDL インターフェースにあります。しかし、リスト 2 とリスト 4 の Java インターフェースを比較するとわかるように、一部の情報は失われています。
両方の WSDL のインターフェース部分から、この操作のデータ型が base64Binary であることがわかります (base64Binary は byte[] にマッピングされます)。JAX-RPC での Sw/A による WSDL では、バインディングから、part の型が MIME タイプの image/jpeg と MIME タイプの application/octet-stream であることがわかります。JAX-WS での MTOM による WSDL では、この情報は失われており、これは悪いことのように思えるかもしれませんが、インターフェースが完全に整うという良い点もあります。バインディングがどうであれ、インターフェースは常に同じになります。実際、クライアントやサーバーのコードベースを実装する人は、パラメーターが添付なのかどうかを気にする必要はありません。パラメーターが添付なのかどうかは、単に SOAP メッセージの詳細情報にすぎません。WSDL から Java へのマッピングを作成した人達は、プログラマーが SOAP メッセージの詳細情報を知らずにすむように抽象化するため最大限の努力をしたのです。
しかし、MIME タイプが何かをどうしても知りたい場合 (例えば失った情報を参照したい場合など) のために、JAX-WS は XML 要素の中に注入できる属性、expectedContentTypes をサポートしています。リスト 5 では、この特別な属性が強調表示されています。リスト 6 は、これに対応する Java インターフェースを示しています。注釈を無視すれば、この Java インターフェースは基本的にリスト 2 のインターフェースと同じです。
リスト 5. JAX-WS での MIME 属性
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://attachment.tip/">
<types>
<xsd:schema
xmlns:tns="http://attachment.tip/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://attachment.tip/">
<xsd:element name="sendImage" type="tns:sendImage"/>
<xsd:complexType name="sendImage">
<xsd:sequence>
<xsd:element
xmlns:ns1="http://www.w3.org/2005/05/xmlmime"
ns1:expectedContentTypes="image/*"
name="image"
type="xsd:base64Binary"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="sendImageResponse" type="tns:sendImageResponse"/>
<xsd:complexType name="sendImageResponse">
<xsd:sequence/>
</xsd:complexType>
<xsd:element name="sendOctet" type="tns:sendOctet"/>
<xsd:complexType name="sendOctet">
<xsd:sequence>
<xsd:element
xmlns:ns1="http://www.w3.org/2005/05/xmlmime"
ns1:expectedContentTypes="application/octet-stream"
name="octet"
type="xsd:base64Binary"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="sendOctetResponse" type="tns:sendOctetResponse"/>
<xsd:complexType name="sendOctetResponse">
<xsd:sequence/>
</xsd:complexType>
</xsd:schema>
</types>
<message name="sendImage">
<part name="parameters" element="tns:sendImage"/>
</message>
<message name="sendImageResponse">
<part name="parameters" element="tns:sendImageResponse"/>
</message>
<message name="sendOctet">
<part name="parameters" element="tns:sendOctet"/>
</message>
<message name="sendOctetResponse">
<part name="parameters" element="tns:sendOctetResponse"/>
</message>
<portType name="AttachmentTip">
<operation name="sendImage">
<input message="tns:sendImage"/>
<output message="tns:sendImageResponse"/>
</operation>
<operation name="sendOctet">
<input message="tns:sendOctet"/>
<output message="tns:sendOctetResponse"/>
</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 binding="tns:AttachmentBinding" name="AttachmentTip">
<soap:address location="http://localhost:9080/MTOMService/services/AttachmentTip"/>
</port>
</service>
</definitions> |
この新しい属性が、完全に WSDL インターフェースの中に含まれていることに注目してください。バインディングの中に含まれているのではありません。そのため、すべての型情報は、あるべきところにあります。
リスト 6. MIME 属性からマッピングされた JAX-WS の Java インターフェース
package tip.attachment;
import java.awt.Image;
import javax.activation.DataHandler;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/")
public interface AttachmentTip {
@WebMethod
@RequestWrapper(localName = "sendImage",
targetNamespace = "http://attachment.tip/",
className = "tip.attachment.SendImage")
@ResponseWrapper(localName = "sendImageResponse",
targetNamespace = "http://attachment.tip/",
className = "tip.attachment.SendImageResponse")
public void sendImage(
@WebParam(name = "image", targetNamespace = "")
Image image);
@WebMethod
@RequestWrapper(localName = "sendOctet",
targetNamespace = "http://attachment.tip/",
className = "tip.attachment.SendOctet")
@ResponseWrapper(localName = "sendOctetResponse",
targetNamespace = "http://attachment.tip/",
className = "tip.attachment.SendOctetResponse")
public void sendOctet(
@WebParam(name = "octet", targetNamespace = "")
DataHandler octet);
}
|
先ほど触れたように、JAX-WS は Web サービスのコンテンツの大部分に関するデータ・バインディングの処理を、JAXB を利用して行います。expectedContentTypes 要素に対するマッピングは JAXB 2.0 仕様の Appendix H に定義されています (「参考文献」を参照)。JAXB 2.0 のマッピングは JAX-RPC のマッピングと似ています。表 1 はこれらのマッピングを比較したものです。
表 1. MIME タイプから Java 型へのマッピング
| MIME タイプ | JAX-RPC でのマッピング | JAX-WS/JAXB でのマッピング |
|---|
| image/gif | java.awt.Image | java.awt.Image |
|---|
| image/jpg | java.awt.Image | java.awt.Image |
|---|
| text/plain | java.lang.String | javax.xml.transform.Source |
|---|
| text/xml | javax.xml.transform.Source | javax.xml.transform.Source |
|---|
| application/xml | javax.xml.transform.Source | javax.xml.transform.Source |
|---|
| multipart/* | javax.mail.internet.MimeMultipart | javax.activation.DataHandler |
|---|
| その他すべてのタイプ | javax.activation.DataHandler | javax.activation.DataHandler |
|---|
添付サポートを有効/無効にする
MTOM のもう 1 つの利点は、オン・オフができるということです。Sw/A の場合には、どちらか一方が Sw/A による添付の送信をサポートしていないと、WSDL で定義される規約を守ることができません。一方、リスト 3 やリスト 5 のような MTOM による WSDL の場合には、クライアントは MTOM 添付としてデータを送信するのか、あるいは SOAP メッセージにインライン化して送信するのかを選択することができます。クライアントは何を選択しても、変わらず Web サービスと対話動作することができます。MTOM はコンテンツの送信を最適化するだけであり、Sw/A のように強制的ではありません。
Sw/A と JAX-WS
JAX-WS も Sw/A モデルをサポートしています。JAX-WS はデフォルトで、リスト 4 の例のように Sw/A による添付を Java インターフェースの byte[] にマッピングします。JAX-RPC で慣れているマッピングを使用するには、WSDL バインディング定義 enableMIMEContent を使用します (詳細については JAX-WS 仕様のセクション 8.7.5 を見てください)。リスト 7 は、リスト 2 の JAX-RPC 版のインターフェースに等価な JAX-WS 版の Java インターフェースを示しています。
リスト 7. mime:content からマッピングされた、Sw/A 添付を持つ JAX-WS 版の Java インターフェース
package tip.attachment;
import java.awt.Image;
import javax.activation.DataHandler;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface AttachmentTip {
@WebMethod
public void sendImage(
@WebParam(name = "image", partName = "image")
Image image);
@WebMethod
public void sendOctet(
@WebParam(name = "octet", partName = "octet")
DataHandler octet);
} |
まとめ
JAX-RPC は Sw/A モデルをサポートしています。JAX-WS も Sw/A をサポートしていますが、さらに強化されて、新しい MTOM モデルもサポートしています。MTOM は下記のいくつかの点で Sw/A よりも改善されています。
- Java インターフェースを作成するために必要なものが、すべて WSDL インターフェースにあります。
- MTOM は document/literal でラップされた WSDL の中で使うことができます。
- MTOM では添付を最適化することができますが、Sw/A のように添付を強制することはありません。
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | |  | Russell Butek は IBM の SOA/Web サービスのコンサルタントです。彼は IBM の WebSphere Web サービス・エンジンの開発者の 1 人であり、JAX-RPC JSR (Java Specification Request) エキスパート・グループのメンバーでもあります。Apache の Axis SOAP エンジンの実装に参加し、Axis 1.0 を JAX-RPC に準拠させるために貢献しました。 |
 | |  | Nick Gallardo は WebSphere プラットフォームに関する業務を行う IBM のソフトウェア・エンジニアです。彼は主にプログラミング・モデルを中心として、Websphere Web サービス・ランタイムのさまざまな側面に関わってきました。彼は Apache Software Foundation のメンバーでもあり、Axis2 コミュニティーの中で JAX-WS に対するサポートを確立するために貢献しました。 |
記事の評価
|