웹 서비스 생성과 배치

본 장에서는 JAX-WS 웹 서비스를 Java 클래스와 WSDL 파일로부터 생성하고 deploy하여 패키징하는 방법에 대해 설명한다. 또한 JAX-WS 웹 서비스를 JEUS 21에서 동작시키는 방법에 대해 설명한다.

1. 개요

기본적으로 웹 서비스를 Java 클래스로부터 구현하든 WSDL로부터 구현하든 배치하는 과정은 거의 동일하다. JAX-WS 웹 서비스는 POJO 방식의 웹 서비스 구현을 지향하므로 이러한 DD의 개수는 JAX-RPC 웹 서비스에 비해 대폭적으로 줄어든다.

JEUS 5 JAX-RPC 방식 웹 서비스의 구현에서 일반적으로 사용되었던 DD 없이 프로그래밍할 수 있고, 이것은 웹 서비스 개발자가 매우 쉽고 빠르고 편리하게 웹 서비스를 개발하도록 도와준다(Description-free programming).

2. Java 클래스 웹 서비스 생성과 배치

Java 클래스로부터 구현한 웹 서비스를 WAR 파일로 구성하는 것은 서비스 Endpoint 구현 클래스와 그 밖의 Java 클래스들(Portable Artifact들)을 여러 DD 파일과 함께 WAR 포맷으로 묶는 것을 의미한다.

다음은 이전 장에서 Java 클래스로부터 구현한 웹 서비스를 WAR 형태로 구성하는 모습을 디렉터리별로 나타낸 것이다.

META-INF/MANIFEST.MF
WEB-INF/classes/AddNumbersImplService_schema1.xsd
WEB-INF/classes/AddNumbersImplService.wsdl
WEB-INF/classes/fromjava/server/AddNumbersImpl.class
WEB-INF/classes/fromjava/server/jaxws/AddNumbers.class
WEB-INF/classes/fromjava/server/jaxws/AddNumbersResponse.class

위의 WAR 파일은 서비스 Endpoint 구현 클래스와 Portable Artifact 클래스들과 함께 유일한 DD인 web.xml로 구성된다. 사실 JAX-WS 웹 서비스의 구현에는 web.xml 파일조차 필요가 없으나 여기서는 원하는 Endpoint 주소를 얻기 위해 web.xml을 사용하였다. Endpoint 주소에 대한 보다 자세한 사항은 Endpoint 주소 결정 방식을 참고한다.

이와 같이 생성된 웹 서비스 WAR 파일은 JEUS 21에서 제공하는 방식으로 deploy되어 접근할 수 있다. 생성된 WAR 파일을 JEUS 21에 deploy하기 위해 콘솔에서 다음의 명령을 실행한다.

$ ant build deploy

정상적으로 deploy되면 실제 이 서비스에 접근할 수 있는 실제 주소는 다음과 같다.

http://host:port/AddNumbers/AddNumbersImplService

3. EJB 웹 서비스 생성과 배치

Java 클래스로부터 구현한 웹 서비스를 JAR 파일로 구성하는 것은 서비스 Endpoint 구현 클래스와 그 밖의 Java 클래스(Portable Artifact)들을 여러 DD 파일과 함께 JAR 포맷으로 묶는 것을 의미한다.

다음은 이전 장에서 EJB Stateless Session Bean으로부터 구현한 웹 서비스를 JAR 형태로 구성하는 모습을 디렉터리별로 나타낸 것이다.

META-INF/MANIFEST.MF
fromejb/server/AddNumbersImpl.class
fromejb/server/jaxws/AddNumbers.class
fromejb/server/jaxws/AddNumbersResponse.class

위의 JAR 파일은 서비스 Endpoint 구현 클래스와 Portable Artifact 클래스들로 이루어진다. Endpoint 주소에 대한 보다 자세한 사항은 Endpoint 주소 결정 방식을 참고한다.

이와 같이 생성된 웹 서비스 JAR 파일은 JEUS 21에서 제공하는 방식으로 deploy되어 접근할 수 있다. 생성된 JAR 파일을 JEUS 21에 deploy하기 위해 콘솔에서 다음과 같은 명령을 실행한다.

$ ant build deploy

정상적으로 deploy되면 이 서비스에 접근할 수 있는 실제 주소는 다음과 같다.

http://host:port/AddNumbersImplService/AddNumbersImpl

4. WSDL 웹 서비스 생성과 배치

WSDL로부터 구현한 웹 서비스를 WAR 파일을 구성하는 것은 서비스 Endpoint 인터페이스와 그것을 구현한 서비스 Endpoint 클래스 그리고 그 밖의 Portable Artifact들을 여러 DD 파일과 함께 WAR 포맷으로 묶는 것을 의미한다.

다음은 이전 장에서 WSDL로부터 구현한 웹 서비스를 WAR 형태로 구성하는 모습을 디렉터리별로 나타낸 것이다.

META-INF/MANIFEST.MF
WEB-INF/wsdl/AddNumbers.wsdl
WEB-INF/classes/fromjava/server/AddNumbers.class
WEB-INF/classes/fromjava/server/AddNumbersImpl.class
WEB-INF/classes/fromjava/server/AddNumbersPortType.class
WEB-INF/classes/fromjava/server/AddNumbersResponse.class
WEB-INF/classes/fromjava/server/AddNumbersService.class
WEB-INF/classes/fromjava/server/ObjectFactory.class
WEB-INF/classes/fromjava/server/package-info.class

위의 WAR 파일은 서비스 Endpoint 인터페이스인 AddNumbersPortType과 이를 구현하는 AddNumbersImpl 그리고 여러 가지 Portable Artifact 클래스들과 함께 유일한 DD인 web.xml 파일들로 구성된다. 사실 JAX-WS 웹 서비스의 구현에는 web.xml 파일조차 필요가 없으나 여기서는 원하는 Endpoint 주소를 얻기 위해 web.xml을 사용하였다. Endpoint 주소에 대한 보다 자세한 사항은 Endpoint 주소 결정 방식을 참고한다.

이와 같이 생성된 웹 서비스 WAR 파일은 JEUS 21에서 제공하는 방식으로 deploy되어 웹 서비스로 공개될 수 있다. 생성된 WAR 파일을 JEUS 21에 deploy하기 위해 콘솔에서 다음과 같은 명령을 실행한다.

$ ant build deploy

정상적으로 deploy되면 실제 이 서비스에 접근할 수 있는 실제 주소는 다음과 같다.

http://host:port/AddNumbers/AddNumbersService

5. Endpoint 주소 결정 방식

JAX-WS 웹 서비스는 web.xml을 비롯한 webservices.xml 등의 기존 JEUS 5의 JAX-RPC 웹 서비스에서 필요했던 DD 파일이 없어도(Descriptor-free) JEUS 21에 deploy가 가능하다.

본 절에서는 서블릿 기반의 웹 서비스와 EJB 기반의 웹 서비스에 대해 이러한 JAX-WS가 JEUS 21에 deploy될 때 실제로 이 서비스에 접근할 수 있는 각각의 주소 결정 방식을 설명한다.

5.1. 서블릿 Endpoint

서블릿 Endpoint의 경우 URL 결정 우선순위는 다음과 같다.

  1. web.xml 파일의 <url-pattern>을 사용하는 경우

    web.xml 파일의 <url-pattern>을 사용하는 경우 입력된 값이 실제 이 웹 서비스에 접근할 수 있는 URL 주소이다. 이는 @EndpointDescription Endpoint 주소의 기본값을 overwrite한다.

    다음은 web.xml 파일과 AddNumbersImpl과 같은 Endpoint 클래스의 예이다.

    web.xml 파일의 <url-pattern> 사용 : <web.xml>
    <web-app>
        <display-name>fromwsdl</display-name>
        <description>fromwsdl</description>
        <servlet>
            <servlet-name>fromwsdl</servlet-name>
            <display-name>fromwsdl</display-name>
            <servlet-class>fromwsdl.server.AddNumbersImpl</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>fromwsdl</servlet-name>
            <url-pattern>/addnumbers</url-pattern>
        </servlet-mapping>
    </web-app>
    Endpoint 클래스 : <AddNumbersImpl.java>
    @WebService(serviceName="AddNumbers")
    @EndpointDescription(endpointUrl="MyService")
    public class AddNumbersImpl {
    
        public int addNumbers(int number1, int number2) {
            return number1 + number2;
        }
    }

    이 웹 서비스에 접근할 수 있는 실제 URL 주소는 다음과 같다.

    http://server:port/context/addnumbers
  2. @EndpointDescription Annotation을 사용하는 경우

    @EndpointDescription라는 Annotation에 endpointUrl이라는 변수값이 정해져 있을 경우에는 이 값이 실제 이 웹 서비스에 접근할 수 있는 URL 주소이다. 이는 @WebService Annotation의 serviceName Endpoint 주소값을 overwrite한다.

    다음은 Endpoint 클래스의 예이다.

    @EndpointDescription Annotation 사용 : <AddNumbersImpl.java>
    @WebService(serviceName="AddNumbers")
    @EndpointDescription(endpointUrl="MyService")
    public class AddNumbersImpl {
    
        public int addNumbers(int number1, int number2) {
            return number1 + number2;
        }
    }

    이 웹 서비스에 접근할 수 있는 실제 URL 주소는 다음과 같다.

    http://server:port/context/MyService
  3. @WebService Annotation의 serviceName 속성을 사용하는 경우

    @WebService라는 Annotation에 serviceName이라는 변수값이 정해져 있을 경우에는 이 값이 실제 이 웹 서비스에 접근할 수 있는 URL 주소이다. 이는 Endpoint 주소의 기본값을 overwrite한다.

    다음은 Endpoint 클래스의 예이다.

    @WebService Annotation의 serviceName 속성 사용 : <AddNumbersImpl.java>
    @WebService(serviceName="AddNumbers")
    public class AddNumbersImpl {
    
        public int addNumbers(int number1, int number2) {
            return number1 + number2;
        }
    }

    이 웹 서비스에 접근할 수 있는 실제 URL 주소는 다음과 같다.

    http://server:port/context/AddNumbers
  4. Endpoint 주소의 기본값 + "Service" 사용

    @WebService라는 Annotation 이외에 아무런 설정이 없다면 기본값으로 'Endpoint 클래스 이름 + Service’가 이 웹 서비스의 Endpoint 주소의 기본값이다.

    다음은 Endpoint 클래스의 예이다.

    Endpoint 클래스 : <AddNumbersImpl.java>
    @WebService
    public class AddNumbersImpl {
    
        public int addNumbers(int number1, int number2) {
            return number1 + number2;
        }
    }

    이 웹 서비스에 접근할 수 있는 실제 URL 주소는 다음과 같다.

    http://server:port/context/AddNumbersImplService

5.2. EJB Endpoint

EJB Endpoint의 경우 Endpoint URL 결정 우선순위는 서블릿 Endpoint의 경우와 같고, 컨텍스트의 결정 방식만 다르다.

컨텍스트의 결정 우선순위는 다음과 같다.

  1. @EndpointDescription Annotation을 사용하는 경우

    • Endpoint

      @EndpointDescription라는 Annotation에 endpointUrl이라는 변수값이 정해져 있을 경우에는 이 값이 실제 이 웹 서비스에 접근할 수 있는 URL 주소이다. 이는 @WebService Annotation의 name Endpoint 주소값을 overwrite한다.

      다음은 Endpoint 클래스의 예이다.

      @EndpointDescription Annotation 사용 (1) : <AddNumbersImpl.java>
      @WebService(name="AddNumbersService")
      @EndpointDescription(endpointUrl="MyService")
      @Stateless
      public class AddNumbersImpl {
      
          public AddNumbersImpl() {
      
          }
      
          public int addNumbers(int number1, int number2) {
              return number1 + number2;
          }
      }

      이 웹 서비스에 접근할 수 있는 실제 URL 주소는 다음과 같다.

      http://server:port/context/MyService
    • Context

      @jeus.webservices.annotation.EndpointDescription Annotation에 contextPath 속성을 사용하는 경우 컨텍스트 기본값을 overwrite한다.

      다음은 Endpoint 클래스에 대한 예이다.

      @EndpointDescription Annotation 사용 (2) : <AddNumbersImpl.java>
      @WebService(name="Hello", serviceName="AddNumbersService")
      @jeus.webservices.annotation.EndpointDescription(contextPath="EJBService",
          endpointUrl="MyEndpoint")
      @Stateless
      public class AddNumbersImpl {
      
          public AddNumbersImpl() {
      
          }
      
          public int addNumbers(int number1, int number2) {
              return number1 + number2;
          }
      }

      이 웹 서비스에 접근할 수 있는 실제 URL 주소는 다음과 같다.

      http://server:port/EJBService/MyEndpoint
  2. @WebService Annotation의 serviceName 속성을 사용하는 경우

    • Endpoint

      @WebService라는 Annotation에 name이라는 변수값이 정해져 있을 경우에는 이 값이 실제 이 웹 서비스에 접근할 수 있는 URL 주소이다. 이는 Endpoint 주소의 기본값을 overwrite한다.

      다음은 Endpoint 클래스의 예이다.

      @WebService Annotation의 serviceName 속성 사용 (1) : <AddNumbersImpl.java>
      @WebService(name="AddNumbersService")
      @Stateless
      public class AddNumbersImpl {
      
          public AddNumbersImpl() {
      
          }
      
          public int addNumbers(int number1, int number2) {
              return number1 + number2;
          }
      }

      이 웹 서비스에 접근할 수 있는 실제 URL 주소는 다음과 같다.

      http://server:port/context/AddNumbersService
    • Context

      @WebService Annotation에 serviceName 속성을 사용하는 경우 컨텍스트 기본값을 overwrite한다.

      다음은 Endpoint 클래스의 예이다.

      @WebService Annotation의 serviceName 속성 사용 (2) : <AddNumbersImpl.java>
      @WebService(name="Hello", serviceName="AddNumbersService")
      @Stateless
      public class AddNumbersImpl {
      
          public AddNumbersImpl() {
      
          }
      
          public int addNumbers(int number1, int number2) {
              return number1 + number2;
          }
      }

      이 웹 서비스에 접근할 수 있는 실제 URL 주소는 다음과 같다.

      http://server:port/AddNumbersService/Hello
  3. 컨텍스트의 기본값

    • Endpoint

      @WebService라는 Annotation 이외에 아무런 설정이 없다면 기본값으로 Endpoint 클래스 이름이 이 웹 서비스의 Endpoint 주소의 기본값이다.

      다음은 Endpoint 클래스의 예이다.

      컨텍스트의 기본값 사용 Endpoint 클래스 : <AddNumbersImpl.java>
      @WebService
      @Stateless
      public class AddNumbersImpl {
      
          public AddNumbersImpl() {
      
          }
      
          public int addNumbers(int number1, int number2) {
              return number1 + number2;
          }
      }

      이 웹 서비스에 접근할 수 있는 실제 URL 주소는 다음과 같다.

      http://server:port/context/AddNumbersImpl
    • Context

      컨텍스트(context) 기본값은 그 웹 서비스의 WSDL 문서의 ServiceName이다. 또한, 이 ServiceName은 Endpoint 클래스 이름에 Service를 붙힌 값이 기본값으로 설정된다.

      따라서 위의 Endpoint 클래스의 웹 서비스에 대해 다음과 같은 주소로 접근할 수 있다.

      http://server:port/AddNumbersImplService/AddNumbersImpl