클라이언트 상에서 JAX-WS 핸들러 구성하기

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

지난 테크 팁인 JAX-WS 핸들러 구성, 패키징 및 배치하기 에서는
서버 상에서 웹 서비스를 위한 핸들러를 구성, 패키징, 배치하는 방법에 대해
살펴보았다. 본 팁에서는 웹 서비스 클라이언트 상에서 핸들러를 구성하는 다른
방법에 대해 알아보도록 한다.

JavaEE 5 SDK 다운로드?  http://java.sun.com/javaee/downloads/index.jsp
클 라이언트 상에서 JAX-WS 핸들러 구성하기 (-샘플 아카이브 다운로드 받기-)
http://java.sun.com/mailers/techtips/en ··· lers.zip


클라이언트 상에서 핸들러 사용하기

@HandlerChain 주석을 사용하거나 JAX-WS에 의해 정의되는 API를 통해 클라이언트
상에서 핸들러를 구성할 수 있으며, 구성은 핸들러 리졸버(resolver)에 의해 이루어진다.
Service 인스턴스는 핸들러 리졸버에 대한 액세스를 제공하고, 핸들러 리졸버는
서비스 당, 포트 당, 프로토콜 당 바인딩 방식으로 일련의 핸들러를 구성하게 된다.
Service 인스턴스를 사용하여 프록시나 Dispatch 인스턴스를 생성할 경우에는 현재
서비스에 등록되어 있는 핸들러 리졸버를 사용하여 필요한 핸들러 체인을 생성한다.

클라이언트 상에서 핸들러를 구성하는 방법은 클라이언트가 정적으로 생성되는지
(wsimport를 사용) 아니면 동적 클라이언트인지(Dispatch를 사용)의 여부에 따라 좌우된다.
일반적으로 정적 클라리언트를 사용하여 핸들러 구성을 지정하는 것이 더 수월한데,
왜냐하면 wsimport는 생성된 서비스 클래스에 @HandlerChain 주석을 자동으로 삽입해주기
때문이다. 이에 관한 부분은 2006년 8월 26일자 테크 팁의 "JAX-WS 커스터마이제이션을 통해 핸들러 구성하기" 섹션에 기술되어 있다.

아래 예제에는 핸들러 체인 정보가 첨부된 생성 서비스 클래스가 나와 있다.
서비스 클래스에 지정된 핸들러 체인 파일은 서비스를 위한 핸들러 리졸버를 정의하는데,
이는 해당 서비스를 이용하여 생성된 모든 프록시에 대한 핸들러 체인을 설정한다.


   @WebServiceClient(name = "HelloService1",
       targetNamespace = "http://example.com/handlers",
       wsdlLocation =
           "http://localhost:8080/service1/HelloService1?wsdl")
   @HandlerChain(file = "HelloService1_handler.xml")
   public class HelloService1
       extends Service
   {
   @WebEndpoint
   ...
   ...
   }
  
클라이언트가 Java EE 컨테이너에서 실행되는 웹 클라이언트나 애플리케이션 클라이언트인
경우에는 웹 서비스 레퍼런스 상에서 @HandlerChain 주석을 지정할 수 있다. 이렇게 하면
삽입된 서비스 상에 핸들러가 설정된다. 관련 예제는 다음과 같다.


   public class WebClient extends HttpServlet {
        @javax.jws.HandlerChain(file="myhandler.xml")
        @WebServiceRef HelloService2 service;

       public void doGet(HttpServletRequest req,
            HttpServletResponse resp)
            throws javax.servlet.ServletException {
       ...
       }
   }  
  
사용자는 또한 프로그램적으로 핸들러 리졸버를 설정하여 서비스를 위한 핸들러를 설정할 수 있는데, 이 방법은 Dispatch 기반의 클라이언트에서 널리 사용된다. 아래 예제는 서비스 상에 커스텀 핸들러 리졸버를 프로그램적으로 설정하는 경우를 보여주고 있다. 단, 핸들러 리졸버를 통해 구성 파일에서 지정된 것과 동일한 핸들러가 설정된다는 점에 유의할 것.


   Public void test2() {
        client.HelloService2 service =
             new client.HelloService2();
        // set new HandlerResolver
        service.setHandlerResolver(new MyHandlerResolver());
        ...
    }
 
   public class MyHandlerResolver implements HandlerResolver {
    
     public java.util.List<Handler>
          getHandlerChain(PortInfo portInfo) {      
       List<Handler> handlerChain = new ArrayList<Handler>();
       QName serviceQName = portInfo.getServiceName();
       if(serviceQName.getNamespaceURI().equals(
             "http://example.com/handlers") &&
             serviceQName.getLocalPart().startsWith(
                  "HelloService")) {
          handlers.common.LogicalLoggingHandler lh =
               new handlers.common.LogicalLoggingHandler();
          handlerChain.add(lh);
          handlers.common.SOAPLoggingHandler sh =
               new handlers.common.SOAPLoggingHandler();
          handlerChain.add(sh);
       }
       if(portInfo.getBindingID().equals(
            "http://schemas.xmlsoap.org/wsdl/soap/http")) {
          client.handlers.SOAP11Handler sh =
               new client.handlers.SOAP11Handler();
          handlerChain.add(sh);
       }
       if(portInfo.getBindingID().equals(
            "http://java.sun.com/xml/ns/jaxws/2003/0 ··· Fhttp%2F")) {
          client.handlers.SOAP12Handler sh =
               new client.handlers.SOAP12Handler();
          handlerChain.add(sh);
       }
       return handlerChain;
     }   
   }
  
사용자는 또한 BindingProvider 상에 직접 체인을 설정하여(가령, Dispatch 오브젝트 또는 포트 프록시) 런타임 시 클라이언트 측에 핸들러 체인을 구성할 수도 있다. 이 방법은 특정 포트를 위한 핸들러를 정의하고자 할 때 특히 유용할 수 있다. 관련 예제는 다음과 같다.

   public void test4() {
          client.HelloService1 service =
               new client.HelloService1();
          client.Hello1 port = service.getHello1Port();
          //List<Handler> handlerChain =
               ((BindingProvider)port).getBinding().getHandlerChain();
          client.handlers.SOAP11Handler sh =
               new client.handlers.SOAP11Handler();
          List<Handler> new_handlerChain =
               new ArrayList<Handler>();
          new_handlerChain.add(sh);
          ((BindingProvider)port).getBinding().setHandlerChain(new_handlerChain);

   } 

예제 코드 실행하기

지난 테크 팁, JAX-WS 핸들러 구성, 패키징 및 배치하기 웹 서비스 클라이언트 상에 핸들러를 구성하는 코드가 포함되어 있다. 예제를 실행하려면 다음 단계를 수행한다:

1. Java EE 5 SDK를 아직 구하지 못했다면 Java EE 다운로드 페이지에서 다운로드 받아 설치한다.
http://java.sun.com/javaee/downloads/index.jsp

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. 예제 패키지(http://java.sun.com/mailers/techtips/en ··· lers.zip)
를 다운로드하여 압축을 푼다. 이 때, 새로 압축이 풀린 디렉토리는
<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 파일이 배치된다.

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

      ant run

wsimport가 호출되어 클라이언트 artifacts가 생성되고 예제가 실행된다.

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

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

[java] ************ Start:test1 *************
   [java] Executing LogicalLoggingHandler
  
   [java] Outbound message:
   [java] <ns2:sayHello xmlns:ns2="http://example.com/handlers">
   [java] <arg0>Duke</arg0>
   [java] </ns2:sayHello>
   [java] Executing SOAPLoggingHandler
  
   [java] Outbound message:
   [java] <?xml version="1.0" ?><soapenv:Envelope xmlns:soapenv=
   "http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http:/
   /www.w3.org/2001/XMLSchema" xmlns "http://example.com/handler
   s"><soapenv:Body><ns2:sayHello xmlns:ns2="http:/example.com/h
   andlers"><arg0>Duke</arg0></ns2:sayHello></soapenv:Body></soa
   p:Envlope>
   [java] Executing SOAP11Handler
   [java] Executing SOAP11Handler
   [java] Verifying Inbound message
   [java] Executing SOAPLoggingHandler
  
   [java] Inbound message:
   [java] <?xml version="1.0" ?><soapenv:Envelope xmlns:soapenv=
   "http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http:/
   /example.com/handlers" xmlns:xsd="http://www.w3.org/2001/XMLS
   chema"><soapenv:Body><ns1:sayHelloResponse><return>Hello  Duk
   e!</return></ns1:sayHelloResponse></soapenv:Body></soapenv:En
   velope>
   [java] Executing LogicalLoggingHandler
  
   [java] Inbound message:
   [java] <ns1:sayHelloResponse xmlns:ns1="http://example.com/ha
   ndlers">
   [java] <return>Hello Duke!</return>
   [java] </ns1:sayHelloResponse>
   [java] Result = Hello Duke!
[java] ************ End:test1 ***************    

요약

JAX-WS는 사용자의 웹 서비스 클라이언트 상에서 핸들러를 구성하는 다양한 방법을 제공하며, 사용자는 각자의 애플리케이션에 가장 적합한 방법을 선택하면 된다.


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

2006/11/22 18:07 2006/11/22 18:07

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

댓글을 달아 주세요

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

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

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

    좋은 정보 감사해요~

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

◀ Prev 1  ... 329 330 331 332 333 334 335 336 337  ... 626  Next ▶