레이블이 JAXB인 게시물을 표시합니다. 모든 게시물 표시
레이블이 JAXB인 게시물을 표시합니다. 모든 게시물 표시

2011년 2월 14일 월요일

JAXB 개발 환경에서 XSD 생성 (maven pom 파일)

Jaxb 관련 annotation을 이용하여 웹서비스를 개발하다보면
가끔씩 최종 XSD를 확인해 보고 싶은 경우가 생긴다.

물론 CXF와 같은 프레임워크를 이용하여 웹서비스를 개발하면 웹서비스 URI에 ?wsdl을 붙히면 WSDL을 살펴 볼 수도 있지만
개발 환경에서 @XmlRootElement, @XmlElement로 작업할 경우 매핑되는 XSD를 보고자 한다면 아래의 pom.xml 파일을 참고하기 바란다.

jdk1.6 (mustang)의 bin 폴더에 있는 xjc (xsd를 이용하여 java class 생성) 와 schemagen을 이용해도 동일한 결과를 얻을 수 있으나 maven plugin을 이용하는 편이 훨씬 수월하다.

<project xmlns="http://maven.apache.org/POM/4.0.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
    http://maven.apache.org/POM/4.0.0 
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.archnal.maven</groupId>
  <artifactId>jaxb-project</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>jaxb-project</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.0</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.5</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.0.1</version>
      <type>jar</type>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <repositories>
    <repository>
      <id>java.net</id>
      <name>java.net Maven Repository</name>
      <url>https://maven-repository.dev.java.net/nonav/repository</url>
      <layout>legacy</layout>
    </repository>
  </repositories>

  <build>

    <plugins>
      <plugin>
        <groupId>com.sun.tools.jxc.maven2</groupId>
        <artifactId>maven-jaxb-schemagen-plugin</artifactId>
        <version>1.2</version>
        <executions>
          <execution>
            <phase>generate-resources</phase>
            <goals>
              <goal>generate</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <includes>
            <include>**/com/archnal/sample/jaxb/**</include>
          </includes>
          <verbose>true</verbose>
          <source>1.6</source>
        </configuration>
      </plugin>
      <plugin>
        <groupId>com.sun.tools.xjc.maven2</groupId>
        <artifactId>maven-jaxb-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>generate</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <includeSchemas>
            <includeSchema>**/*.xsd</includeSchema>
            <includeSchema>**/*.dtd</includeSchema>
          </includeSchemas>
          <verbose>true</verbose>
          <source>1.6</source>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
    </plugins>

  </build>
  <pluginRepositories>
    <pluginRepository>
      <id>maven-repository.dev.java.net</id>
      <name>Java.net Maven 2 Repository</name>
      <url>http://download.java.net/maven/2</url>
    </pluginRepository>
  </pluginRepositories>
</project>

2010년 8월 30일 월요일

Spring에서 Jaxb (Un)Marshaller 사용하기

스프링에서 XOM(Xml-Object Mapping)을 사용하는 방법이다.
이미 WebService를 사용하기 위해서 JAXB 애너테이션을 사용하고 있는 경우라면
더욱 사용하기가 용이하다.

다음은 User 객체를 XML로 마샬링하는 방법과 XML을 User객체로 언마샬링하는 방법을 보여주는 간단한 예제다.

/spring/context-oxm.xml 예제
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:oxm="http://www.springframework.org/schema/oxm"
    xsi:schemaLocation="
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
     http://www.springframework.org/schema/oxm 
     http://www.springframework.org/schema/oxm/spring-oxm-1.5.xsd">

 <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
  <property name="classesToBeBound">
   <list>
    <value>sample.maven.jaxws.User</value>
   </list>
  </property>
 </bean>
 
</beans>    

아래의 소스는 사용자 정보를 담고 있는 Jaxb 클래스다.
CXF에서 XmlType 애너테이션만 설정하면 WSDL이 생성되는 것과는 달리
Jaxb2Marshaller에서는 XmlRootElement 애너테이션을 반드시 설정해 주어야 한다.

User 클래스
package sample.maven.jaxws;

import java.sql.Timestamp;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlType
@XmlRootElement(name="user", namespace="org.sds.sample")
public class User {
 private long userId;
 private String loginId;
 private String userName;
 private Timestamp createDate;
 public long getUserId() {
  return userId;
 }
 public void setUserId(long userId) {
  this.userId = userId;
 }
 public String getLoginId() {
  return loginId;
 } 
 public void setLoginId(String loginId) {
  this.loginId = loginId;
 }
 public String getUserName() {
  return userName;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
 @XmlJavaTypeAdapter(value=DateTimestampAdapter.class)
 public Timestamp getCreateDate() {
  return createDate;
 }
 public void setCreateDate(Timestamp createDate) {
  this.createDate = createDate;
 }
 @Override
 public String toString() {
  return "User [userId=" + userId + ", loginId=" + loginId
    + ", userName=" + userName + ", createDate=" + createDate + "]";
 }
 
 
}


아래는 JUnit테이스 케이스다.
User객체를 XML로 마샬링하는 예제와 XML을 User객체로 언마샬링하는 예제가 포함되어 있다.

Jaxb 테스트 케이스
package sample.maven.jaxws;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;

import javax.annotation.Resource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@ContextConfiguration(locations={"classpath*:/spring/context-*.xml"})
@RunWith(SpringJUnit4ClassRunner.class)

public class UserXomTest {

 @Resource(name="jaxb2Marshaller")
 Marshaller marshaller;
 
 @Resource(name="jaxb2Marshaller")
 Unmarshaller unmarshaller;
 
 @Test
 public void testMarshaller() throws Exception {
  User user = new User();
  user.setLoginId("loginId");
  
  ByteArrayOutputStream out = new ByteArrayOutputStream();
  
  StreamResult result = new StreamResult(out);
  marshaller.marshal(user, result);
  
  System.out.println(out.toString());
  
  ByteArrayInputStream in = 
   new ByteArrayInputStream(out.toByteArray());
  
  StreamSource source = new StreamSource(in);
  User newUser = (User) unmarshaller.unmarshal(source);
  
  System.out.println("new user: " + newUser);
 }
}

2010년 7월 27일 화요일

JAXB의 XmlJavaTypeAdapter 애너테이션

JAXB를 이용하여 XML-Binding을 처리할 때 유용한 애너테이션들이 많이 있다.
그 중의 하나인 XmlJavaTypeAdapter를 살펴보기로 한다.

아래의 소스코드를 살펴 보자

package sample.maven.jaxws;

import java.sql.Timestamp;

import javax.xml.bind.annotation.XmlType;

@XmlType
public class User {
  private long userId;
  private String loginId;
  private String userName;
  private Timestamp createDate;
  public long getUserId() {
    return userId;
  }
  public void setUserId(long userId) {
    this.userId = userId;
  }
  public String getLoginId() {
    return loginId;
  } 
  public void setLoginId(String loginId) {
    this.loginId = loginId;
  }
  public String getUserName() {
    return userName;
  }
  public void setUserName(String userName) {
    this.userName = userName;
  }
  public Timestamp getCreateDate() {
    return createDate;
  }
  public void setCreateDate(Timestamp createDate) {
    this.createDate = createDate;
  }
}

대부분의 dateTime 처리와 관련하여 java.util.Date 타입을 처리하면 문제가 될 게 없다.
Jaxb에서도 java.util.Date 처리를 기본적으로 지원하고 있다.
하지만 Anyframe의 QueryService는 java.util.Date로 매핑을 하게 되면 시분초를 싸그리 없애버린다.
java.sql.Date도 아닌데 말이다.
어쨋거나 어쩔 수 없이 또는 이런 저런 이유로 Timestamp를 데이터 타입으로 사용해야 하는 경우가 있다.
디폴트 생성자도 없는 Timestamp를 Jaxb는 기본적으로 처리할 수가 없다.
따라서 Jaxb가 Timestamp를 java.util.Date로 처리할 수 있도록 어뎁터(Adapter)를 구현해 주어야 한다.

Adapter를 지정하지 않은 경우에 CXF가 웹서비스를 초기화하는 과정에서 아래와 같은 에러메시지가 출력된다.

Timestamp를 사용하는 bean
package sample.maven.jaxws;

import java.sql.Timestamp;

import javax.xml.bind.annotation.XmlType;

@XmlType
public class User {
  private long userId;
  private String loginId;
  private String userName;
  private Timestamp createDate;
  public long getUserId() {
    return userId;
  }
  public void setUserId(long userId) {
    this.userId = userId;
  }
  public String getLoginId() {
    return loginId;
  } 
  public void setLoginId(String loginId) {
    this.loginId = loginId;
  }
  public String getUserName() {
    return userName;
  }
  public void setUserName(String userName) {
    this.userName = userName;
  }
  public Timestamp getCreateDate() {
    return createDate;
  }
  public void setCreateDate(Timestamp createDate) {
    this.createDate = createDate;
  }
}


에러 메시지
... 39 more
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.sql.Timestamp does not have a no-arg default constructor.
this problem is related to the following location:
at java.sql.Timestamp
at public java.sql.Timestamp sample.maven.jaxws.User.getCreateDate()
at sample.maven.jaxws.User
at private sample.maven.jaxws.User sample.maven.jaxws.jaxws_asm.GetUserResponse._return
at sample.maven.jaxws.jaxws_asm.GetUserResponse



XmlAdapter
package sample.maven.jaxws;

import java.sql.Timestamp;
import java.util.Date;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class DateTimestampAdapter extends XmlAdapter {

  @Override
  public Timestamp unmarshal(Date v) throws Exception {
    return new Timestamp(v.getTime());
  }

  @Override
  public Date marshal(Timestamp v) throws Exception {
    return new Date(v.getTime());
  }
}


@XmlJavaTypeAdapter를 적용한 User 빈
package sample.maven.jaxws;

import java.sql.Timestamp;

import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlType
public class User {
  private long userId;
  private String loginId;
  private String userName;
  private Timestamp createDate;
  public long getUserId() {
   return userId;
  }
  public void setUserId(long userId) {
    this.userId = userId;
  }
  public String getLoginId() {
    return loginId;
  } 
  public void setLoginId(String loginId) {
    this.loginId = loginId;
  }
  public String getUserName() {
    return userName;
  }
  public void setUserName(String userName) {
    this.userName = userName;
  }
  @XmlJavaTypeAdapter(value=DateTimestampAdapter.class)
  public Timestamp getCreateDate() {
    return createDate;
  }
  public void setCreateDate(Timestamp createDate) {
    this.createDate = createDate;
  }
}