저자: Deep Singh
JAX-WS 2.0 스펙에서는 웹 서비스가 XML 메시지 레벨에서 운영될 수 있도록 하는 두 가지 새로운 API를 제공한다. 프로그래머는 웹 서비스와 XML 작업 시 SEI(Service Endpoint Interface) 구현을 이용하여 자바 메소드와 그에 대응하는 XML 간 변환의 세부사항을 숨기는 자바 레벨의 추상화를 제공하나, 개발자들은 종종 자바 추상화보다 XML로 직접 작업하기를 원할 때가 있다. 이런 상황과 관련하여 새로운 API는 SEI 방식의 대안책을 제시한다. 본 테크 팁에서는 예제 애플리케이션을 통한 API의 사용 실례를 살펴 보도록 한다.
새로운 API는 javax.xml.ws.Provider와 java.xml.ws.Dispatch이며, 이 둘 모두 제네릭 API이다. Provider는 서버 측 API인 반면 Dispatch는 클라이언트 측 API이다. 이들 API는 서비스가 메시지나 메시지 페이로드로 작업할 것을 요구하는데, 이 때문에 API는 메시지의 구조 또는 페이로드 구조에 관한 세부 특성을 알고 있어야 한다. API는 일반적인 특성 상 다양한 타입의 메시지 오브젝트에 사용할 수 있다. 한편 JAX-WS 스펙은 구현들이 최소한 javax.xml.transform.Source, javax.xml.soap.SOAPMessage, javax.activation.DataSource, 및 JAXB 오브젝트를 지원할 것을 요구하고 있다. 본 팁의 예제 애플리케이션은 javax.xml.transform.Source와 javax.xml.soap.SOAPMessage 오브젝트를 각기 별개의 구현에서 사용한다.
예제 애플리케이션: Dispatch와 Provider 사용하기
본 팁의 예제 애플리케이션은 2006년 7월 5일자 팁 웹 서비스 애플리케이션에서 문서 처리하기의 예제 애플리케이션을 업데이트한 것이다. 이전 팁의 예제 애플리케이션은 신용카드 인증을 에뮬레이트하고 SEI를 이용하여 웹 서비스를 구현했는데, 본 팁의 예제 애플리케이션은 Provider 인터페이스를 이용하여 웹 서비스를 구현하는 동일한 서비스를 제공한다. 클라이언트는 각각 SOAPMessage 오브젝트와 Source 오브젝트를 이용하여 메시지를 전송하고 메시지 페이로드를 전송한다. 예제는 동기 콜백 서비스 호출 방식을 사용하며, 동기 콜백 방식에서는 원격 오퍼레이션이 완료되어 결과를 반환할 때까지 서비스의 invoke 메소드가 추가 처리를 차단한다. 예제 애플리케이션은 또한 클라이언트와 서버 모두에서 JAXB를 사용하게 된다.
환경 설정하기
본 팁의 예제는 GlassFish라고 불리는 Java EE 5의 오픈 소스 레퍼런스 구현을 사용한다. GlassFish를 아직 구하지 못했다면 GlassFish 커뮤니티 다운로드 페이지에서 다운로드한다. 예제를 구축하고 실행하려면 JDK 5.0(J2SE 5.0 다운로드 페이지에서 다운로드 할 수 있음)과 Apache Ant 1.6.5(GlassFish 번들에 포함되어 있으며, Windows의 경우에는 lib\ant 서브디렉토리에 있음)도 함께 필요하다.
예제 애플리케이션 설치하기
예제 패키지를 다운로드하여 압축을 푼다. 예제 관련 루트 디렉토리는 techtip이다. 현재 디렉토리를 techtip 디렉토리로 변경한다. 각 사용자의 빌드 환경을 반영하도록 스크립트 env.sh(UNIX의 경우) 또는 env.bat(Windows의 경우)를 편집한다. 예를 들어, 스크립트 내에 있는 JAVA_HOME 환경 변수의 값을 각자의 시스템에서 JDK 5.0의 위치로 변경한 다음 스크립트를 실행하여 각자의 환경을 설정하면 된다.
웹 서비스 구축하기
예제에서는 WSDL 파일을 이용하여 웹 서비스를 구축하는데, 이를 수행하기 위한 단계는 다음과 같다.
- XML 스키마를 기반으로 WSDL 파일을 생성한다.
- 엔드포인트 구현 클래스를 작성한다.
- 웹 서비스 실행을 위한 portable artifacts를 생성한다.
- 웹 서비스를 컴파일하고 WAR 파일로 패키징하여 배포한다.
이 단계와 파일들을 조금 더 면밀히 살펴보기로 하자.
1. XML 스키마를 기반으로 WSDL 파일을 생성한다
WSDL 파일은 예제 패키지에 포함되어 있으며, WSDL 파일 CreditCardService.wsdl은 conf 디렉토리에 들어 있다. WSDL 파일은 신용카드 결제를 인증하는 웹 서비스 연산을 보여준다. WSDL에 관한 자세한 내용은 Web Services Description Language (WSDL) 1.1을 참조할 것.
스키마 파일
WSDL 파일이 임포트하는 2개의 스키마 파일은 CreditCardAuthorization.xsd와 CreditCardServiceException.xsd인데, CreditCardAuthorization.xsd는 클라이언트가 웹 서비스에 전송할 수 있는 XML 문서의 구조를 정의한다. 신용카드 인증 요청과 관련이 있는 스키마 내의 엘리먼트는 다음과 같다.

(위의 코드는 본 테크 팁의 텍스트 버전에서 캡쳐할 수 있다.)
유사한 엘리먼트들이 정의되어 인증 상태를 리턴하는 데 사용된다.
CreditCardServiceException.xsd는 오류 메시지를 리턴하기 위한(즉, 웹 서비스가 요청을 처리할 수 없는 경우) XML 문서의 구조를 정의한다.
2. portable artifact를 생성한다
예제를 위한 ant 태스크는 techtip 디렉토리 내의 build.xml 파일에 들어 있으며, 예제에서는 wsimport 툴과 패키징된 WSDL을 사용하여 서비스 클래스, JAXB 클래스, 예외 클래스 등과 같은 portable artifacts를 생성한다. 예제에서는 타깃 이름이 generate-server인 ant 태스크에서 상기 작업을 수행하게 된다. ant 태스크는 conf 디렉토리에 들어 있는 외부 바인딩 파일 config-server.xml을 사용한다.
artifacts가 생성된 후에는 javac 컴파일러를 사용하여 컴파일하는데, 예제에서는 타깃 이름이 compile-server인 ant 태스크에서 이 작업을 수행한다.
3. 엔드포인트 구현 클래스를 작성한다
예제에는 CreditCardServiceUsingPAYLOAD.java와 CreditCardServiceUsingMESSAGE.java 등 두 가지 엔드포인트 구현 클래스를 제공한다. 이들은 한번에 하나씩만 서비스로 배치될 수 있는데, 어느 쪽이 배치되느냐는 서비스 모드를 위한 환경 변수에 의해 좌우된다. 환경 변수는 사용자가 앞서 실행한 스크립트에 의해 설정된다. 예를 들어, env.sh 스크립트에는 다음과 같은 서비스 모드를 위한 환경 변수 설정이 포함되어 있다.

(위의 코드는 본 테크 팁의 텍스트 버전에서 캡쳐할 수 있다.)
CreditCardServiceUsingPAYLOAD.java 클래스는 페이로드 지향의 동기 콜백 모드를 위한 Provider 인터페이스를 구현하고, CreditCardServiceUsingMESSAGE.java 클래스는 메시지 지향의 동기 콜백 모드를 위한 Provider 인터페이스를 구현한다.
다음은 Payload를 이용한 구현이다.

(위의 코드는 본 테크 팁의 텍스트 버전에서 캡쳐할 수 있다.)
JAX-WS 스펙은 Provider 구현 클래스에 @WebServiceProvider 주석이 포함될 것을 요구하며, @ServiceMode 주석은 어떤 콜백 모드를 사용할 것인지 정의한다. CreditCardServiceUsingPAYLOAD.java를 위한 코드는 Service.Mode.PAYLOAD 모드를 지정하는데, 이는 Provider 구현이 오직 메시지 페이로드에 대해서만 동작한다는 것을 의미한다.
이 클래스는 Provider<Source> 인터페이스를 구현하며, Source 타입은 페이로드 모드에서만 사용할 수 있다. 동기 콜백의 경우, 구현은 invoke 메소드를 정의하는데, 이 메소드는 클라이언트에 의해 호출된다. Provider<Source> 타입 인터페이스의 경우, invoke 메소드의 입력/출력 매개변수는 Source 오브젝트이다. 예제에서는 authorizePayment 메소드가 신용카드에 대한 대금 청구를 승인하는 데 사용되는 유틸리티 메소드이다.

(위의 코드는 본 테크 팁의 텍스트 버전에서 캡쳐할 수 있다.)
authorizePayment 메소드는 입력 Source를 문자열로 변환하는데, 이 경우 StAX 리더/라이터 API를 이용하여 입력 XML을 읽고 출력 XML을 구성한다. 2006년 5월의 테크팁에 실린 예제에서 authorizePaymentSTAX 메소드를 이용하여 StAX를 사용하는 XLM 문서를 처리했던 것을 상기해보기 바란다.
이제, Message를 이용한 서비스 구현에 대해 살펴보기로 하자.

(위의 코드는 본 테크 팁의 텍스트 버전에서 캡쳐할 수 있다.)
이전과 마찬가지로, 클래스는 WebServiceProvider와 ServiceMode 주석을 사용하는데, 눈에 띄는 차이점은 이번에는 모드가 Service.Mode.MESSAGE라는 사실이다. Provider 인터페이스는 SOAPMessage 타입의 메소드들을 지원하며, invoke 메소드는 SOAP 메시지를 위한 입력/출력 매개변수를 가지는 동기 콜백 메소드이다. 유틸리티 메소드 getSourceFromSOAPMessage는 Source 오브젝트를 리턴한다. 한편 유틸리티 메소드 authorizePayment는 페이로드 예제에서 정의된 것과 유사하다고 보면 된다.
Provider 구현 역시 페이로드나 메시지 서비스 모드에서 JAXB를 사용할 수 있다. JAXB의 구체적인 사용법은 본 팁에서 다루지는 않으나 예제에 JAXB의 사용을 예시하는 코드가 포함되어 있다(이에 대해서는 잠시 후에 다시 설명하도록 한다).
4. 웹 서비스를 컴파일하고 WAR 파일로 패키징하여 배포한다
서비스 구현 클래스와 앞서 생성한 웹 서비스용 portable artifacts를 컴파일해야 한다. CreditCardService.wsdl 상에서 wsimport를 실행하여 서비스 구현 클래스와 생성된 artifacts를 컴파일한 다음 클래스를 웹 서비스용 배치 서술자 sun-jaxws.xml와 함께 WAR 파일로 패키징해야 한다. 예제에서는 타깃 build를 가지는 ant 태스크를 통해 패키징이 수행되며, 서버는 사용자가 환경에서 설정한 서비스 모드를 기반으로 구축을 수행한다. 다양한 모드를 시험해 보려면 env.sh 또는 env.bat script 내의 service_mode 환경 변수를 변경하고 서버와 클라이언트를 재구축한다.
클라이언트 구축
다음은 웹 서비스 클라이언트를 구축하기 위한 단계들이다.
- 클라이언트 클래스를 작성한다.
- 웹 서비스 실행을 위한 portable artifacts를 생성한다.
- 클라이언트를 컴파일한다.
5. 클라이언트 클래스를 작성한다
예제 패키지에는 독립형 웹 서비스 클라이언트 CreditCardServiceTest.java가 포함되어 있으며, src\client 디렉토리에 들어 있다. 클라이언트는 신용카드 웹 서비스를 호출하여 고객이 제시하는 신용카드에 대한 결제를 인증하고, XML 문서에 포함된 신용카드 및 카드 소지자 정보를 서버에 전송한다.
다음은 웹 서비스를 호출하는 CreditCardServiceTest 내의 메소드이다.

(위의 코드는 본 테크 팁의 텍스트 버전에서 캡쳐할 수 있다.)
testAuthorizePayment 메소드는 서버 상에 위치하는 WSDL의 url을 이용하는 서비스와 wsdl:service 엘리먼트를 식별하는 QName 서비스를 생성한다. 이어서 메소드는 Dispatch와 함께 사용할 포트를 추가하는데, 추가된 포트에는 wsdl:port에 관한 정보가 포함되어 있지 않으며, 오직 Dispatch 인스턴스를 통해서만 사용이 가능하다. portName은 새로운 웹 서비스 포트의 QName이며, url은 웹 서비스의 엔드포인트 주소이다. 포트는 SOAP1.1/HTTP 바인딩을 사용한다.
선택된 서비스 모드가 PAYLOAD인 경우, Dispatch 인스턴스는 Source 타입의 오브젝트를 이용하여 생성되는데, Dispatch 인스턴스는 Source 오브젝트를 입력으로 사용하여 서비스 메소드를 호출하고 Source 타입의 출력을 얻는다.
선택된 모드가 MESSAGE인 경우에는 Dispatch 인스턴스가 SOAPMessage 타입의 오브젝트를 이용하여 생성된다.

(위의 코드는 본 테크 팁의 텍스트 버전에서 캡쳐할 수 있다.)
MESSAGE 모드의 경우, Dispatch 인스턴스는 SOAPMessage 오브젝트를 이용하여 invoke 메소드를 호출하고 그 응답으로 SOAPMessage 오브젝트를 얻는다.
앞서 언급한 것처럼, 본 팁에서는 페이로드 또는 메시지 서비스 모드에서 JAXB를 사용하는 방법을 설명하지 않는다. 하지만 CreditCardServiceTest.java 클래스의 다음 코드 행들은 JAXB을 사용하여 결제 인증을 시험한다.

(위의 코드는 본 테크 팁의 텍스트 버전에서 캡쳐할 수 있다.)
6. portable artifacts를 생성하고 클라이언트를 컴파일한다
서버 상의 WSDL을 사용하여 클라이언트 측 portable artifacts를 생성한다. 예제에서는 타깃 build를 가지는 ant 태스크를 사용하여 이 작업을 수행하는데, 실제로 ant 타깃 build를 호출하면 생성된 artifacts를 포함하여 서버 및 클라이언트 클래스를 모두 컴파일하게 된다. 이와 더불어 배포 가능한 WAR 파일을 구축한다. 클라이언트는 JAXB 바인딩 구성 파일 config-client.xml을 사용한다는 점에 유의할 것. 클라이언트는 사용자가 환경에서 설정한 서비스 모드를 기반으로 구축된다. 다양한 모드를 시험해 보려면 env.sh 또는 env.bat 스크립트 내의 service_mode 환경 변수를 변경하고 서버와 클라이언트를 재구축한다.
예제 실행하기
각자의 환경 설정을 위한 스크립트를 실행한 후, 다음과 같이 예제를 실행할 수 있다.
- 다음 명령어를 입력하여 GlassFish를 시작한다.
%J2EE_HOME%/bin/asadmin start-domain domain1J2EE_HOME환경 변수가 GlassFish 설치 디렉토리로 설정되어 있는지 확인한다. - 웹 서비스, 클라이언트, 그리고 필요한 artifacts를 구축하고 다음 명령어를 입력하여 이를 WAR 파일로 패키징한다.
ant build - 다음 명령어를 입력하여 애플리케이션을 배포한다.
ant deploy - 다음 명령어를 입력하여 애플리케이션을 실행한다.
명령어는 세 가지 XML 처리 기술을 모두 사용하여 애플리케이션을 실행하게 되는데, 이 경우 아래와 유사한 결과가 표시되어야 한다.ant run
(위의 코드는 본 테크 팁의 텍스트 버전에서 캡쳐할 수 있다.)
- 다음 명령어를 입력하여 애플리케이션을 배포 해제한다.
ant undeploy - 다음 명령어를 입력하여 애플리케이션을 위해 생성된 모든 클래스와 WAR 파일을 삭제한다.
ant clean
저자 소개
Deep Singh은 썬 마이크로시스템즈 Java Performance Engineering 그룹의 스태프 멤버로 활동하고 있다.
"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/07 20:18웹 서비스 구축하기..좋은 정보 감사합니다!
2007/09/15 21:52좋은 정보 감사해요~
2007/09/19 04:15좋은 정보 감사해요~
2007/09/19 04:15