이 아티클의 영문 원본은
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, WakeboardBinding 및 Tower 클래스를 정의할 수 있다.
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 추상 클래스를 도입하여 상속 계층 구조를 더 흥미롭게 만들어 본다. Wearable은 Wakeboard 및 WakeboardBinding 클래스의 크기 속성을 보유한다. Wearable 클래스는 다음과 같이 정의된다.
public abstract class Wearable extends Item { protected String size; }
그리고 그 결과 Wakeboard 및 WakeboardBinding 클래스는 다음과 같다.
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, WakeboardBinding 및 Tower 유형을 비롯하여 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, WakeboardBinding 및 Tower 클래스에 대한 참조를 갖는다. 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를 사용하여 샘플 코드를 빌드하고 실행할 수 있다.
- NetBeans 5.5.1 IDE가 없으면 다운로드하여 설치한다.
- GlassFish V2 RC 4 이상이 없으면 다운로드하여 설치한다.
- 팁의 샘플 애플리케이션을 다운로드하고 압축을 푼다. 이제 압축이 풀린 새 디렉토리,
<sample_install_dir>/wakerider가 나타나며, 여기서<sample_install_dir>은 샘플 애플리케이션을 설치한 디렉토리이다. 예를 들어, Windows 시스템의C:\에 해당 컨텐츠의 압축을 풀었다면 새로 생성된 디렉토리는C:\wakerider에 있어야 한다. wakerider 디렉토리는 NetBeans 프로젝트, 즉wrservice,wrviewer및wrmanager별로 하나의 디렉토리를 포함한다.
- NetBeans IDE를 시작한다. JDK 5.0으로 Netbeans를 실행한다. 또한 JDK 6을 사용할 수도 있는데, 그러한 경우 JDK 6의 상위에서 실행하기의 지침을 따라야 한다.
- 다음과 같이 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 버튼을 클릭한다.
- Runtime 창에서 Servers 노드를 마우스 오른쪽 버튼으로 클릭한다.
- 다음과 같이
wrservice프로젝트를 연다.
- File 메뉴에서 Open Project를 선택한다.
- 샘플 애플리케이션 다운로드에서
wrservice디렉토리로 이동한다.
- Open Project Folder 버튼을 클릭한다.
- "Missing Server Problem"이라는 경고 메시지가 나타나면 Projects 창에서
wrservice노드를 마우스 오른쪽 버튼으로 클릭하고 Resolve Missing Server Problem을 선택하여 해결한다. 그런 다음 Sun Java System Application Server를 선택한다.
- File 메뉴에서 Open Project를 선택한다.
- 다음과 같이
wrservice프로젝트를 배포한다.
- Projects 창에서
wrservice노드를 마우스 오른쪽 버튼으로 클릭한다.
- Deploy Project를 선택한다.
- Projects 창에서
- 다음과 같이
wrviewer프로젝트를 연다.
- File 메뉴에서 Open Project를 선택한다.
- 샘플 애플리케이션 다운로드에서
wrviewer디렉토리로 이동한다.
- Open Project Folder 버튼을 클릭한다.
- 서버 누락 문제가 생기면 6단계에서 설명한 대로 해결해야 한다.
- File 메뉴에서 Open Project를 선택한다.
- 다음과 같이
wrviewer를 실행한다.
- Projects 창에서
wrviewer노드를 마우스 오른쪽 버튼으로 클릭한다.
- Run Project를 선택한다. 그러면 현재
WakeRider재고를 표시하는 창이 웹 브라우저에 열린다. 맨 처음wrviewer를 실행할 때 재고가 빈 상태이어야 한다.
WakeRider Inventory
- Projects 창에서
- 다음과 같이
wrmanager프로젝트를 연다.
- File 메뉴에서 Open Project를 선택한다.
- 샘플 애플리케이션 다운로드에서
wrmanager디렉토리로 이동한다.
- Open Project Folder 버튼을 클릭한다.
- File 메뉴에서 Open Project를 선택한다.
- 다음과 같이
wrmanager를 실행한다.
- Projects 창에서
wrmanager노드를 마우스 오른쪽 버튼으로 클릭한다.
- Run Project를 선택한다. 그러면 WakeRider Inventory Manager 애플리케이션이 열린다.
- Projects 창에서
- 다음과 같이 재고 항목을 추가, 삭제, 편집하거나 조회한다.
- 항목을 추가하려면 WakeRider Inventory Manager 애플리케이션에서 Add 버튼을 클릭하고 Add Item 대화 상자를 입력한 다음 OK 버튼을 클릭한다.
- 항목을 편집하려면 WakeRider Inventory Manager 애플리케이션의 알맞은 재고 창에서 항목을 선택하고 Edit 버튼을 클릭한다. Edit Item 대화 상자의 내용을 수정하고 OK 버튼을 클릭한다.
- 항목을 삭제하려면 WakeRider Inventory Manager 애플리케이션의 알맞은 재고 창에서 항목을 선택하고 Remove 버튼을 클릭한다.
- wrmanager 애플리케이션에서 현재 재고 항목을 조회하려면 브라우저에서 wrviewer 페이지를 보거나 새로 고친다.

- 항목을 추가하려면 WakeRider Inventory Manager 애플리케이션에서 Add 버튼을 클릭하고 Add Item 대화 상자를 입력한 다음 OK 버튼을 클릭한다.
"Java SE" 카테고리의 다른 글
- STRINGTOKENIZER에서 SCANNER까지 (댓글 2개 / 트랙백 1개) 2005/04/26
- 정적 인스턴스 초기화 블록 사용하기 (댓글 2개 / 트랙백 0개) 2004/04/13
- QUEUE와 DELAYED 프로세싱 (댓글 3개 / 트랙백 0개) 2004/11/04
- Callable을 사용하여 Runnable로부터 결과 반환 (댓글 0개 / 트랙백 0개) 2008/02/20
- 가비지 콜렉션 (댓글 3개 / 트랙백 0개) 2004/06/30
- 스윙에서의 멀티 쓰레딩 (댓글 2개 / 트랙백 0개) 2003/12/12
- SWING COMPONENTS의 저장과 재구성 (댓글 5개 / 트랙백 0개) 2003/08/05
- 스플래시 스크린과 MUSTANG (댓글 1개 / 트랙백 2개) 2005/12/20
- WSIT에서의 지원 토큰과 발급된 토큰 위임 (댓글 20개 / 트랙백 2개) 2007/09/03
- Singleton 패턴에 대한 재고찰 (댓글 4개 / 트랙백 1개) 2006/04/21
댓글을 달아 주세요