제6장 WSDL 문서에서 Java 클래스로 표준 바인딩 선언과 사용자화

내용 목차

6.1. 개요
6.2. 표준 바인딩 선언하기
6.2.1. 외부 문서(파일)에서 직접 선언
6.2.2. WSDL 문서 내에서 직접 선언
6.3. 표준 바인딩의 사용자화
6.3.1. 전체적인 바인딩
6.3.2. 패키지명의 사용자화
6.3.3. Wrapped 스타일
6.3.4. 비동기화
6.3.5. 프로바이더 인터페이스
6.3.6. 클래스명의 사용자화
6.3.7. Java 메소드의 사용자화
6.3.8. Java 파라미터의 사용자화
6.3.9. XML 스키마의 사용자화
6.3.10. 핸들러 체인의 사용자화

본 장에서는 표준 바인딩 선언 방법 및 사용자화에 대한 자세한 사항들을 알아본다.

6.1. 개요

앞에서 살펴본 바와 같이 기본적인 JAX-WS 웹 서비스는 Java 클래스로부터 혹은 WSDL 문서로부터 구현할 수 있다.

여기서 우리는 보다 확장 가능하고 다양한 기능을 제공하는 웹 서비스를 구현하기 위해서는 여러 가지 기능을 추가하거나 다양한 설정을 할 수 있다. 그 중 한 가지 방법은 그러한 기능이나 설정을 Java 클래스에 Annotation을 부여함으로써 wsgen 툴을 통해 얻을 수 있고, 또 다른 방법은 WSDL 문서에 직접 혹은 간접적으로 기능을 추가 하거나 설정하여 wsimport 툴을 통해 얻을 수 있다.

본 장에서는 WSDL 문서를 가지고 wsimport 툴을 통해 웹 서비스를 구성하거나 클라이언트를 구성할때 사용할 수 있는 바인딩 사용자화의 전체적인 모습에 대해 알아본다. 보다 자세한 기능에 대한 소개와 설정 사용법 및 Java 클래스로부터 wsgen 툴을 통해 원하는 웹 서비스를 구현하는 법은 계속되는 다음 장에서 살펴보기로 하겠다.

JEUS 웹 서비스는 WSDL 문서에서 Java 클래스로의 바인딩 선언 및 사용자화(주로 wsimport 툴을 가지고 작업하는 경우)를 JAX-WS에서 요구하는 표준화된 방식으로 지원한다. 기존 JAX-RPC 방식의 웹 서비스에서는 이러한 표준이 명세화되어 있지 않았기 때문에 서로 다른 벤더 사이에 포터블하지 않은 웹 서비스의 생성 문제를 야기시켰다.

이와 같은 JEUS 6 웹 서비스의 WSDL 문서에서 Java 클래스로의 표준화된 바인딩 선언 및 사용자화는 웹 서비스를 구현하는 데 있어서 2가지 역할을 하는데 이는 다음과 같다.

  • 거의 모든 WSDL 컴포넌트들로부터 서비스 Endpoint 인터페이스 클래스, 메소드 이름, 파라미터 이름, 예외(Exception) 클래스 등과 같은 Java 언어로의 매핑을 사용자화할 수 있다.

  • 비동기화, 프로바이더, 랩퍼 방식, 부가적인 헤더들과 같은 기능을 사용자화할 수 있다.

6.2. 표준 바인딩 선언하기

모든 바인딩에 관련된 element들은 http://java.sun.com/xml/ns/jaxws 이름 공간에 속하며 그 이름 공간에 속하는 접두어인 jaxws를 붙혀 jaxws:bindings라는 element로 바인딩을 선언하게 된다.

바인딩을 선언하는 장소에 따라 두 가지로 나뉠 수 있는데 하나는 외부 문서를 통해 바인딩을 선언하는 것이며 또 다른 하나는 바인딩할 WSDL 문서 내에 직접 바인딩 선언을 포함시키는 방법이다.

6.2.1. 외부 문서(파일)에서 직접 선언

외부 문서(파일)에서 직접 선언하는 방법은 주로 웹 서비스를 이용하는 클라이언트에 의해 wsimport 툴의 파라미터로 WSDL 문서의 위치와 함께 넘겨지게 된다. 여기서 쓰이는 WSDL 문서의 위치값은 다음과 같이 바인딩 선언 문서의 wsdlLocation이라는 element 값으로 추가한다.

[예 6.1] << custom-client.xml >>

<jaxws:bindings
    wsdlLocation="http://localhost:8080/AddNumbers/addnumbers?WSDL"
    jaxws:xmlns="http://java.sun.com/xml/ns/jaxws">
...
</jaxws:bindings>


또한 WSDL 문서 컴포넌트의 바인딩 설정을 위해서는 위에서 선언한 최상위 element 아래에 자식 element로써 추가한다. 선언할 바인딩에 해당하는 컴포넌트는 node라는 element 내에 XPath 문법으로 위치시킨다. 또한 그 컴포넌트에 대해 선언할 바인딩을 그 아래 자식 element로써 추가한다. 이는 다음과 같다.

[예 6.2] << custom-client.xml >>

<jaxws:bindings
    wsdlLocation="http://localhost:8088/AddNumbers/addnumbers?WSDL"
    jaxws:xmlns="http://java.sun.com/xml/ns/jaxws">
    <jaxws:bindings node="wsdl:definitions"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
        <jaxws:package name="customize.client"/>
        ...
</jaxws:bindings>


위의 예제에서 이 바인딩 선언은 WSDL 문서 내의 'wsdl:definitions'에 대해 생성되는 Java 클래스들에 대해 그 패키지명을 customize.client로 사용자화하겠다는 의미를 갖고 있음을 알 수 있다.

이와 같이 생성된 외부 바인딩 선언 문서는 wsimport 툴에서 다음과 같이 실행할 수 있다.

C:\>wsimport -b custom-client.xml http://localhost:8088/AddNumbers/addnumbers?WSDL

6.2.2. WSDL 문서 내에서 직접 선언

WSDL 문서 내에서 직접 선언하는 방법은 앞에서 설명한 외부 문서(파일)에서 직접 선언하는 방법과 약간 다른데 이는 다음과 같다.

  • WSDL 문서 내에 확장 element로 'jaxws:bindings' element를 사용한다.

  • WSDL 문서 내에서 선언할 경우 node 속성은 사용하지 않는다.

  • jaxws:bindings element 내에 자식 element로 'jaxws:bindings' element를 사용하지 않는다.

  • jaxws:bindings element는 그것을 감싸고 있는 WSDL 컴포넌트에만 영향을 준다.

[예 6.3] << AddNumbers.wsdl >>

<wsdl:portType name="AddNumbersImpl">
    <jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
        <jaxws:class name="MathUtil"/>
        ...
    </jaxws:bindings>
    <wsdl:operation name="addNumber">
    ...
</wsdl:portType>


위의 예제는 WSDL 문서 내에서 wsdl:portType에 대한 사용자화를 나타낸다.

jaxws:binding라는 확장 element는 이 wsdl:portType으로부터 생성되는 서비스 Endpoint 인터페이스 클래스의 이름에 대한 사용화를 나타내는데 표준 기본값으로 만들어지는 클래스 이름(여기에서는 AddNumbersImpl)을 MathUtil로 사용화할 것을 나타내고 있다.

6.3. 표준 바인딩의 사용자화

지금까지 바인딩을 선언하는 표준적인 방식에 대해 알아보았다. 본 절에서는 여러 가지 선언된 바인딩의 사용자화에 대해 자세히 알아보기로 한다.

이는 다음과 같이 구성되어 있다.

  • 전체적인 바인딩

  • 패키지명의 사용자화

  • Wrapped 스타일

  • 비동기화

  • 프로바이더 인터페이스

  • 클래스명의 사용자화

  • Java 메소드의 사용자화

  • Java 파라미터의 사용자화

  • XML 스키마의 사용자화

  • 핸들러 체인의 사용자화

6.3.1. 전체적인 바인딩

전체적인 바인딩은 외부 문서 파일로 정의된 바인딩 선언에서 유효하며 jaxws:bindings@wsdlLocation에 명시한 WSDL 문서의 wsdl:definition 내 전체에 적용된다.

<jaxws:package name="..."/> 
<jaxws:enableWrapperStyle/> 
<jaxws:enableAsyncMapping/>

전체적인 바인딩에 해당하는 element들은 위와 같다. 실제로 사용되는 예는 다음과 같다.

[예 6.4] << custom-client.xml >>

<jaxws:bindings
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    wsdlLocation="http://localhost:8080/AddNumbers/addnumbers?WSDL"
    xmlns="http://java.sun.com/xml/ns/jaxws">
        <package name="customize.client"/>
        <enableWrapperStyle>true</enableWrapperStyle>
        <enableAsyncMapping>false</enableAsyncMapping>
</jaxws:bindings>


6.3.2. 패키지명의 사용자화

기본값으로 wsimport 툴을 사용하여 WSDL 문서로부터 Java 클래스를 생성하는 경우 클래스의 패키지명은 그 WSDL 파일 문서의 이름공간에 따라 정해진다.

이러한 클래스의 패키지명을 사용자화하여 다른값으로 정하기 위해서는 jaxws:package element로 바인딩 사용자화 선언을 한다. wsimport 커맨드 라인으로 생성하는 경우 -p 옵션으로 패키지명을 변경할 수 있는데 이는 앞에서 jaxws:package element로 바인딩 사용자화한 것을 오버라이드한다.

예는 다음과 같다.

[예 6.5] << custom-client.xml >>

<jaxws:bindings
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    wsdlLocation="http://localhost:8080/AddNumbers/addnumbers?WSDL"
    xmlns="http://java.sun.com/xml/ns/jaxws">
        <package name="customize.client" />
...
</jaxws:bindings>


이는 줄여서 다음과 같이 나타낼 수도 있다.

[예 6.6] << custom-client.xml >>

<jaxws:bindings
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    wsdlLocation="http://localhost:8080
/jaxws-external-customize/addnumbers?WSDL"
    xmlns="http://java.sun.com/xml/ns/jaxws">
    <bindings node="wsdl:definitions">
        <package name="customize.client" />
...
</jaxws:bindings>


6.3.3. Wrapped 스타일

wsimport 툴은 기본값으로 WSDL 문서 내의 wsdl:portType으로 정의된 추상 오퍼레이션에 대해 Wrapped 스타일의 규칙을 적용한다. 이러한 Wrapped 스타일은 바인딩 사용자화에 의해 가능하지 않도록 할 수 있는데 예는 다음과 같다.

[예 6.7] << custom-client.xml >>

<jaxws:bindings
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    wsdlLocation="http://localhost:8080/AddNumbers/addnumbers?WSDL"
    xmlns="http://java.sun.com/xml/ns/jaxws">
        <enableWrapperStyle>true</enableWrapperStyle>
    <bindings node="wsdl:definitions/
        wsdl:portType[@name='AddNumbersImpl']/
        wsdl:operation[@name='addNumbers']">
        <enableWrapperStyle>false</enableWrapperStyle>
    ...
</jaxws:bindings>


위와 같이 jaxws:enableWrapperStyle element로써 설정할 수 있으며 wsdl:definitions, wsdl:portType, wsdl:operation element 하위에서 각각 사용될 수 있다. wsdl:defitions 아래에서 사용될 경우 모든 wsdl:portType 속성의 모든 wsdl:oprtations element들에 적용된다. wsdl:portType 하위에 사용될 경우 그 portType의 모든 wsdl:operations에 적용된다. wsdl:operation 하위에 적용될때는 그 오퍼레이션에 대해서만 적용된다.

6.3.4. 비동기화

클라이언트 애플리케이션은 jaxws:enableAsyncMappingbinding element를 선언함으로써 wsimport하는 경우 비동기 Polling 혹은 Callback 방식의 오퍼레이션들을 생성한다. 비동기 클라이언트 애플리케이션에 대해서는 “제9장 비동기 웹 서비스”에서 자세히 설명한다.

적용되는 WSDL 문서 내의 컴포넌트 및 적용 범위는 위에서 설명한 Wrapped 스타일의 규칙과 동일하다. 이를 사용한 예는 다음과 같다.

[예 6.8] << custom-client.xml >>

<jaxws:bindings
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    wsdlLocation="http://localhost:8080/AddNumbers/addnumbers?WSDL"
    xmlns="http://java.sun.com/xml/ns/jaxws">
        <enableAsyncMapping>false</enableAsyncMapping>
    <bindings node="wsdl:definitions/
        wsdl:portType[@name='AddNumbersImpl']/
        wsdl:operation[@name='addNumbers']">
        <enableAsyncMapping>true</enableAsyncMapping>
    ...
</jaxws:bindings>


6.3.5. 프로바이더 인터페이스

“제8장 프로바이더와 디스패치 인터페이스”에서 설명할 프로바이더(provider) 인터페이스를 바인딩 선언을 통해 설정하는 방법을 알아본다.

WSDL 문서 내의 어느 포트(port)를 프로바이더 인터페이스로 설정하고 싶을 때 wsdl:port 노드를 XPath 표현법으로 나타내고 jaxws:provider 바인딩을 설정하면 된다. 기본값은 설정하지 않음으로 되어 있다. 이는 웹 서비스를 WSDL로부터 생성하는 경우 유효하다.

6.3.6. 클래스명의 사용자화

WSDL 문서 내의 wsdl:portType, wsdl:fault, soap:headerfault, wsdl:server는 Java 클래스로 생성이 되는데 여기서 jaxws:class 바인딩 선언을 하면 원하는 클래스명으로 바꿀 수 있다. 이러한 WSDL 문서 내의 컴포넌트들에 대한 각각의 Java 클래스에 대한 설명은 다음과 같다.

6.3.6.1. 서비스 Endpoint 인터페이스 클래스

다음은 서비스 Endpoint 인터페이스 클래스명에 대한 바인딩 사용자화의 예이다.

[예 6.9] << custom-client.xml >>

<jaxws:bindings node="wsdl:definitions/wsdl:portType[@name='AddNumbersImpl']">
    <jaxws:class name="TmaxUtil" />
</jaxws:bindings>


위의 예에서 서비스 Endpoint 인터페이스 클래스명은 기본값인 AddNumbersImpl이 아닌 TmaxUtil이 된다.

6.3.6.2. 예외(Exception) 클래스

다음은 예외 클래스명에 대한 바인딩 사용자화의 예이다.

[예 6.10] << custom-client.xml >>

<jaxws:bindings node="wsdl:definitions/
    wsdl:portType[@name='AddNumbersImpl']/
    wsdl:operation[@name='addNumbers']/
    wsdl:fault[@name='AddNumbersException']">
    <jaxws:class name="TmaxException" />
</jaxws:bindings>


위의 예에서 예외(Exception) 클래스명은 기본값인 AddNumbersExeption이 아닌 TmaxException이 된다.

6.3.6.3. 서비스 클래스

다음은 서비스 클래스명에 대한 바인딩 사용자화의 예이다.

[예 6.11] << custom-client.xml >>

<jaxws:bindings node="wsdl:definitions/
    wsdl:service[@name='AddNumbersService']">
    <jaxws:class name="TmaxService" />
</jaxws:bindings>


위의 예에서 서비스 클래스명은 기본값인 AddNumbersService이 아닌 TmaxService이 된다.

6.3.7. Java 메소드의 사용자화

서비스 Endpoint의 메소드 이름 혹은 서비스 클래스의 포트를 가져오기 위한 메소드명을 사용자화하는 경우에는 jaxws:method 바인딩 선언을 이용한다.

6.3.7.1. 서비스 Endpoint 인터페이스 메소드

다음은 서비스 Endpoint 인터페이스의 메소드 이름을 변경하는 바인딩 선언의 예이다.

[예 6.12] << custom-client.xml >>

<jaxws:bindings node="wsdl:definitions/
    wsdl:portType[@name='AddNumbersImpl']/
    wsdl:operation[@name='addNumbers']">
    <jaxws:method name="add" />
</jaxws:bindings>


wsimport 툴은 서비스 Endpoint 인터페이스의 메소드 이름으로 기본값인 addNumbers 메소드 이름 대신 add라는 메소드 이름을 취한다.

6.3.7.2. 포트에 접근하기 위한 서비스 클래스의 메소드

다음은 포트에 접근하기 위한 서비스 클래스의 메소드 이름을 변경하는 바인딩 선언의 예이다.

[예 6.13] << custom-client.xml >>

<jaxws:bindings node="wsdl:definitions/
    wsdl:service[@name='AddNumbersService']/
    wsdl:port[@name='AddNumbersImplPort']">
    <jaxws:method name="getTmaxUtil" />
</jaxws:bindings>


wsimport 툴은 포트에 접근하기 위한 서비스 클래스의 메소드 이름으로 기본값인 getAddNumbersImplPort 대신 getTmaxUtil 이라는 메소드 이름을 취한다.

6.3.8. Java 파라미터의 사용자화

jaxws:parameter 바인딩 선언은 생성되는 Java 메소드의 파라미터 이름을 원하는 것으로 변경할 때 사용된다. wsdl:operation 혹은 wsdl:portType의 메소드 파라미터를 변경할 수 있다. 다음은 그 예이다.

[예 6.14] << custom-client.xml >>

<jaxws:bindings node="wsdl:definitions/
    wsdl:portType[@name='AddNumbersImpl']/
    wsdl:operation[@name='addNumbers']">
    <jaxws:parameter part="definitions/
        message[@name='addNumbers']/
        part[@name='parameters']"
    element="tns:number1" name="num1"/>
</jaxws:bindings>


위와 같이 이 바인딩 사용자화 선언은 wsdl:operation의 메소드 파라미터를 number1에서 num1으로 변경된 것을 알 수 있다.

6.3.9. XML 스키마의 사용자화

WSDL 문서 내에 선언된 XML 스키마는 jaxws:bindings element 하위에서 표준 JAXB 바인딩 element를 사용함으로써 변경할 수 있다.

다음은 이러한 JAXB 바인딩 element를 사용하는 예이다.

[예 6.15] << custom-client.xml >>

<jaxws:bindings node="wsdl:definitions/
    wsdl:types/
    xsd:schema[@targetNamespace='http://tmaxsoft.com']">
    <jaxb:schemaBindings>
        <jaxb:package name="fromwsdl.server"/>
    </jaxb:schemaBindings>
</jaxws:bindings>


또한 WSDL 문서에 의해 임포트(import)되는 XML 스키마 파일 또한 바인딩 사용화를 할 수 있는데, 이때에는 JAXB 표준 확장 바인딩 선언 파일을 사용한다.

다음은 이를 사용하는 예이다.

[예 6.16] << custom-client.xml >>

<jxb:bindings
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    version="1.0">
    <jxb:bindings
        schemaLocation=
            "http://localhost:8088/AddNumbers/schema1.xsd"
        node="/xsd:schema">
        <jxb:schemaBindings>
            <jxb:package name="fromjava.client"/>
        </jxb:schemaBindings>
    </jxb:bindings>
...


외부 표준 JAXB 바인딩 선언 파일은 wsimport 툴의 -b 스위치에 의해 전달된다.

6.3.10. 핸들러 체인의 사용자화

jaxws:bindings 바인딩 선언은 핸들러를 추가하거나 사용자화하는데에도 사용된다. 핸들러에 대한 자세한 사항은 “제7장 핸들러 프레임워크”를 참조한다.

바인딩 사용자화 선언에 핸들러 사항을 추가하거나 변경할때에는 핸들러 체인 설정에 관한 스키마(JAR 181)에 명시된 것과 같이 핸들러 체인 설정을 jaxws:bindings 안에 설정한다. 다음은 그 예이다.

[예 6.17] << custom-client.xml >>

<jaxws:bindings
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    wsdlLocation="http://localhost:8080/jaxws-fromwsdlhandler/
        addnumbers?WSDL"
    xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
    xmlns:javaee="http://java.sun.com/xml/ns/javaee">
    <jaxws:bindings node="wsdl:definitions">
        <javaee:handler-chain>
            <javaee:handler-chain-name>
                LoggingHandlers
            </javaee:handler-chain-name>                    
            <javaee:handler>
                <javaee:handler-name>Logger</javaee:handler-name>
                <javaee:handler-class>
                    fromwsdlhandler.common.LoggingHandler
                </javaee:handler-class>          
            </javaee:handler>                        
        </javaee:handler-chain>
    </jaxws:bindings>
</jaxws:bindings>


이와 같은 외부 바인딩 선언 문서와 WSDL 문서를 wsimport 툴을 통해 Portable Artifact들을 생성하면 핸들러 설정 파일이 또한 생성된다. 생성된 서비스 Endpoint 인터페이스 클래스에는 JAX-WS 런타임이 핸들러들을 찾기 위한 @javax.jws.HandlerChain Annotation이 추가된다.