웹 서비스를 통한 유형 대체 사용

Java SE 2007/10/09 15:02 Posted by Sun
저자 Doug Kohlert는 Sun Microsystems 웹 기술 및 표준 부문의 수석 스탭 엔지니어로서 JAX-WS 규격의 책임자로 일하고 있습니다.

이 아티클의 영문 원본은
http://java.sun.com/mailers/techtips/en ··· html%231
에서 볼수 있습니다.

JAXB(Java Architecture for XML Binding) 2.1에서는 JAXB가 추가 유형을 인식하도록 사용할 수 있는 새로운 @XmlSeeAlso 주석을 선보였다. JAX-WS(Java API for XML-Based Web Services) 2.1에서도 SEI(service endpoint interface)에서 추상 클래스 사용이 가능하도록 @XmlSeeAlso 주석을 사용한다. JAX-WS 2.1을 이용하면 SEI에서 @XmlSeeAlso 주석을 지정할 수 있다. JAX-WS는 런타임 시 이 주석을 읽어 주석에서 참조한 모든 클래스를 JAXBContext를 통해 JAXB로 전달한다. JAXB 및 JAX-WB에서 @XmlSeeAlso 주석을 사용하면 상속을 보충하는 하위 클래스 개념인 유형 대체(type substitution)를 지원할 수 있다.

이번 팁에서는 유형 대체를 사용하는 간단한 웹 서비스와 그 서비스를 사용하는 클라이언트의 개발 방법에 대해 알아본다. Java 클래스 및 WSDL 파일로부터 웹 서비스를 빌드하는 방법도 소개한다.

샘플 애플리케이션이 이 팁에 제공된다. 팁의 코드 예제는 샘플 애플리케이션의 소스 코드에서 가져온 것이다.

웹 서비스에서 유형 대체 사용

웨이크보드 및 관련 장비를 판매하는 상점을 위해 재고를 관리하는 웹 서비스를 만들려 한다고 가정한다. 웨이크보드는 부양성 소재로 만든 숏 보드로서 주로 보트 뒤에 연결하거나 케이블 스키 기구와 함께 사용하면서 수면 위를 활주할 때 쓰인다.

간단히 이 상점은 세 가지 유형의 품목, 즉 웨이크보드, 바인딩과 보트용 타워만 판매한다고 가정한다. 웹 서비스는 매우 간단하게 사용할 수 있고 노출되는 연산의 양이 최소화되어야 한다. 간소화를 위해 웹 서비스에서는 유형별 연산을 사용하지 않고 추상 Item 클래스를 연산에 사용한다. 다음 Item 클래스는 웹 서비스를 통해 노출하려는 재고 개체를 모델링할 때 사용할 수 있다.

   public abstract class Item implements Serializable {
       private long id;
       private String brand;
       private String name;
       private double price;
       ...      
   }

Item 클래스를 확장하면서 다음 Wakeboard, WakeboardBindingTower 클래스를 정의할 수 있다.

   public class Wakeboard extends Item {
       private String size;      
   }
   
   public class WakeboardBinding extends Item {
       private String size;      
   }

   public class Tower extends Item {
       private Fit fit;    
       private String tubing;
   
       public static enum Fit { Custom, Exact, Universal };      
   }

이 예제에서는 유형 대체를 다루므로 Wearable 추상 클래스를 도입하여 상속 계층 구조를 더 흥미롭게 만들어 본다. WearableWakeboardWakeboardBinding 클래스의 크기 속성을 보유한다. Wearable 클래스는 다음과 같이 정의된다.

   public abstract class Wearable extends Item {
       protected String size;      
   }

그리고 그 결과 WakeboardWakeboardBinding 클래스는 다음과 같다.

   public class Wakeboard extends Wearable {   
   }

   public class WakeboardBinding extends Wearable {   
   }

또한 웹 서비스가 재고를 관리하므로, JPA라고도 부르는 Java Persistence API를 사용하여 재고 항목이 데이터베이스에서 지속되게 할 것이다. 그러기 위해서는 지속될 클래스 각각에 @Entity 주석을 추가해야 한다. 유일하게 지속시키지 않을 클래스는 Wearable 클래스일 것이다. 이 클래스에 @MappedSuperclass 주석을 추가하여 JPA가 하위 클래스를 지속시킬 목적으로 이 클래스의 속성을 사용하게 할 수 있다. 그런 다음 @Id@GeneratedValue(strategy = GenerationType.AUTO) 주석을 Item.Id 필드에 추가해야 한다. 그 결과, 이 필드는 데이터베이스에서 기본 키로 사용되며 ID가 제공되지 않으면 자동으로 생성된다. 마지막으로, 나중에 새로운 Item 유형을 시스템에 추가할 수도 있으므로 @Inheritance(strategy=InheritanceType.JOINED) 주석을 Item 클래스에 추가해야 한다. 그러면 각 하위 클래스를 각자의 데이터베이스 테이블에 저장하게 된다.

최종 데이터 클래스는 다음과 같이 된다.

   @Entity
   @Inheritance(strategy=InheritanceType.JOINED)
   public abstract class Item implements Serializable {
       @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       private Long id;
       private String brand;
       private String itemName;
       private double price;

       // Getters & setters
       ...      
   }

   @MappedSuperclass
   public abstract class Wearable extends Item {
       protected String size;
       ...
   }

   @Entity
   public class Wakeboard extends Wearable {}

   @Entity
   public class WakeboardBinding extends Wearable {}

   @Entity
   public class Tower extends Item {
       private Fit fit;    
       private String tubing;
   
       public static enum Fit { Custom, Exact, Universal };
       ...      
   }

애플리케이션의 데이터 모델을 정의했으므로 이제 웹 서비스 인터페이스를 정의할 수 있다. 애플리케이션에서 웨이크보드 장비 정보를 관리하므로 웹 서비스를 WakeRider라고 부르고 웹 서비스에서 addItem, updateItem, removeItem 그리고 getItems의 네 개 연산을 노출하도록 한다.

WakerRider 클래스는 다음과 같다.

   @WebService()
   public class WakeRider {
       ...
       public List<Item> getItems() {...}
 
       public boolean addItem(Item item) {...}
   
       public boolean updateItem(Item item) {...}

       public boolean removeItem(Item item) {...}
   }

이 웹 서비스를 배포한 다음 생성된 WSDL과 스키마를 보면 Item 유형만 정의되었음을 알 수 있다. Wearable, Wakeboard, WakeboardBinding 또는 Tower에 대한 언급이 없다. 이는 JAX-WS가 WakeRider 클래스를 검사할 때 나머지 클래스에 대한 언급이 없기 때문이다. 이 문제를 해결하기 위해 새로운 @XmlSeeAlso 주석을 사용하고 노출하려는 나머지 클래스를 WakeRider 웹 서비스를 통해 나열할 수 있다.

@XmlSeeAlso 주석이 있는 WakeRider 클래스는 다음과 같다.

   @WebService()
   @XmlSeeAlso({Wakeboard.class,
                WakeboardBinding.class,
                Tower.class})  
   public class WakeRider {
       ...
   }

이제 WakeRider 서비스를 배포하고 생성된 스키마를 보면 Item, Wearable, Wakeboard, WakeboardBindingTower 유형을 비롯하여 JAX-WS 및 JAXB에서 내부적으로 사용하는 다른 유형도 나타난다.

WSDL에서 시작

WSDL 파일로부터 작성된 웹 서비스에서 유형 대체를 사용할 수 있다. 이 방법에서 특히 좋은 점은 WSDL에서 시작할 때 유형 대체를 사용하는 작업이 완전히 투명하다는 것이다. JAX-WS 2.1을 사용하여 WSDL 파일을 가져올 때 생성된 프록시 클래스는 알맞은 @XmlSeeAlso 주석을 가져야 한다. 예를 들어, 이전 섹션의 웹 서비스 예제에 나온, 가져온 WakeRider 프록시는 다음과 같이 @XmlSeeAlso 주석을 갖게 된다.

   @WebService(name="WakeRider",            
               targetNamespace="http://wakerider/")
   @XmlSeeAlso({ObjectFactory.class})
   public interface WakeRider {
       ...
   }

프록시의 @XmlSeeAlso 주석은 클래스를 나열하지 않고 ObjectFactory.class를 포함한다. ObjectFactory 클래스는 JAXB가 해당 패키지에서 인식해야 하는 모든 Java 유형에 대한 정보를 제공하는 JAXB 필수 클래스이다. 이 예제에서 ObjectFactory 클래스는 Item, Wearable, Wakeboard, WakeboardBindingTower 클래스에 대한 참조를 갖는다. WSDL에서 시작할 때 유형 대체를 가능하게 하기 위해 해야 하는 작업은 없다.

WakeRider 클라이언트

클라이언트로부터 WakeRider 웹 서비스를 호출하는 것은 JAX-WS를 사용하는 다른 웹 서비스를 호출하는 것과 동일하다. 생성된 WakeRider 웹 서비스로부터 WakeRider 프록시를 가져오고 프록시에 대해 연산을 호출하면 된다. 이 팁에 제공된 샘플 애플리케이션은 wrmanager라는 Java SE 애플리케이션을 위한 NetBeans 5.5.1 프로젝트를 포함한다. 이 애플리케이션을 사용하여 WakeRider 웹 서비스 재고에서 항목을 추가, 제거하거나 편집할 수 있다.

또한 wrviewer라는 JSF(JavaServer Faces) 기술 애플리케이션을 위한 NetBeans 5.5.1 프로젝트도 있다. 이 애플리케이션에서는 WakeRider 웹 서비스를 사용하여 현재 재고를 조회한다.

두 클라이언트 애플리케이션 모두 WakeRider 웹 서비스에 대한 연산을 호출하기 위해 다음과 비슷한 코드를 포함한다.

   WakeRiderService service = new WakeRiderService();
   port = service.getWakeRiderPort();
   List<Item> items = port.getItems();
   for (Item item : items) {
       if (item instanceof Wakeboard) {
           ...
       } else if (Item instance of WakeboardBinding) {
        ...
       } else if (Item instance of Tower) {
           ...
       }
   }

샘플 코드 실행하기

이 팁의 샘플 코드는 세 개의 NetBeans 프로젝트로 제공된다.

  • wrservice. WakeRider 종점을 정의한다.
  • wrviewer. WakeRider 재고를 조회하는 JSF페이지이다.
  • wrmanager. WakeRider에서 항목을 추가, 제거하고 편집하는 Java SF 애플리케이션이다.

다음과 같이 NetBeans 5.5.1 IDE를 사용하여 샘플 코드를 빌드하고 실행할 수 있다.

  1. NetBeans 5.5.1 IDE가 없으면 다운로드하여 설치한다.

  2. GlassFish V2 RC 4 이상이 없으면 다운로드하여 설치한다.

  3. 팁의 샘플 애플리케이션을 다운로드하고 압축을 푼다. 이제 압축이 풀린 새 디렉토리, <sample_install_dir>/wakerider가 나타나며, 여기서 <sample_install_dir>은 샘플 애플리케이션을 설치한 디렉토리이다. 예를 들어, Windows 시스템의 C:\에 해당 컨텐츠의 압축을 풀었다면 새로 생성된 디렉토리는 C:\wakerider에 있어야 한다. wakerider 디렉토리는 NetBeans 프로젝트, 즉 wrservice, wrviewerwrmanager별로 하나의 디렉토리를 포함한다.

  4. NetBeans IDE를 시작한다. JDK 5.0으로 Netbeans를 실행한다. 또한 JDK 6을 사용할 수도 있는데, 그러한 경우 JDK 6의 상위에서 실행하기의 지침을 따라야 한다.

  5. 다음과 같이 GlassFish V2를 NetBeans Application Server에 추가한다.

    • Runtime 창에서 Servers 노드를 마우스 오른쪽 버튼으로 클릭한다.
    • Add Server를 선택한다.
    • Server는 Sun Java System Application Server로 유지한다.
    • Next 버튼을 클릭한다.
    • Browse 버튼을 클릭하고 GlassFish V2를 설치한 위치로 이동한다.
    • Choose 버튼을 클릭한다.
    • Next 버튼을 클릭한다.
    • GlassFish에 다른 비밀번호를 선택하지 않았다면 Admin Password를 기본값인 adminadmin으로 설정한다.
    • Finish 버튼을 클릭한다.

  6. 다음과 같이 wrservice 프로젝트를 연다.

    • File 메뉴에서 Open Project를 선택한다.
    • 샘플 애플리케이션 다운로드에서 wrservice 디렉토리로 이동한다.
    • Open Project Folder 버튼을 클릭한다.
    • "Missing Server Problem"이라는 경고 메시지가 나타나면 Projects 창에서 wrservice 노드를 마우스 오른쪽 버튼으로 클릭하고 Resolve Missing Server Problem을 선택하여 해결한다. 그런 다음 Sun Java System Application Server를 선택한다.

  7. 다음과 같이 wrservice 프로젝트를 배포한다.

    • Projects 창에서 wrservice 노드를 마우스 오른쪽 버튼으로 클릭한다.
    • Deploy Project를 선택한다.

  8. 다음과 같이 wrviewer 프로젝트를 연다.

    • File 메뉴에서 Open Project를 선택한다.
    • 샘플 애플리케이션 다운로드에서 wrviewer 디렉토리로 이동한다.
    • Open Project Folder 버튼을 클릭한다.
    • 서버 누락 문제가 생기면 6단계에서 설명한 대로 해결해야 한다.

  9. 다음과 같이 wrviewer를 실행한다.

    • Projects 창에서 wrviewer 노드를 마우스 오른쪽 버튼으로 클릭한다.
    • Run Project를 선택한다. 그러면 현재 WakeRider 재고를 표시하는 창이 웹 브라우저에 열린다. 맨 처음 wrviewer를 실행할 때 재고가 빈 상태이어야 한다.

    Wake Rider Inventory
    WakeRider Inventory

  10. 다음과 같이 wrmanager 프로젝트를 연다.

    • File 메뉴에서 Open Project를 선택한다.
    • 샘플 애플리케이션 다운로드에서 wrmanager 디렉토리로 이동한다.
    • Open Project Folder 버튼을 클릭한다.

  11. 다음과 같이 wrmanager를 실행한다.

    • Projects 창에서 wrmanager 노드를 마우스 오른쪽 버튼으로 클릭한다.
    • Run Project를 선택한다. 그러면 WakeRider Inventory Manager 애플리케이션이 열린다.
    WakeRider Inventory Manager
  12. 다음과 같이 재고 항목을 추가, 삭제, 편집하거나 조회한다.
    • 항목을 추가하려면 WakeRider Inventory Manager 애플리케이션에서 Add 버튼을 클릭하고 Add Item 대화 상자를 입력한 다음 OK 버튼을 클릭한다.

    • 항목을 편집하려면 WakeRider Inventory Manager 애플리케이션의 알맞은 재고 창에서 항목을 선택하고 Edit 버튼을 클릭한다. Edit Item 대화 상자의 내용을 수정하고 OK 버튼을 클릭한다.

    • 항목을 삭제하려면 WakeRider Inventory Manager 애플리케이션의 알맞은 재고 창에서 항목을 선택하고 Remove 버튼을 클릭한다.

    • wrmanager 애플리케이션에서 현재 재고 항목을 조회하려면 브라우저에서 wrviewer 페이지를 보거나 새로 고친다.

      WakeRider Inventory
WakeRider Inventory

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

2007/10/09 15:02 2007/10/09 15:02

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

댓글을 달아 주세요

[로그인][오픈아이디란?]

◀ Prev 1  ... 215 216 217 218 219 220 221 222 223  ... 641  Next ▶