SAAJ(SOAP with Attachments API for Java)는 사용자가 직접 SOAP 메세징 애플리케이션을 작성할 수 있는 API로써, 즉 JAX-RPC API를 대체하는 것이다. SAAJ를 사용하여 메소드를 호출함으로써 사용자는 SOAP 기반 XML 메세지를 읽고 작성할 수 있으며, 인터넷을 통해 이런 타입의 메세지들을 주고받을 수도 있다. 이번 테크팁은 J2EE 1.4 튜토리얼의 Chapter 9: SOAP with Attachments API for Java을 기본으로 작성되었다. SAAJ 메세징이 SOAP 프레임워크에서 작용되는 법을 다룬다. 이번 테크팁에서는 사용자가 이미 SOAP 메세지의 내부 구조에 익숙하다고 가정한다. 익숙하지 않은 사용자라면 SOAP specifications를 먼저 참조하기 바란다.
먼저 알아둬야할 SOAP 메세지는 두가지 타입이 있다. 첨부파일이 있는 메세지/첨부파일이 없는 메세지. 각각의 메세지들은 javax.xml.soap 패키지 안의 클래스들을 활용하며, 첨부파일이 없는 SOAP 메세지가 좀 더 간단하다.
첨부 없는 SOAP
첨부파일이 없는 SOAP 메세지는 SOAP part, SOAP envelope, 선택적으로 SOAP header, SOAP body로 스트럭처가 구성되어 있다.
스트럭처의 각각의 컴포넌트는 물론 전체 SOAP 메세지를 위한 SAAJ 클래스가 있다. javax.xml.soap.SOAPMessage 클래스는 SOAP 메세지를 나타내고, javax.xml.soap.SOAPPart는 SOAP part, javax.xml.soap.SOAPEnvelope 인터페이스는 SOAP envelope을 나타내는 식이다. 새로운 SOAPMessage 오브젝트를 생성하면 SOAP 메세지 안에 필요한 모든 서브클래스들이 자동적으로 생성된다. 예를 들어 새로운 SOAPMessage 오브젝트를 생성하면, 새로운 오브젝트는 SOAPPart를 가지고, 차례로 SOAPEnvelope 오브젝트 생성한다. 그러면 SOAPEnvelope 오브젝트는 자동적으로 빈 SOAPHeader 오브젝트를 생성하고, 그 다음 빈 SOAPBody 오브젝트를 생성한다.
SOAPHeader 오브젝트는 메세지의 메타데이터를 포함하는 하나이상의 header를 생성할 수 있다(ex.송수신 부분에 대한 정보). 그러나, SOAPHeader 오브젝트는 선택사항이다. 디폴트로는 생성되나, 필요없는 경우 삭제할 수 있다.
언제나 SOAPHeader에 뒤따라 생성되는 SOAPBody 오브젝트는 메세지 컨텐츠를 포함한다. SOAP 메세지 스트럭처에 포함될 수 있는 또다른 오브젝트는 SOAPFault 오브젝트이다. 이 오브젝트에는 에러, 상태 정보가 담겨져 있다. SOAPFault는 반드시 SOAPBody 안에 생성된다.
첨부 있는 SOAP 메세지
SOAP 메세지에는 SOAP part에 덧붙여 하나 이상의 첨부파일이 포함될 수 있다. SOAP part에는 반드시 XML 컨텐츠만 포함될 수 있다. 따라서, XML형식이 아닌 컨텐츠는 첨부부분에 담겨져야한다. 예를 들어 SOAP 메세지에 바이너리 파일을 포함시키고 싶으면, 메세지에는 반드시 이를 위한 첨부부분이 있어야한다. 첨부 부분은 모든 형식의 컨텐츠를 담을 수 있으며, XML 형식도 물론 가능하다.
SAAJ에서는 javax.xml.soap.AttachmentPart 클래스로 SOAP 메세지의 첨부부분을 나타낸다. SOAPMessage 오브젝트가 하나 이상의 첨부를 갖고 있다면 각각의 AttachmentPart 오브젝트에는 반드시 각각의 첨부에 포함되는 데이터의 타입을 가리키는 MIME header가 있어야한다. AttachmentPart 오브젝트에는 또한 첨부를 분별하거나 첨부의 위치를 가리키는 추가적인 MIME header도 가질 수 있다. 이런 header들은 선택사항이지만, 여러개의 첨부파일이 있을 때 유용하다. SOAPMessage 오브젝트가 하나 이상의 AttachmentPart 오브젝트를 가질 때, SOAPPart 오브젝트는 메세지 컨텐츠를 포함하거나 포함하지 않을 수 있다.
간단한 SOAP 메세지 생성 & 전송하기
SOAP 메세지를 생성하는 첫번째 단계는 MessageFactory 오브젝트의 정적 newInstance() 메소드를 실행하는 것이다. SAAJ는 MessageFactory를 디폴트로 구현하여 클래스의 인스턴스를 얻기 쉽게 한다. 다음의 코드는 디폴트 메세지 팩토리의 인스턴스를 얻어 메세지를 생성하는 것을 보여준다.
SOAPMessageFactory messageFactory =
MessageFactory.newInstance();
SOAPMessage message = messageFactory.createMessage();
SOAPHeader header = message.getSOAPHeader();
SOAPBody body = message.getSOAPBody();
위의 코드는 다음의 XML 메세지를 생성한다.
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
. . .
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
다음 단계는 body에 컨텐츠를 추가하는 것이다.
Name bodyName = soapFactory.createName("GetLastTradePrice",
"m", "http://wombat.ztrade.com");
SOAPBodyElement bodyElement = body.addBodyElement(bodyName);
다음은 생성된 XML 이다.
<m:GetLastTradePrice
xmlns:m="http://wombat.ztrade.com">
. . . .
</m:GetLastTradePrice>
이 경우, GetLastTradePrice는 로컬 이름의 요소이고 m은 namespace의 접두사, http://wombat.ztrade.com은 namespace URI 이다. 이제 몇가지 세부사항을 GetLastTradePrice 요소에 추가해보자.
Name name = soapFactory.createName("symbol");
SOAPElement symbol = bodyElement.addChildElement(name);
symbol.addTextNode("SUNW");
다음은 이에 따라 생성된 XML 이다.
<symbol>SUNW</symbol>
커넥션
모든 SOAP 메세지는 커넥션(connection)으로 발송/수신 된다. SAAJ에서는 SOAPConnection 오브젝트로 커넥션을 나타낸다. SOAPConnection 오브젝트가 나타내는 커넥션은 발송자로부터 바로 수신자에게 전달된다(일반적으로 HTTP Post 이용). 이런 형태의 커넥션은 한쪽끝에서 다른 쪽끝으로 일방향적으로 전달되기 때문에 점 대 점(point-to-point) 커넥션이라고 부른다. SAAJ를 이용하여 발송되는 일반적인 메세지는 요청에 대한 반응 메세지(request-response 메세지)이다. 이런 형태의 메세지는 SOAPConnection 오브젝트를 통해 발송되며, call() 메소드(요청)를 사용한다. 이 요청은 답변이 수신(반응)될 때까지 블록되어 있는다.
간단한 예제를 보자. 다음의 코드는 SOAPConnection 오브젝트 커넥션을 생성하고, 메세지를 생성, 정착시키며, 커넥션 오브젝트를 이용하여 그 메세지를 전달한다.
SOAPConnectionFactory factory =
SOAPConnectionFactory.newInstance();
SOAPConnection connection = factory.createConnection();
// create a SOAP request message and give it content
java.net.URL endpoint =
new URL("http://fabulous.com/gizmo/order");
SOAPMessage response = connection.call(request, endpoint);
The second argument to the call() method identifies where the message is being sent. The argument can be a String object or a URL object. Call() 메소드에 대한 두번째 인수는 메세지를 전송할 곳을 가리킨다. 이 인수는 String 오브젝트나 URL 오브젝트가 될 수 있다.
요청-반응 메세징으로 구현되는 모든 웹 서비스는 반드시 HTTP Post를 핸들링할 수 있어야하며, 수신한 메세지에 대해 반응을 리턴해야한다. 반응은 반드시 SOAPMessage오브젝트여야하며, 이는 요청이 반드시 SOAPMessage 오브젝트여야하는 것과 같은 이치이다. 이를 통해 사용자는 메세지를 생성하는데 사용한 메소드와 동일한 메소드로 반응의 컨텐츠에 접근할 수 있게 된다. 어떤 메세지들은 반응을 요청하지 않는다는 것을 주의하기 바란다. 그렇지만 이런 메세지를 얻는 서비스도 여전히 반응을 리턴해야한다. call() 메소드를 언블락해야하기 때문이다.
커넥션은 많은 리소스를 사용할 수 있으므로, 사용 후 바로 커넥션을 클로징하는 것이 좋다. 다음과 같이 커넥션을 클로징할 수 있다.
connection.close();
Resources
SAAJ에 대한 좀 더 많은 정보는 J2EE 1.4 튜토리얼의 Chapter 9: SOAP with Attachments API for Java를 참조하기 바란다.
Sample Code
이 테크 팁을 위한 예제 코드는 SAA를 이용하여 이름이 "Federal Government Service"의 패턴과 일치하는 조직체에 대한 레지스트리를 조회합니다.
예제 코드를 구동하려면,
- 이 테크팁을 위한 샘플 아카이브(
ttapr2005saaj.jar)를 다운로드합니다.
- JWSDP 1.5를 다운로드하여 설치합니다.
- 예제 아카이브를 다운로드한 디렉토리로 이동합니다. 다음과 같이 예제 아카이브가 담긴 JAR 파일의 압축을 풉니다.
jar xvf ttapr2005saaj.jar
- 사용자의
CLASSPATH환경 변수에 다음 JWSDP 1.5 라이브러리를 추가합니다. 위치는 기본 디렉터리를 기준으로 부여됩니다(jwsdp-1.5)saaj/lib/saaj-api.jar saaj/lib/saaj-impl.jar jaxp/lib/jaxp-api.jar jaxp/lib/endorsed/xercesImpl.jar jaxp/lib/endorsed/xalan.jar jaxp/lib/endorsed/dom.jar jaxp/lib/endorsed/sax.jar jwsdp-shared/lib/mail.jar jwsdp-shared/lib/activation.jar SAAJMain.java파일을 컴파일합니다.
SAAJMain을 구동합니다.java SAAJMain
다음과 같은 결과가 나타납니다.
---- Request Message ---- <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/so ap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><find_service gen eric="2.0" maxRows="100" xmlns="urn:uddi-org:api_v2"><name>Feder al Government Service</name></find_service></SOAP-ENV:Body></SOA P-ENV:Envelope> Received reply from: http://uddi.ibm.com/beta/inquiryapi ---- Reply Message ---- <?xml version="1.0" encoding="UTF-8" ?><Envelope xmlns="http://s chemas.xmlsoap.org/soap/envelope/"><Body><serviceList generic="2 .0" xmlns="urn:uddi-org:api_v2" operator="private.uddi.operator" truncated="false"><serviceInfos><serviceInfo serviceKey="056b290 5-3999-4912-89de-fe79cbfedea0" businessKey="8cd1668c-64fa-4aa5-a 053-bd0be4bd53f5"><name xml:lang="en-US">Federal Government Serv ice</name></serviceInfo><serviceInfo serviceKey="a70ad5a7-564a-4 acd-ac6a-b2bcf4b26a30" businessKey="3d686d3d-22d7-470c-b515-3264 28321566"><name xml:lang="en-US">Federal Government Service</nam e></serviceInfo><serviceInfo serviceKey="ca5939ca-71ce-4e65-8b20 -d53f6ad52036" businessKey="f9aa37f9-c9f0-401b-8c0f-f2bd16f20f42 "><name xml:lang="en-US">Federal Government Service</name></serv iceInfo><serviceInfo serviceKey="2b69352b-835d-4d5b-a51e-1af1e91 a1e44" businessKey="06b7a606-b5a5-452f-8df6-e8cdf5e8f6c6"><name xml:lang="fr-BE">Federal Government Service</name></serviceInfo> </serviceInfos></serviceList></Body></Envelope>
"Java EE" 카테고리의 다른 글
- Attach API (댓글 18개 / 트랙백 1개) 2007/09/03
- JSP 2.0 EXPRESSION LANGUAGE (댓글 1개 / 트랙백 0개) 2004/02/05
- 환경 엔트리를 이용해서 배포의 사용자 정의하기 (댓글 2개 / 트랙백 0개) 2003/12/24
- JAX-WS를 이용한 웹 서비스 개발 (댓글 1개 / 트랙백 0개) 2006/01/18
- EJB 2.1로 메시지 구동 빈 이용하기 (댓글 1개 / 트랙백 0개) 2005/05/18
- EclipseLink를 사용하여 JPA에서 반복 불가능한 읽기 방지 (댓글 0개 / 트랙백 1개) 2008/07/09
- 컴포넌트 시스템과 클래스 로더 경계 (댓글 1개 / 트랙백 0개) 2004/10/05
- JAX-WS Dispatch 및 Provider API를 이용한 문서 처리 (댓글 4개 / 트랙백 0개) 2006/09/15
- POJO를 Persistent Entity로 변환하기 (댓글 1개 / 트랙백 0개) 2005/12/27
- SAAJ 소개 (댓글 1개 / 트랙백 0개) 2005/06/08
댓글을 달아 주세요
좋은 정보 감사해요~
2007/09/19 05:24