저자: Rama Pulavarthi

2006년 8월 10일자 테크 팁, JAX-WS에서 핸들러 작성하기에서는 JAX-WS 핸들러를 소개하고 이들이 어떻게 서버와 클라이언트 간의 교환 메시지를 pre-process 또는 post-process하는 데 사용될 수 있는지에 관해 설명한 바 있다. 이번호 테크 팁에서는 웹 서비스를 위한 핸들러를 구성, 패키징, 배치하는 방법에 관해 다루어 보도록 하겠으며, 본 팁에 이어 다음 달에는 웹 서비스 클라이언트에서 핸들러를 구성하는 다양한 방법을 보여주는 팁들을 소개하려고한다.

JAX-WS는 핸들러를 위한 플러그인 프레임워크를 제공할 뿐 아니라 핸들러의 라이프사이클과 핸들러가 클라이언트/서버와 인터랙트하는 방식을 정의하는 역할을 한다. JAX-WS는 핸들러를 위한 표준 배치 모델을 정의하지 않는 대신 서버 상의 핸들러 구성에 사용되는 배포 메타데이터가 JSR-109: Implementing Enterprise Web Services에 의해 정의된다.

핸들러 체인

핸들러는 실행 순서가 정해진 핸들러의 묶음인 '핸들러 체인'에 따라 구성되며, 핸들러 체인의 신택스는 JSR-109에 의해 정의된다. 핸들러 체인 내에서, 포트 구성요소(즉, 서비스에 연결된 특정 포트)에 대한 해당 핸들러가 선택되어 체인을 형성하게 되는데, 선택된 핸들러는 정해진 순서에 따라 실행된다. 로지컬 핸들러는 SOAP 핸들러 전에 실행되어 체인의 원래 순서를 유지한다. 핸들러 체인을 위한 스키마는 Java EE 웹 서비스 배치 기술자(http://java.sun.com/xml/ns/javaee/javaee_web_services_1_2.xsd)에서 정의된다.

다음은 간단한 핸들러 체인의 예제이다.

핸들러 체인 구성은 어떠한 포트나 서비스에도 적용이 가능한데, 가령 사용자는 WSDL 파일에 정의된 복수의 서비스를 비롯하여 서비스에서 다양한 프로토콜 바인딩을 지원하는 복수의 포트를 가질 수 있다. 사용자는 어떠한 서비스나 포트에도 핸들러 체인을 적용할 수 있는 동시에 <handler-chain> 엘리먼트에 제약조건을 지정함으로써 특정 포트에 선택적으로 핸들러 구성을 적용할 수도 있다. 사용자는 핸들러 체인의 핸들러가 서비스, 포트, 또는 프로토콜 바인딩에 각각 적용되는지 여부를 지정하는 <service-name-pattern>, <port-name-pattern>, 또는 <protocol-bindings> 엘리먼트에서 이러한 제약조건을 지정할 수 있다. <handler-chain element> 내에서 이 엘리먼트들 중 어느 것도 지정되지 않을 경우에는 <handler-chain>에 지정된 핸들러가 모두에 적용된다.

이와 관련한 제약조건들을 살펴보기로 하자.

<service-name-pattern>

이 엘리먼트는 핸들러를 특정 서비스에 적용할 때 사용하며, 엘리먼트에서 Java EE QName 유형을 지정함으로써 이 작업을 수행할 수 있다. 그런 다음, 연결된 <handler-chain> 엘리먼트에서 식별된 핸들러가 QName 유형과 일치하는 포트에 적용된다. 이 때, QName 유형은 정확한 이름일 수도 있고 와일드 카드를 포함할 수도 있다. 다음은 정확한 이름의 QName 유형을 지정하는 예제이다.

정확하게 이름을 지정할 경우, <handler-chain> 엘리먼트에 지정된 핸들러는 서비스 이름이 HelloService인 모든 포트에 적용된다. 사용자는 반드시 접두사가 사용된 엘리먼트의 시작 태그 또는 ancestor 엘리먼트(즉, 내용 중에 접두사가 붙고 마크업이 나타나는 엘리먼트)의 네임스페이스 선언 속성에 네임스페이스 접두사를 선언해야 한다.

다음은 와일드 카드 유형을 지정하는 <service-name-pattern> 엘리먼트의 예제이다.

여기서, 연결된 <handler-chain> 엘리먼트에 지정된 핸들러는 서비스 이름이 HelloService로 시작되는(가령, HelloService1 또는 HelloServiceFoo) 모든 포트에 적용된다.

다음은 또 다른 와일드 카드의 유형이다.

<service-name-pattern>*<service-name-pattern>

연결된 <handler-chain> 엘리먼트에 지정된 핸들러는 모든 서비스 이름의 포트에 적용되는데, 이는 <handler-chain> 엘리먼트에 아무런 제약조건을 지정하지 않는 것과도 같다고 볼 수 있다.

<port-name-pattern>

이 엘리먼트는 핸들러를 특정 포트에 적용할 때 사용한다. 예:

여기서, 연결된 <handler-chain> 엘리먼트에 지정된 핸들러는 이름이 Hello로 시작되는 모든 포트에 적용된다.

<protocol-bindings>

이 엘리먼트는 핸들러를 특정 프로토콜 바인딩 세트에 적용할 때 사용하고, 관련 <handler-chain>에 지정된 핸들러는 리스트에 포트의 프로토콜 바인딩이 포함된 경우에 적용된다. 사용자는 프로토콜 바인딩의 URI를 지정하는 것 외에도 표준 바인딩의 별칭(alias)인 토큰을 지정할 수 있다. 이 사전 정의된 토큰들에 대한 URI는 다음과 같다:

##SOAP11_HTTP - "http://schemas.xmlsoap.org/wsdl/soap/http"
##SOAP11_HTTP_MTOM - "http://schemas.xmlsoap.org/wsdl/soap/http?mtom=true"
##SOAP12_HTTP - "http://www.w3.org/2003/05/soap/bindings/HTTP/"
##SOAP12_HTTP_MTOM - "http://www.w3.org/2003/05/soap/bindings/HTTP/?mtom=true"
##XML_HTTP - "http://www.w3.org/2004/08/wsdl/http"

다음 예제에서 <protocol-bindings> 엘리먼트는 핸들러 체인의 핸들러가 포트의 프로토콜 바인딩이 Mtom이 포함된 SOAP 1.1 또는 SOAP 1.1인 경우에 적용된다는 것을 명시한다.

핸들러 체인에서 핸들러 구성하기

사용자는 @javax.jws.HandlerChain 주석을 이용하거나 JAX-WS 커스터마이제이션을 통해 핸들러 체인에서 핸들러를 구성할 수 있다.

HandlerChain 주석을 이용하여 핸들러 구성하기

JSR-181: Web Services Metadata for the Java Platform은 JAX-WS 코드와 함께 포트 구성요소 또는 서비스와 연결된 핸들러 체인을 지정하는 데 사용될 수 있는 @javax.jws.HandlerChain 주석을 정의한다. 이 주석은 웹 서비스 엔드포인트(@javax.jws.WebService 또는 @javax.xml.ws.WebServiceProvider 주석으로 선언) 또는 웹 서비스 레퍼런스(@javax.xml.ws.WebServiceRef 주석으로 선언) 상에서 선언될 수 있다. 사용자는 핸들러 체인 파일의 위치로 @javax.jws.HandlerChain 주석을 정의하는데, 위치는 http://example.com/handlers/handlerfile1.xml처럼 절대적 URL일 수도 있고 bar/handlerfile1.xml처럼 소스 파일이나 클래스 파일에 대한 상대적 경로일 수도 있다.

다음은 @javax.jws.HandlerChain 주석을 이용하여 핸들러 체인을 웹 서비스 엔드포인트에 연결하는 예제이다.

JAX-WS 커스터마이제이션을 통해 핸들러 구성하기

이 방식의 경우, 사용자는 JAX-WS 커스터마이제이션 파일의 <jaxws:bindings> 내에 있는 <handler-chains> 엘리먼트를 지정하고, wsimport 툴을 이용하여 커스터마이제이션 파일에서 WSDL 파일을 임포트한다.

다음은 핸들러 구성에 사용할 수 있는 커스터마이제이션 파일의 예제이다.

wsimport 툴은 @HandlerChain 주석을 통해 SEI(Service Endpoint Interface)와 서비스 클래스를 생성한다.

@HandlerChain 주석이 SEI(사용자가 직접 주석을 지정했거나 wsimport에 의해 생성되었는지 여부와 상관 없이) 및 엔드포인트 구현 상에서 지정되는 경우에는 엔드포인트 구현 상에서 선언된 주석이 우선권을 가진다.

배치 기술자에서 핸들러 지정하기

사용자는 또한 <handler-chains> 엘리먼트를 이용하여 배치 기술자에서 핸들러를 지정할 수도 있다. 포트 구성요소 또는 서비스 상의 배치 기술자는 구현에서 지정된 @HandlerChain 주석을 오버라이드한다. 다음 예제는 웹 서비스를 위한 Java EE 배치 서술자에서 핸들러가 지정되는 방식을 보여준다.

사용자 삽입 이미지


여러분은 세 가지 방식( 배치 기술자, 엔드포인트 구현 상의 @HandlerChain 주석, SEI 상의 @HandlerChain 주석)을 모두 이용하여 핸들러를 지정하면 어떻게 될지 궁금해 할 수 있는데, 그 대답은 서버 상에서 핸들러는 다음의 서열에 따라 선택된다는 것이다. (1) 배치 기술자, (2) 엔드포인트 구현 상의 @HandlerChain 주석, (3) SEI 상의 @HandlerChain 주석.

핸들러 패키징 및 배치하기

사용자는 한 모듈 내의 핸들러 클래스와 그 종속 클래스를 핸들러 클래스를 참조하는 배치 기술자 정보와 함께 컨테인먼트(containment) 또는 레퍼런스로 패키징해야 한다. 앞서 논의한 것처럼 사용자는 배치 기술자에서 또는 @HandlerChain 주석을 통해 핸들러를 지정할 수 있으며, @HandlerChain 주석을 이용할 경우에는 주석에 식별된 핸들러 체인 파일을 동일한 모듈에 패키징해야 한다 -- 이렇게 하면 클래스 경로에서 리소스로 액세스할 수 있게 된다. 다시 말해, 서비스 패키징 시 handlers.xml 파일은 반드시 WAR 파일과 함께 클래스 경로 내에 있어야 한다(서비스 클래스 파일과 동일한 패키지 내의 WEB-INF/classes 바로 아래 또는 경로를 따라 더 아래쪽에).

요약

Java EE 웹 서비스 핸들러를 정의하는 일은 어렵지 않다. 즉, 간단히 @HandlerChain 주석을 이용하거나 JAX-WS 커스터마이제이션으로 핸들러를 구성하기만 하면 된다. NetBeans 5.5와 같은 개발자 툴에서는 핸들러 구성 방식이 훨씬 간편하여 사용자가 원하는 핸들러를 선택해서 클릭하기만 하면 된다.

예제 코드 실행하기

사용자는 본 팁의 예제 코드를 다음과 같이 실행할 수 있다.

  1. Java EE 5 SDK를 아직 구하지 못했다면 Java EE 다운로드 페이지에서 다운로드 받아 설치한다.

  2. 아래의 환경 변수를 설정한다:

    • JAVAEE_HOME. Java EE 5 SDK의 설치 장소를 표시해야 한다.
    • ANT_HOME. ant의 설치 장소를 표시해야 한다. ant는 다운로드한 Java EE 5 SDK 번들에 포함되어 있다. (Windows에서는 lib\ant 서브디렉토리에 위치함.)
    • JAVA_HOME. 사용자 시스템에서의 JDK 5.0 위치를 표시해야 한다. JDK는 다운로드한 Java EE 5 SDK 번들에 포함되어 있다. (Windows에서는 jdk 서브디렉토리에 위치함.)

    PATH 환경변수에 $JAVA_HOME/bin, $ANT_HOME/bin, $JAVAEE_HOME/bin을 추가한다.

  3. 예제 패키지를 다운로드하여 압축을 푼다. 이 때, 새로 압축이 풀린 디렉토리는 <sample_install_dir>/handler_config로 표시되어야 하는데, 여기서 <sample_install_dir>은 예제 패키지가 설치된 디렉토리이다.

  4. handler_config 디렉토리로 이동하여 build.properties 파일을 적절히 편집한다. 예를 들어 admin 호스트가 원격인 경우에는 admin.host의 값을 기본값(localhost)에서 적절한 원격 호스트로 변경하면 된다. 또한, javaee.server.passwordfile 위치가 정확한지 확인하고, 호스트 또는 포트가 변경된 경우에는 config-client.xml 파일 내의 wsdlLocation을 수정한다.

  5. 다음 명령어를 입력하여 애플리케이션 서버를 시작한다.

    $JAVAEE_HOME/bin/asadmin start-domain domain1

  6. 예제 서비스와 웹 클라이언트를 구축하고 배치한다. handler_config 디렉토리에서 아래 명령어를 입력한다:

    ant deploy

    그러면 웹 서비스가 구축되어 handler_config.war 파일이 생성되고, .war 파일이 배치된다. 아울러 웹 클라이언트가 생성되고 wsclient.war 파일이 배치된다.

  7. 클라이언트를 구축하고 예제를 실행한다. handler_config 디렉토리에서 아래 명령어를 입력한다:

    ant run

    그러면 wsimport가 호출되어 클라이언트 artifacts가 생성되고 예제가 실행된다. (다음 달 팁에서는 웹 서비스 클라이언트 상에서 핸들러를 구성하는 방법에 관해 설명할 예정이다.)

    예제에는 다음 5개의 핸들러 관련 테스트가 포함되어 있다:

    • test1은 JAX-WS WSDL 커스터마이제이션을 이용하여 프록시 상에서 구성되는 핸들러를 사용한다.
    • test2는 HandlerResolver를 이용하여 서비스 상에서 핸들러를 설정한다.
    • test3은 Dispatch 클라이언트를 포함하는 핸들러를 사용한다.
    • test4는 특정 포트에 대해 설정된 핸들러를 사용한다.
    • test5는 웹 서비스 레퍼런스 상에서 @HandlerChain의 사용을 예시하는 WebClient(서블릿)를 호출한다.

    다음은 예제의 test1 부분에서 표시되는 출력 내용이다.

사용자 삽입 이미지

 

저자 소개

Rama Pulavarthi는 썬 마이크로시스템즈 Java Web Services 그룹 기술팀 소속으로, 현재 JAX-WS 레퍼런스 구현 개발에 참여하고 있다. 이전에는 JAX-RPC를 위한 Software Quality Engineering 프로젝트를 이끈 바 있다.

"Java EE" 카테고리의 다른 글

2006/10/19 11:38 2006/10/19 11:38

TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/158

댓글을 달아 주세요

  1. 고진구  수정/삭제  댓글쓰기

    자바는 알면 알수록 재미가 있어지네요. 좋은 자료 잘 활용하겠습니다.

    2007/09/13 22:43
  2. 박정숙  수정/삭제  댓글쓰기

    좋은 정보 감사해요~

    2007/09/19 04:11
[로그인][오픈아이디란?]

◀ Prev 1  ... 343 344 345 346 347 348 349 350 351  ... 626  Next ▶