 |  |
|
난이도 : 중급 Russell Butek, Certified IT Specialist, IBM Nicholas Gallardo, Advisory Software Engineer, IBM
2008 년 1 월 29 일 Java™ API for XML-based RPC (JAX-RPC)는 SOAP with Attachments (Sw/A) 스팩을 지원하고, Java API for XML Web Services (JAX-WS)는 Sw/A와 Message Transmission Optimization Mechanism (MTOM)을 지원합니다. 시리즈 다섯 번째 글에서는 Web Services Description Languages (WSDL)과 매핑된 자바 인터페이스의 샘플을 검토함으로써 두 개의 첨부 파일 모델을 비교합니다.
머리말
JAX-RPC용 첨부 모델은 Sw/A이다. JAX-RPC가 작성된 이후, 새로운 첨부 모델이 등장했는데, 바로 MTOM이다. JAX-WS는 JAX-RPC와 마찬가지로 Sw/A 지원만 제공했지만, MTOM 지원을 추가했다. JAX-WS는 Java Architecture for XML Binding (JAXB) 스팩을 통해 MTOM을 지원하는데, 여기에는 Sw/A와 MTOM 첨부를 정렬(marshalling/unmarshalling)하기 위한 API가 포함된다. 이 글에서, 예제를 통해 두 모델 모두를 검토한다. 주: 이 팁에서는 WSDL과 자바 프로그래밍 모델만 비교한다. 와이어 레벨(wire-level) 메시지를 비교하는 것은 독자 여러분들의 몫으로 남겨두겠다.
JAX-RPC와 Sw/A 예제
Listing 1은 몇 년 전에 작성된 첨부와 관련한 글에서 발췌한 WSDL이다. (참고자료) Listing 2는 자바 인터페이스인데, 이 WSDL로부터 JAX-RPC 매핑이 만들어진다.
Listing 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> |
Listing 2. JAX-RPC Sw/A 자바 인터페이스
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의 자바 인터페이스 매핑은 매우 단순하다:
sendImage 연산의 image/jpeg 부분이 java.awt.Image 매개변수로 매핑된다. sendOctet 연산의 application/octet-stream은 javax.activation.DataHandler 매개변수로 매핑된다. 하지만, 이러한 매핑에 대한 대가가 있다. Multipurpose Internet Mail Extensions (MIME) 유형 정보가 WSDL의 인터페이스 부분(portType, message, types 섹션)에는 없다. MIME 정보를 찾기 위해 바인딩에 발을 담가야 한다. 같은 WSDL 인터페이스에 대한 다른 바인딩은 다른 유형이 되기 때문에, 다른 자바 인터페이스로 매핑 될 수 있다. WSDL 인터페이스에서 자바 인터페이스로 일대일 매핑이라면 더욱 좋다. 한 개 이상의 바인딩을 갖고 있다면, 각각은 하나의 구현으로 매핑되며, 모두 같은 자바 인터페이스를 구현한다.
Sw/A가 가진 두 번째 문제는 document/literal wrapped WSDL의 산업 규약을 따르지 않는다는 점이다. (Listing 1의 WSDL은 rpc/literal WSDL이다.) Sw/A 콘텐트를 document/literal wrapped 메시지는 단일 연산 래퍼 이상의 추가 메시지 부분들을 지정해야 한다.
MTOM이 이러한 문제를 픽스할 수 있을까? 다음 섹션에서 알아보자.
JAX-WS와 MTOM 예제
Listing 3에서, Listing 1의 Sw/A WSDL을 수정하여 똑 같은 MTOM WSDL을 만들었다.
Listing 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>
|
Listing 3의 MTOM WSDL과 Listing 1의 Sw/A WSDL간 유일한 차이는 바인딩이다. MTOM 바인딩에는 MIME 정보가 없다. 사실, WSDL에서 첨부 파일을 다루고 있다고 말할 수 있는 방법이 없다. WSDL의 바인딩은 일반 바인딩처럼 보인다.
Listing 4는 자바 인터페이스인데, 이 WSDL에서 JAX-WS 매핑이 만들어진다.
Listing 4. JAX-WS MTOM 자바 인터페이스
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이기 때문에, 자바 인터페이스도 마찬가지로 이를 반영하고 있다. 일부 base64Binary (또는 hexBinary) 유형의 경우, JAX-WS는 이것을 byte[]의 매개변수로 매핑한다. MTOM에서, 유형의 MIME은 WSDL에서 추출되었고, 콘텐트를 포맷팅 하는 부담은 클라이언트나 서버 런타임에 부과된다.
Sw/A와 MTOM의 비교
JAX-RPC Sw/A 섹션에서는 Sw/A의 두 가지 단점을 언급했다:
- MIME 유형 정보는 WSDL 인터페이스가 아닌, WSDL 바인딩에 있다.
- document/literal wrapped 첨부 WSDL을 만드는 것은 어렵다.
document/literal wrapped 스타일에 대해 알아보자.
document/literal wrapped 스타일과 첨부
Listing 3의 MTOM WSDL을 비교를 위해 rpc/literal WSDL로서 남겨두었다. 하지만, 이 WSDL을 document/literal wrapped WSDL로 전환하는 것은 쉽다. 다음 섹션의 Listing 5는 Listing 3의 WSDL과 똑 같은 document/literal wrapped를 보여주고 있다. (다양한 WSDL 스타일들 간 차이점은 참고자료 섹션 참조)
바인딩에 있는 MIME 유형 정보
MTOM WSDL의 바인딩은 MIME 정보를 갖고 있지 않으므로, 파트 유형을 결정지을 바인딩을 살펴볼 필요가 없다. WSDL 인터페이스에는 자바 인터페이스를 생성하는데 필요한 모든 것이 있다. 하지만, Listing 2와 Listing 4의 자바 인터페이스를 비교해 보면 알겠지만, 일부 정보가 없다.
두 WSDL의 인터페이스 부분은 연산의 데이터 유형이 base64Binary인데, 이것은 byte[]로 매핑된다. JAX-RPC Sw/A WSDL에서는 파트 유형이 MIME 이미지이고 MIME octet 스트림이라는 것을 바인딩으로부터 알 수 있다. JAX-WS MTOM WSDL에는 이 정보가 없다. 안타까운 일이지만, 인터페이스를 완벽히 청소한다는 이점이 있다. 어떤 바인딩이든 간에, 인터페이스는 언제나 같다. 사실, 클라이언트와 서버 코드 베이스 구현자는 매개변수가 첨부인지 여부에 곤란을 겪어서는 안된다. 이것은 단순한 SOAP 메시지의 상세이고, WSDL-자바 매핑 작성자는 SOAP 메시지 상세에서 프로그래머를 분리하기 위해 최선을 다해야 한다.
하지만, 여러분이 MIME 유형이 무엇인지 알고 싶고, 소실된 정보로 가고 싶다면, JAX-WS는 XML 엘리먼트로 투입할 수 있는 애트리뷰트(expectedContentTypes)를 지원한다. 이 특별한 애트리뷰트는 Listing 5에 강조되고 있다. Listing 6는 상응하는 자바 인터페이스를 보여준다. 주석을 무시하면, 이 자바 인터페이스는 Listing 2의 인터페이스와도 같다.
Listing 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 인터페이스 안에 모두 저장된다. 바인딩 안에 없기 때문에, 모든 유형 정보가 여러분이 원하는 곳에 있다.
Listing 6. MIME 애트리뷰트에서 매핑된 JAX-WS 자바 인터페이스
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는 JAXB에 의존하여 대부분의 웹 서비스 콘텐트용 데이터 바인딩을 핸들한다. expectedContentTypes 엘리먼트용 매핑은 JAXB 2.0 스팩의 Appendix H에 정의된다. (참고자료) JAXB 2.0 매핑은 JAX-RPC 매핑과 비슷하다. 표 1에 매핑을 비교했다.
표 1. MIME 유형과 자바 유형 매핑
| 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 |
|---|
| all other types | javax.activation.DataHandler | javax.activation.DataHandler |
|---|
enabling/disabling 첨부 지원
MTOM의 또 다른 혜택 중 하나는 켜고 끌 수 있다는 점이다. Sw/A의 경우, 한 쪽 또는 다른 쪽이 Sw/A 첨부 보내기를 지원하지 않는다면, WSDL에 의해 정의된 콘트랙트는 인정될 수 없다. 한편, Listing 3 또는 5에 있는 것 같은 MTOM WSDL을 갖고 있다면, 클라이언트는 SOAP 메시지에 MTOM 첨부 또는 인라인으로 데이터를 보낼 수 있다. 클라이언트가 무엇을 선택하든지, 웹 서비스와 인터랙팅 할 수 있다. MTOM은 Sw/A처럼 의무적인 것이 아니라 콘텐트 보내기의 최적화일 뿐이다.
Sw/A와 JAX-WS
JAX-WS는 여전히 Sw/A 모델을 지원한다. 기본적으로, JAX-WS는 Sw/A 첨부를 자바 인터페이스의 byte[]로 매핑한다. (Listing 4) JAX-RPC에서 했던 것과 같은 매핑을 얻으려면, enableMIMEContent WSDL 바인딩 정의를 사용한다. (자세한 내용은 JAX-WS 스팩 section 8.7.5를 참조하라.) Listing 7은 Listing 2의 JAX-RPC 버전 인터페이스와 똑 같은 JAX-WS 버전의 자바 인터페이스이다.
Listing 7. mime:content에서 매핑된 Sw/A 첨부를 가진 JAX-WS 자바 인터페이스
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보다 향상되었다:
- 자바 인터페이스를 생성하는데 필요한 모든 것을 이제 WSDL 인터페이스에서 사용할 수 있다.
- MTOM은 document/literal wrapped WSDL에서 사용할 수 있다.
- MTOM은 첨부의 최적화를 적용하지만, Sw/A가 했던 것 같은 첨부를 실행하지는 않는다.
참고자료 교육
제품 및 기술 얻기
토론
필자소개  | |  | Russell Butek은 IBM의 SOA 및 웹 서비스 컨설턴트이다. 한때는 IBM WebSphere 웹 서비스 엔진 개발자로서, 또한 JAX-RPC Java Specification Request (JSR) 전문가 그룹의 멤버로 활동했었다. Apache의 AXIS SOAP 엔진 구현에도 참여했다. |
 | |  | Nick Gallardo는 IBM 소프트웨어 엔지니어이다. 웹 서비스의 다양한 측면들을 연구하고 있다. 최근에는 JAX-WS 지원도 하고 있다. 이전에는, WebSphere와 Tivoli 플랫폼에서 작업했다. |
기사에 대한 평가
|  |