저자 Manisha Umbarje JAX-RPC(Java API for XML-based RPC) 1.1의 후속 릴리즈인 Java API for XML Web Services (JAX-WS) 2.0, JSR 224는 Java EE 5 플랫폼에 있어서 매우 중요한 부분으로서 자바 기술을 이용한 웹 서비스 개발 작업을 간소화시켜준다. JAX-WS는 SOAP 1.1, SOAP 1.2, XML을 비롯한 복수의 프로토콜을 지원하고 HTML 등의 추가 프로토콜 지원을 위한 기능을 제공함으로써 JAX-RPC 1.1의 몇 가지 문제를 해결하고 있다. JAX-WS는 데이터 바인딩에 JAXB 2.0을 사용하며 생성된 서비스 엔드포인트 인터페이스를 관리하기 위한 커스터마이제이션을 지원한다. JAX-WS는 또한 주석(annotation)을 지원하여 웹 서비스 개발을 간소화하고 런타임 Jar 파일의 사이즈를 줄여주기도 한다.
본 테크팁에는 예제 패키지가 포함되어 있으며, 패키지는 독립형 자바 클라이언트 상에서 JAX-WS 2.0를 통해 액세스되는 간단한 웹 서비스를 예시한다. 이 예제는 GlassFish라 불리는 Java EE 5 SDK의 오픈 소스 구현에 기반을 두고 있으며, 예제 패키지에는 예제를 위한 소스 코드, 빌드 스크립트, 빌드 파일 등이 포함되어 있다.
초기 셋업 작업 부분부터 시작해 보기로 하자. 먼저 다운로드 페이지에서 GlassFish를 다운로드한다. (본 팁은 GlassFish의 Build 29로 테스트를 거쳤음.) 그리고 다음과 같이 설정한다.
GLASSFISH_HOME. GlssFish 설치 장소가 표시되어야 한다(예: C:\Sun\AppServer)
ANT_HOME. Ant 설치 장소가 표시되어야 한다. Ant는 다운로드한 GlassFish 번들에 포함되어 있으며(Windows의 경우에는 lib\ant 서브디렉터리에 있음), Apache Ant Project 페이지에서도 Ant를 다운로드할 수 있다. 예제에서는 Apache ant 1.6.5를 사용한다.
JAVA_HOME. 사용자 시스템의 JDK 5.0 위치가 표시되어야 한다. Also, add the ant location to your PATH environment variable. 아울러, 각자의 PATH 환경 변수에 ant 위치를 추가한다.
이어서 예제 패키지를 다운로드하고 압축을 해제한다. 본 팁의 메인 디렉터리는 jaxws-techtip이다.
웹 서비스 구축하기
초기 셋업이 완료된 다음에는 웹 서비스를 구축할 차례다. 본 예제의 경우, Java 클래스를 이용하여 웹 서비스를 개발한다. 웹 서비스를 구축하려면 다음 단계를 수행한다.
엔드포인트 구현 클래스를 작성한다. 엔드포인트 구현 클래스를 컴파일한다. 옵션에 따라 웹 서비스 실행에 필요한 portable artifact를 생성한다. 웹 서비스를 WAR 파일로 패키징하여 배치한다. 엔드포인트 구현 클래스 작성
<Sample_install_dir>\jaxws-techtip 디렉터리 구조를 훑어 내려가면 엔드포인트 디렉터리를 찾을 수 있는데, 이 디렉터리에 Calculator라는 이름의 클래스가 있다. 이 클래스는 2개의 정수를 추가하는 단순 서비스 엔드포인트 구현이다.
@WebService( name="Calculator", serviceName="CalculatorService", targetNamespace="http://techtip.com/jaxws/sample" ) public class Calculator { public Calculator() {}
@WebMethod(operationName="add", action="urn:Add") public int add(int i, int j) { int k = i +j ; System.out.println(i + "+" + j +" = " + k);
return k; } }
JAX-WS 2.0의 경우, A Metadata Facility for the Java Programming Language(JSR 175) 및 Web Services Metadata for the Java Platform(JSR 181)에 명시된 주석과 JAX-WS 2.0 스펙에 정의된 추가 주석을 주로 사용한다.
Calculator 클래스의 @WebService 및 @WebMethod의 2개 주석에 유의할 것. 유효한 엔드포인트 구현 클래스에는 반드시 @WebService 주석이 포함되어야 하며, 주석은 클래스를 웹 서비스로 표시한다. @WebService 주석의 이름 속성값은 WSDL(Web Service Description Language) portType(이 경우는 "Calculator")을 나타내며, serviceName ("CalculatorService")는 WSDL 서비스이다. TargetNamespace는WSDL에 사용되는 XML 네임스페이스를 지정한다. 모든 속성은 옵션사항이다. 이들 속성의 기본값에 관한 자세한 내용을 보려면 Web Services Metadata for the Java Platform 명세를 참조하기 바란다.
@WebMethod 주석은 메소드를 웹 서비스 메소드 방식으로 표시한다. Calculator 클래스의 주석에 있는 operationName 속성값은 WSDL 연산(이 경우에는 add)을 나타내며 액션 속성값("urn:Add")은 WSDL을 위한 XML 네임스페이스와 이 웹 서비스 연산에서 생성된 일부 요소를 지정한다. 두 가지 속성 모두 옵션사항인데, 이들을 지정하지 않을 경우 WSDL 연산값은 디폴트값은 메소드 이름이고, 액션 값의 디폴트값은 서비스의 targetNamespace이다.
구현 클래스 컴파일
구현 클래스를 코딩한 후에는 컴파일을 해야 한다. 다음 명령어를 입력하여 GlassFish를 시작한다.
<GF_install_dir>\bin\asadmin start-domain domain1
이 때, <GF_install_dir>은 GlassFish를 설치한 디렉터리이다. 이어서 <Sample_install_dir>\jaxws 디렉터리 구조의 jaxws-techtip 폴더로 이동하여 다음의 명령어를 실행한다.
ant compile
이 명령어를 실행하는 것은 다음 javac명령어(실제는 한 줄로 입력)를 실행하는 것과 동일하다.
이 단계는 옵션사항으로, 웹 서비스 배치 과정에서 GlassFish의 배치 툴에 배치 가능한 서비스 유닛이 번들로 포함되지 않은 경우에는 자동적으로 artifacts를 생성한다. 하지만, 이 artifacts를 수동으로 생성하기를 원할 경우에는 다음의 명령어를 실행한다.
ant generate-runtime-artifacts
이 경우, jaxws-techtip 밑에 build/generated 디렉터리를 생성하고 다음 wsgen 명령어(실제는 한 줄로 입력)를 실행한다.
build/generated 디렉터리에 CalculatorService.wsdl 스키마를 정의하는 스키마 파일(CalculatorService_schema1.xsd)과 함께 WSDL 파일(CalculatorService.wsdl)이 생성된다.
JavaBean 기술 컴포넌트(JavaBeans)는 메소드 호출, 응답, 및 서비스별 예외의 정렬을 도와주는데, 이 클래스는 애플리케이션 서버에서 웹 서비스를 실행하는 과정에서 사용된다. JavaBean 클래스는 jaxws-techtip 밑의 /build/classes/service/endpoint/jaxws 디렉터리에 생성되며, 클래스는 다음과 같다.
이어서 서비스를 패키징하고 배치해야 하는데, 이를 위해서는 배치 서술자(deployment descriptor)에 서비스에 관한 세부사항을 지정해야 한다. 웹 서비스는 서블릿 또는 stateless 세션 빈으로 번들링될 수 있으며, 서블릿으로 번들링된 웹 서비스는 Web Archive(WAR) 파일에 패키징된다. 한편, 본 팁에서는 서비스가 서블릿으로 번들링된다.
서비스를 WAR 파일로 패키징하려면 jaxws-techtip 폴더로 가서 다음 명령어를 실행한다.
ant pkg-war
war 파일의 구조를 보려면 build.xml 파일의 pkg-war 타깃을 살펴보면 된다.
public void doTest(String[] args) { try { System.out.println( " Retrieving port from the service " + service); Calculator port = service.getCalculatorPort(); System.out.println( " Invoking add operation on the calculator port"); for (int i=0;i>10;i++) { int ret = port.add(i, 10); if(ret != (i + 10)) { System.out.println("Unexpected greeting " + ret); return; } System.out.println( " Adding : " + i + " + 10 = " + ret); } } catch(Exception e) { e.printStackTrace(); } } }
웹 서비스에 대한 참조를 선언하는 데는 JAXWSClient의 @WebServiceRef 주석이 사용된다. @WebServiceRef에서의 wsdlLocation 매개변수의 값은 참조되는 서비스를 위한 WSDL의 위치를 가리키는 URL이고, @WebServiceRef 주석은 JSR 224의 섹션 7.9에 명시된 추가 옵션 속성을 지원한다. 정적 변수 네임드 서비스는 애플리케이션 클라이언트 컨테이너에 의해 인젝트된다.
JAXWSClient 내의 임포트 문인 com.techtip.jaxws.sample.CalculatorService와 com.techtip.jaxws.sample.Calculator에 유의할 것. 이 임포트는 다음 단계에서 생성될 portable artifact이고, CalculatorService는 서비스 구현을 위한 portable artifact이다. Calculator는 @WebServiceRef의 wsdlLocation 속성이 나타내는 WSDL에서 생성되는 서비스 엔드포인트를 위한 자바 인터페이스이다.
클라이언트는 getWebServiceRefNamePort 메소드(여기서 WebServiceRefName은 @WebServiceRef의 이름 속성) 또는 생성된 WSDL 파일의 WSDP 포트 값을 통해 CalculatorService에서 엔드포인트 Calculator를 검색한다. 클라이언트는 엔드포인트를 검색한 후 add 연산을 요구대로 10회에 걸쳐 호출한다.
클라이언트를 위한 portable artifact 생성
앞에서 언급한 것처럼 CalculatorService와 Calculator는 portable artifact인데, 클라이언트를 위한 모든 portable artifact를 생성하려면 jaxws-techtip 폴더에서 다음 명령어를 실행한다.