XML은 이제 데이터를 표현하는 표준이며, Java 오브젝트를 XML로 나열할 때 사용하는 다양한 XML기술들이 개발되어 왔다. 그 중 자바 개발자들에게 익숙한 두가지 기본 기술은 Simple API for XML (SAX)과 Document Object Model (DOM) APIs이다. 그러나 종종 프로그래머들은 즉각적인 테스트에 좀 더 특정적으로 적용할만한 기술을 필요로 하며, 이 경우 오브젝트 데이터를 나열하는 데 좀 더 간단한 XML 기술을 원할 것이다.

JAXB(XML 바인딩을 위한 Java API)를 살펴보자. JAXB는 이제 Java Web Services Development Pack의 표준이 되었다. JAXB는 XML 스키마로부터 클래스 데이터를 바인딩하거나, XML로부터 나열하거나 반대로 XML로 나열하는 등의 다양한 태스크를 수행할 수 있도록 한다.

이번 테크팁에서는 JAXB APIs를 소개하려고 한다. JAXB 바인딩 컴파일러를 이용하여 XML Schema 문서로부터 Java 클래스들을 생성하는 방법을 보여준다. 이 팁에서는 또한 오브젝트들을 XML 파일에 나열하는 법(marshalling)과, 반대로 XML로부터 오브젝트들을 나열하는 방법(unmarshalling)을 소개한다.

이 팁에서 소개하는 대로 예제를 구동하기 전에 Java Web Services Developer Pack을 다운로드 받아야한다. 그 후 jaxb/libjwsdp-shared/lib 디렉토리를 모두 보고 각각의 JAR 파일들이 사용자의 Java 클래스경로에 정확히 포함되어있는지 확인하자.

또는, 이번 팁에 수반된 WAR 파일에서 제공하는 웹 애플리케이션을 구동할 수도 있다. 이번 팁에서 보여주는 소스 코드는 WAR 파일에 포함되어 있으나 이 소스 코드는 servlet을 사용하기 위해 약간 수정된 것이다. WAR 파일을 사용하려면, Sun Java System Application Server를 다운로드받고, 그 안에 Java Web Services Developer Pack을 다운로드, 설치하기 바란다. 그러면 각각의 필요 라이브러리가 J2EE 환경에 나타날 것이다. Ant 파일이 포함되어 컴파일과 패키징에 도움을 줄 것이다.

바인딩 컴파일러

JAXB에 대해서 가장 먼저 배워야할 것은 XML 스키마를 Java 클래스에 바인딩하는 법이다. 바인딩 작업은 XML 스키마를 가지고, 그 스키마에 의해 정의된 데이터 모델을 표현할 수 있는 Java 인터페이스들을 생성한다. 이 작업을 위한 툴을 바인딩 컴파일러라고 부른다. 바인딩 컴파일러는 W3C XML 스키마를 허용하고 그로부터 적절한 인터페이스와 클래스들을 끌어온다.

다음은 JAXB 클래스를 생성하는 간단한 스키마이다.

   <?xml version="1.0" encoding="UTF-8"?>

   <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  
       <xs:import namespace="http://www.w3.org/XML/1998/namespace"
        schemaLocation="http://www.w3.org/2001/xml.xsd" />

       <xs:element name="birthdate">
         <xs:complexType>
           <xs:sequence>
             <xs:element name="month" type="xs:string" />
             <xs:element name="day" type="xs:int" />
             <xs:element name="year" type="xs:int" />
           </xs:sequence>  
         </xs:complexType>
       </xs:element>

     </xs:schema>

이번 팁에 수반되는 소스 코드에서 Birthdate.xsd 스키마를 찾을 수 있을 것이다. 이 스키마는 Birthdate라는 이름의 간단한 요소를 정의한다. Birthdate 요소는 세가지 속성 [month (String), day (integer)와 year(또다른 integer)]을 정의하는 익명의 complexType을 갖고있다.

이를 Java 인터페이스에 바인딩하기 위해 XML 바인딩 컴파일러를 호출하자. 이를 위해서는 xjc 코멘드를 구동해야하며, 이 코멘드는 Java Web Services Developer Pack installation 의 jaxb/bin 디렉토리에서 찾을 수 있다. (xjc.bat 파일을 윈도우 환경에서 불러오거나, xjc.sh 파일을 Solaris Operating System 또는 다른 유닉스 환경에서 불러온다) 다음의 코멘드 라인 구문을 사용하자.

   xjc -p <target_package> -d <dir> schema.xsd

<target_package>이 생성된 파일들을 위한 패키지의 이름이고, <dir>는 그 파일들이 위치한 디렉토리이며, schema.xsd은 입력 XML 스키마이다. 따라서 예를 들어 Birthdate.xsd을 포함하는 디렉토리에서 다음의 코멘드를 구동하면,

   xjc -p com.nexes.jaxb.test -d . Birthdate.xsd

그에 대한 반응으로 바인딩 컴파일러는 Java 소스 클래스들을 생성하며, 이 모든 클래스들은 javac로 컴파일되야한다. 이번 팁에 수반되는 샘플 코드에는 소스 클래스들이 포함되어 있다. 그 예로, 다음은 BirthdateType 인터페이스이다.(코멘트는 생략함)

   package com.nexes.jaxb.test;

   public interface BirthdateType {

       int getDay();
       void setDay(int value);

       int getYear();
       void setYear(int value);

       java.lang.String getMonth();
       void setMonth(java.lang.String value);

   }

그러나 스키마 컴파일러는 이 보다 더 많은 것을 생성한다. 생성된 클래스들을 세 개의 카테고리로 분리할 수 있다.

  • 스키마로 정의된 데이터 모델을 나타내는 포터블 JavaBean 스타일의 getter/setter 인터페이스들
  • 이 인터페이스들의 구체적인 특정 벤더 구현
  • 기타 지원 런타임 클래스들

이러한 클래스들은 각각 Birthdate 오브젝트에 대한 인스턴스 데이터를 나열하는 XML 표현을 돕는다. 다음은 Birthdate 오브젝트에 대해 나열된 XML 샘플 리스트가 어떻게 생겼는지를 보여준다.

   <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
   <birthdate>
       <month>January</month>
       <day>1</day>
       <year>1900</year>
   </birthdate>

일반적으로 XML 문서는 직접적으로 컨텐츠 트리로 알려진 클래스 크리에 나열(또는 정렬)한다. XML의 각각의 요소가 그 자신이 또다시 오브젝트가 되어 하나 또는 그 이상의 요소를 보유하고 있기 때문에 트리구조로 나타난다. 이 예제에서 <birthdate> 요소는 클래스이며, <month>요소(String )도 마찬가지이다. String은 Java 구축 타입이기 때문에 JAXB는 이에 대한 클래스를 생성할 필요가 없다. 그러나 좀 더 복잡한 오브젝트에 대해서는 많은 클래스들이 생성될 수 있다. XML 인스턴스 문서가 클래스 인스턴스로 변경된 후에는 Java 애플리케이션은 생성되어 값을 허용하는 아무 오브젝트를 찾아 반복적으로 컨텐츠 트리의 아래쪽으로 움직이게 된다.

바인딩 컴파일러로 필수 클래스를 생성한 후에는 javac으로 생성된 클래스를 컴파일한다. 그 후 JAXB 나열 작업을 시작할 수 있다. 앞서 언급했듯이 Java 오브젝트를 XML 표현으로 변환하는 것을 'marshalling'이라고 한다. 반대의 작업, 즉 XML 표현을 Java 오브젝트로 변환하는 것은 unmarshalling이라고 한다. 먼저 unmarshalling에 대해 알아보자

Unmarshalling

다음은 XML 파일을 JAXB 생성 인스턴스로 unmarshalling하는 예제이다.

   import javax.xml.bind.*;

   JAXBContext jc = JAXBContext.newInstance(
           "com.nexes.jaxb.test");
   Unmarshaller unmarshaller = jc.createUnmarshaller();
   unmarshaller.setValidating(true);
   Birthdate instance = (Birthdate)unmarshaller.unmarshal(
           new File("birthdateInstance.xml"));
           
   System.out.println("Month is: " + instance.getMonth());
   System.out.println("Day is: " + instance.getDay());
   System.out.println("Year is: " + instance.getYear());

이 코드는 com.nexes.jaxb.test 패키지를 사용하여 JAXBContext 인스턴스를 생성한다.

   JAXBContext jc = JAXBContext.newInstance(
              "com.nexes.jaxb.test");

이 패키지에는 이전의 예제에서 Birthdate.xsd 스키마의 바인딩 컴파일러에 의해 생성된 인터페이스와 클래스들이 포함되어있다. 그 후 컨텍스트 오브젝트가 Unmarshaller 오브젝트를 생성하기 위해 사용된다.

   Unmarshaller unmarshaller = jc.createUnmarshaller();

Unmarshaller 오브젝트는 XML을 Java 컨텐츠 트리로 변환하는 것과 관련된 대부분의 태스크를 수행한다. 이 코드는 Unmarshaller 오브젝트의 unmarshal()메소드를 호출하며, 인스턴트 데이터를 포함하는 XML 파일의 이름을 전달한다. 파일 대신 데이터 소스와 sink를 사용할 수 있음을 기억하길 바란다. 이번 팁에 수반 되어있는 예제에서는 String의 결과를 저장하고 servlet의 결과를 보여준다.

   Birthdate instance = (Birthdate)unmarshaller.unmarshal(
              new File("birthdateInstance.xml"));

unmarshal() 메소드는 스키마 컴파일러로 생성한 클래스의 인스턴트인 오브젝트를 리턴한다.

unmarshaller 오브젝트에 대한 setValidating() 메소드를 주의하자.

   unmarshaller.setValidating(true);

setValidating()이 true로 설정되어 있다면 JAXB 런타임 API는 인스턴스 데이터를 가진 그 XML이 JAXB 런타임 API는 XML 스키마에 의해 정의된 제약에 맞는지 검사한다. XML 스키마는 바인딩 컴파일러에 넘겨준 것이다. 만약 데이터가 사용불가라면 사용허가는 false가 되고 런타임 exception을 떨어뜨린다. JAXB 제공자는 사용허가에 오류가 발생하더라도 진행과정을 꼭 멈춰야할 필요는 없다. 그러나 반드시 런타임 exception을 호출자에게 넘겨야한다.

Marshalling

Unmarshalling의 반대 작업이 marshalling이다. 다음은 Java 컨텐츠 트리를 xml 파일로 정렬하는 예제 코드이다.

   import javax.xml.bind.*;

   ObjectFactory objFactory = new ObjectFactory();
   Birthdate birthdate = objFactory.createBirthdate();
        
   birthdate.setMonth("January");
   birthdate.setDay(1);
   birthdate.setYear(1900);
        
   JAXBContext jaxbContext = JAXBContext.newInstance(
       "com.nexes.jaxb.test");
   Marshaller marshaller = jaxbContext.createMarshaller();
   marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
       new Boolean(true));
   marshaller.marshal(birthdate, new FileOutputStream(
       "birthdateInstance.xml"));

이 예제의 코드는 unmarshalling 예제에서의 소스 코드와 매우 흡사하다. 먼저, 코드는 JAXBContext 오브젝트를 생성하여, 바인딩 컴파일러로 생성한 파일을 갖고있는 패키지에 이름을 전달한다.

   JAXBContext jaxbContext = JAXBContext.newInstance(
          "com.nexes.jaxb.test");

그 다음으로 createMarshaller() 메소드에 의해 Marshaller 오브젝트가 생성된다.

   Marshaller marshaller = jaxbContext.createMarshaller();

그 후 코드는 JAXB_FORMATTED_OUTPUT이 결과 파일에 작성되도록 속성을 설정한다.

   marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
          new Boolean(true));

마지막으로, marshaller는 현재 활성화된 클래스 인스턴스를 채택하여 이를 FileOutputStream에 쓴다. FileOuputStreambirthdateInstance.xml 파일에 매핑된다.

marshaller.marshal(birthdate, new FileOutputStream( "birthdateInstance.xml"));

또는 JAXB로 생성된 컨텐츠 트리를 순열화한 오브젝트를 활성화해도 된다. 이를 위해서는 다음과 같이 Validator를 사용해보자.

   Validator validator = jaxbContext.createValidator();
   Validator.validate(birthdate);

JAXB specification에서는 클래스 인스턴스가 XML 표현에 marshall되기 전에 사용가능해야할 필요는 없다.

JAXB 테스트 servlet을 구동시켜 marshalling과 unmarshalling를 시험해볼 수 있다. 좀 더 자세한 정보는 예제 코드 실행란을 참조하기 바란다.

JAXB에 대한 자세한 정보는 Java Architecture for XML Binding (JAXB)에서 볼 수 있으며 세부 사항과 아티클을 포함한다. 또한 XML 바인딩에 대한 완전한 스키마에 대해서는 Java Architecture for XML Binding (JAXB) Bindings Schema for JAXB를 참조하고, java.net에 나와있는 jaxb 프로젝트에 대해서도 방문해보기 바란다.

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

2005/02/03 16:02 2005/02/03 16:02

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

댓글을 달아 주세요

  1. 박정숙  수정/삭제  댓글쓰기

    좋은 정보 감사해요~

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

◀ Prev 1  ... 540 541 542 543 544 545 546 547 548  ... 626  Next ▶