![](http://www.ibm.com/i/c.gif) |
난이도 : 중급
Russell Butek, 소프트웨어 엔지니어, IBM
2004 년 2 월 27 일
JAX-RPC는 SOAP with attachments를 지원한다. JAX-RPC API를 사용하여 MIME attachments를 보내는 방법을 이 글에서 설명한다.
SOAP 메시징 프로토콜은 SOAP 메시지들을 통해 MIME attachments를 보낼 수 있도록 한다. WSDL은 이 attachment의 디스크립션을 제공한다. JAX-RPC는 attachment의 WSDL 디스크립션을 자바로 매핑한다. 이 글에서 JAX-RPC 매핑을 사용하여 SOAP 메시지에서 attachment를 보내는 방법을 설명한다.
WSDL
attachment의 WSDL 디스크립션은 그다지 단순하지가 않다. Listing 1의 WSDL을 보자.
Listing 1. WSDL with attachments
<?xml version="1.0" encoding="utf-8"?>
<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>
|
![](http://www.ibm.com/i/c.gif) |
WS-I와 attachments
MIME 유형은 WSDL의 '인터페이스'로 정의될 수 없다. WS-I organization (참고자료)은 모든 MIME 유형을 위한 새로운 XML 유형을 도입하여 부분적이라도 이러한 단점을 보완을 시도하고 있다: wsi:swaRef. 이 글을 쓰는 당시에는 이 유형은 작업중에 있었으며 표준화된 자바 바인딩이 존재하지 않았음을 밝힌다.
| |
우선 기억해야 할 것은 항상 바인딩에 대처하기 전까지는 어떤 MIME 정보도 없다는 것이다. 한 순간이라도 바인딩을 무시하고 WSDL의 '인터페이스'(portType과 메시지)만을 본다면 두 개의 오퍼레이션인 sendImage 와 sendOctet 를 보게 될 것이다. 이들 각각은 hexBinary 인풋을 갖고 있다. hexBinary 는 byte[] 로 매핑한다. 단지 이 정보만을 이용하여 이 portType이 Java language Service Endpoint Interface (SEI)로 매핑되는 것을 짐직할 수 있다. 이것은 두 개의 메소드를 갖고 있는데 각각 하나의 byte[] 매개변수를 갖고있다. 이는 MIME 유형을 제외한 모든 것에 알맞은 생각이다. 하지만 MIME 유형의 경우 실제 매개변수 유형을 결정하려면 바인딩을 살펴보아야한다.
바인딩에서 오퍼레이션용 인풋이 실제로 MIME 콘텐트 유형인 image/jpeg 와 application/octet-stream 이라는 것을 알 수 있다. hexBinary 가 아니다. JAX-RPC는 이들을 java.awt.Image 와 javax.activation.DataHandler 에 매핑하도록 정의한다.
Service Endpoint Interface
Listing 2에는 Listing 1의 WSDL에서 만들어진 Java language SEI가 포함되어 있다.
Listing 2. AttachmentTip SEI
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 오퍼페이션은 java.awt.Image 매개변수를 이용하여 자바 프로그램 메소드가 된다. 매우 단순하고 깔끔하다. 표 1은 MIME 유형을 자바 유형으로 매핑한 리스트이다.
표 1 - JAX-RPC 매핑
MIME Type |
Java Type |
image/gif, image/jpeg |
java.awt.Image |
text/plain |
java.lang.String |
multipart/* |
javax.mail.internet.MimeMultipart |
text/xml, application/xml |
javax.xml.transform.Source |
클라이언트 구현
JAX-RPC 구현을 사용하여 AttachmentTip WSDL에서 모든 클라이언트 쪽 매핑을 만든다고 가정한다. 클라이언트 구현은 이 매핑에 의존할 것이고 특히 Listing 2의 AttachmentTip SEI를 의존한다.
attachments의 클라이언트 구현은 우선 Service에서 SEI의 구현을 얻는 것으로 시작한다.(Listing 3).
sendImage 메소드 호출하기
SEI 구현을 갖게 되면 attachment로 이 메소드를 호출할 수 있다. sendImage 의 경우, 이 attachment는 java.awt.Image 이다. 이 뿐이다. JAX-RPC 구현은 모든 이미지가 attachment로서 보내지는 것을 알고 있고 이에 따라 SOAP 메시지를 만든다. 클라이언트 프로그래머는 attachment가 개입되었는지를 알 필요가 없다. (Listing 3).
Listing 3. AttachmentTip 클라이언트 구현과 sendImage 호출
package tip.attachment;
import java.awt.Image;
import java.awt.Toolkit;
import java.net.URL;
import java.rmi.RemoteException;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
public class AttachmentTipClient {
static AttachmentTip getTip() throws Exception {
QName serviceName = new QName(
"urn:attachment.tip",
"AttachmentService");
URL wsdlLocation = new URL(
"http://localhost:9080/attachment/services/AttachmentTip?wsdl");
ServiceFactory factory = ServiceFactory.newInstance();
Service service = factory.createService(wsdlLocation, serviceName);
QName portName = new QName("", "AttachmentTip");
return (AttachmentTip) service.getPort(
portName,
AttachmentTip.class);
}
static void sendImage(AttachmentTip tip, String fileName)
throws RemoteException {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.createImage(fileName);
tip.sendImage(image);
}
public static void main(String[] args) {
try {
AttachmentTip tip = getTip();
sendImage(tip, args[0]);
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
|
sendOctet 메소드 호출하기
![](http://www.ibm.com/i/c.gif) |
비 지정 MIME 유형을 매핑할 때 유의할 점
JAX-RPC는 표 1에 나타나지 않은 MIME 유형을 지원하는 구현을 필요로하지 않는다. 구현은 비 지정 MIME 유형을 DataHandler 로 매핑하지 않을 수도 있다. 예를 들어, WebSphere 웹 서비스는 Application Server 6.0 버전이 나오기 전까지는 이 매핑을 지원하지 않는다.
| |
JAX-RPC가 매핑을 정의한 몇 가지 MIME 유형이 있다는 것은 다행이다. (표 1 참조). For those MIME types for which there is no explicit 뚜렷한 JAX-RPC 매핑이 없는 MIME 유형의 경우 javax.activation.DataHandler 객체와 함께 남아있다. 이 클래스는 Java Activation Framework (JAF -- 참고자료)의 일부이다. 따라서 JAF에 대해 알아야한다. 그다지 어렵지 않다. DataHandler 에는 javax.activation.DataSource 가 포함되어 있고 인풋과 아웃풋 스트림이 포함되어 있다. 대부분의 자바 프로그래밍 유형은 이 스트림에서 매우 쉽게 변환된다. 게다가 활성화 프레임웍도 도움이 된다. attachment 데이터가 파일에 있으면 활성화 프레이웍은 javax.activation.FileDataSource 클래스를 제공하고 따라서 스트림 단계를 우회할 수 있다.(Listing 4) .
Listing 4. 완전한 AttachmentTip 클라이언트 구현
package tip.attachment;
import java.awt.Image;
import java.awt.Toolkit;
import java.net.URL;
import java.rmi.RemoteException;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
public class AttachmentTipClient {
static AttachmentTip getTip() throws Exception {
QName serviceName = new QName(
"urn:attachment.tip",
"AttachmentService");
URL wsdlLocation = new URL(
"http://localhost:9080/attachment/services/AttachmentTip?wsdl");
ServiceFactory factory = ServiceFactory.newInstance();
Service service = factory.createService(wsdlLocation, serviceName);
QName portName = new QName("", "AttachmentTip");
return (AttachmentTip) service.getPort(
portName,
AttachmentTip.class);
}
static void sendImage(AttachmentTip tip, String fileName)
throws RemoteException {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.createImage(fileName);
tip.sendImage(image);
}
static void sendOctet(AttachmentTip tip, String fileName)
throws RemoteException {
FileDataSource fds = new FileDataSource(fileName);
DataHandler dh = new DataHandler(fds);
tip.sendOctet(dh);
}
public static void main(String[] args) {
try {
AttachmentTip tip = getTip();
sendImage(tip, args[0]);
sendOctet(tip, args[0]);
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
|
두 개의 attachment 작동에 대한 데이터로 같은 파일을 사용했지만 어디까지나 이것은 sendOctet 에 한해서였다는 것을 기억하라. 이를 고려하지 않는다면 상상에 맡기겠다. application/octet-stream 은 FileDataSource 용 디폴트 콘텐트 유형이다. 이것이 바로 내가 이를 사용한 이유이다. 파일에 데이터를 갖고 있지 않다면 application/octet-stream 말고 다른 것으로 보내야한다. DataSource 의 구현을 만들어야 하지만 이는 간단한 인터페이스이기 때문에 많은 노력이 필요하지는 않다.
참고자료
필자소개
![](http://www.ibm.com/i/c.gif) |
|
Russell Butek: IBM WebSphere Web services engine 개발자. IBM JAX-RPC Java Specification Request (JSR) 전문가 그룹 대표. |
- 출처 : http://www.ibm.com/developerworks/kr/webservices/library/ws-tip-soapjax.html#N100EA - |