Dev Note/JAX-WS (SOA)2008. 3. 6. 13:51


JAXB (2) - XML Schema를 Java Interfaces & Classes로 Binding Compile 하기에서 XML Schema로 정의 되는 데이터를 Binding 하기 위한 Java Interfaces & Classes로 Binding Compile 하는 법에 대해 알아봤습니다.
그럼 이번에는 Binding 된 Interfaces와 Classes를 이용하여 Java Object를 XML 표현으로 marchal하는 것과 XML 표현을 Java Object로 unmarshal 하는 것에 대해 알아본다.

-- marshal
Binding Interfases & Classes로 처리된 Content Tree를 하나 이상의 XML 표현으로 직렬화시키는 것을 말한다. Content Tree는 정렬화되기 전에 유효성 검사를 하게 된다.

-- unmarshal
XML 표현을 Source Schema 조건들에 따라서 Binding Interfases & Classes의 Java Object로 비정렬화시키는 것을 말한다. JAXB에서는 파일이나 문서형태의 소스 만이 아니라 DOM 노드, String Buffer, SAX 소스 등에 대한 처리도 가능하다.

-- validation
유횬성 검사는 XML 문서가 스키마에 표현되어 있는 모든 제약 조건을 만족시키는지를 확인합니다. JAXB 1.0은 비정렬화를 실시할 때 유효선 검사를 할 수 있도록 해주며, 필요할 경우에 JAXB Content Tree에 대해서도 검사를 할 수 있도록 해줍니다. JAXB 2.0은 정렬화 또는 비정렬화 할 때 모두 유효성 검사를 제공하고 있습니다.
웹 서비스 처리 모델은 데이터를 읽을 때는 엄격하지 않게 처리하고, 쓸 때는 엄격하게 처리합니다. 그러한 모델을 위해서는 유효성 검사는 정렬화 시기에 이루어져서 JAXB 형식으로 문서를 수정할 때 XML 문서가 잘못 되었는지를 확인할 수 있도록 해야 합니다.

-- Unmarshalling 하기
다음은 XML 파일을 JAXB 생성 인스턴스로 비정렬화(unmarshalling)하는 것에 대한 예제와 간단한 설명이다.

   package com.junducki.blog.jaxb.test;

   import java.io.File;
   import java.util.Iterator;
   import java.util.List;
   import javax.xml.bind.JAXBContext;
   import javax.xml.bind.JAXBException;
   import javax.xml.bind.Unmarshaller;
   import com.junducki.blog.jaxb.Company;

   public class UnmarshallingTest {

      public static void main(String[] args) {
         try {
            JAXBContext jc = JAXBContext.newInstance("com.junducki.blog.jaxb");

            Unmarshaller unmarshaller = jc.createUnmarshaller();
            // unmarshaller.setValidating(true);

            Company company = (Company) unmarshaller.unmarshal(new File(
                  "E:/temp/blog/jaxb/jaxb_company_sample.xml"));

            System.out.println("Company Info :: NAME[" + company.getName() + "], ADDRESS[" +
                  company.getAddress() + "], TEAM_COUNT[" + company.getTeam().size() + "]");

            List<Team> teamList = company.getTeam();
            Iterator iter = teamList.iterator();
            while (iter.hasNext()) {
               Team team = (Team) iter.next();
               System.out.println("Team Info :: NAME[" + team.getName() + "]");
            }
         } catch (JAXBException e) {
               e.printStackTrace();
         }
      }
   }

먼저 com.junducki.blog.jaxb package를 사용하여 JAXBContext를 생성한다. com.junducki.blog.jaxb package에는 Binding Compile의해 생성 된 Java Interfaces & Classes들이 포함되어 있으며, JAXBContext가 Unmarshaller Object를 생성하기 위해 사용한다.

   JAXBContext jc = JAXBContext.newInstance("com.junducki.blog.jaxb");

XML 표현을 Java Object로 비직렬화하기 위한 Unmarshaller를 생성한다. 여기서 setValidating(boolean)은 Validate 수행 여부를 나타내며, JAXB 1.0에서는 함수를 이용해 설정이 가능했으나, JAXB 2.0에서는 Deprecated 되었다.

   Unmarshaller unmarshaller = jc.createUnmarshaller();
   // unmarshaller.setValidating(true);

JAXBContext에서 생성한 Unmarshaller를 이용하여 XML 파일을 비직렬화 하기 위해 unmarshal() 함수를 이용한다. unmarshal() 함수는 여기서 사용한 파일 이외에 URL, Source, Node 등 다양한 것을 지원한다.

   Company company = (Company) unmarshaller.unmarshal(new File(
         "E:/temp/blog/jaxb/jaxb_company_sample.xml"));

예제의 다음 부분은 Ummarshalling 된 Object의 내용을 간단히 System.out으로 출력하는 부분이다.

-- Marshalling 하기
다음은 Ummarshalling의 반대인 Java Object를 XML 파일로 직렬화하는 것에 대한 간단한 예제와 설명이다.

   package com.junducki.blog.jaxb.test;

   import java.io.FileNotFoundException;
   import java.io.FileOutputStream;
   import javax.xml.bind.JAXBContext;
   import javax.xml.bind.JAXBException;
   import javax.xml.bind.Marshaller;
   import com.junducki.blog.jaxb.Company;
   import com.junducki.blog.jaxb.ObjectFactory;
   import com.junducki.blog.jaxb.Company.Team;

   public class MarshallingTest {

      public static void main(String[] args) {
         try {
            ObjectFactory objFactory = new ObjectFactory();
   
            Company company = objFactory.createCompany();
            company.setName("Test Company");
   
            Team team1 = objFactory.createCompanyTeam();
            team1.setName("Test Team 1");
            Team team2 = objFactory.createCompanyTeam();
            team2.setName("Test Team 2");
   
            company.addTeam(team1);
            company.addTeam(team2);
   
            JAXBContext jc = JAXBContext.newInstance("com.junducki.blog.jaxb");

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

            marshaller.marshal(company, new FileOutputStream(
               "E:/temp/blog/jaxb/jaxb_company_marshal_sample.xml"));
         } catch (JAXBException e) {
            e.printStackTrace();
         } catch (FileNotFoundException e) {
            e.printStackTrace();
         }
      }
   }

Marshalling 하기 위한 Java Content Tree를 생성한다. Tree Element의 생성은 xjc에 의해 생성 된 ObjectFactory를 이용하여 생성하며, Company의 addTeam(Team teamElement) 함수는 xjc에 의해 생성 된 Company Class에 있는 것이 아니고, 추가 된 함수이다.
Java Content Tree를 생성했으면 Marshalling을 위해 JAXBContext를  Unmarshalling 때와 마찬가지로 생성하고, Java Content Tree를 XML 표현으로 직렬화하기 위해 Marshaller를 생성한다.

   Marshaller marshaller = jc.createMarshaller();
   // Marshalling 된 XML 표현을 Formatting 하기 위한 설정
   marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true));

마지막으로 marshaller는 marshal() 함수를 이용하여 생성 된 Java Content Tree를 XML 파일로 직렬화하여 쓴다. marshal() 함수도 unmarshal() 함수와 마찬가지로 여러 형태를 지원한다.

이상 여기까지가 JAXB에 대해 3부로 거쳐 알아봤습니다. 여기 소개한 내용은 JAXB 중 극히 일부에 불과하니 좀더 알고 싶은 분들은 https://jaxb.dev.java.net/jaxb20-fcs/ 여기를 참고하세요.

Posted by as.wind.914