내용 목차
본 장에서는 JEUS 7 웹 서비스가 지원하는 XML에 관련된 다양한 기술들에 대해 설명한다.
XML 문서를 스키마로부터 컴파일된 Java 클래스로 Java 오브젝트화(바인딩)하여 XML 문서의 정보들을 프로그래밍하듯이 다룰 수 있도록(programmatic) 해주는 JAXB(Java Architecture for XML Binding)에 대해 알아본다. 이후, JAXP(Java API for XML Processing)에 새롭게 API를 도입하기 시작한 StAX(Streaming APIs For XML)에 대해서도 알아보기로 한다.
본 장을 진행하기에 앞서 XML 문서 혹은 문서 내의 내용물과 Java 오브젝트의 변환에서 일반적으로 사용되는 용어에 대해 설명한다.
어떤 스키마를 준수하는 XML 문서에 관련된 애플리케이션은 그 문서를 생성하거나 수정하거나 혹은 읽어들일 수 있어야 한다. 이와 같은 애플리케이션에서 사용되는 XML에 관련된 데이터 바인딩은 SAX나 DOM API를 이용할 수도 있지만 유지보수(스키마 변화에 따른)의 면에서 쉽지 않다. 그에 따라 JAXB는 XML 문서와 Java 오브젝트 사이의 연결(mapping)을 자동화시켜주는 API 및 툴들을 제공한다.
XML 콘텐츠들을 Java 오브젝트로 변환하는 과정인 언마셜링 기능
Java 오브젝트로 표현된 객체들에 대하여 접근하거나 수정
Java로 표현된 객체들을 다시 XML 콘텐츠로 변환하는 과정인 마셜링 기능
이와 같이 JAXB는 XML과 Java 코드들 사이의 표준화된, 그리고 효과적인 연결(mapping)을 개발자에게 제공한다. 결국 JAXB는 XML과 웹 서비스 기술을 사용하는 애플리케이션을 더욱 쉽게 개발할 수 있도록 한다. 계속되는 장에서는 JAXB에서 제공해주는 툴과 함께 예제 프로그램을 통해 JAXB에 관해 보다 자세히 설명한다.
XML 콘텐츠들을 Java 오브젝트로 변환하기 위해서는 변환하기 전에 미리 Java 클래스들을 가지고 있어야 한다. 이러한 Java 클래스는 스키마로부터 생성되며 이러한 과정을 바인딩 컴파일이라 한다.
본 절에서는 JEUS 7 웹 서비스가 기본으로 제공하는 바인딩 컴파일러 툴인 XJC에 대해 설명한다.
기본적인 동작방법은 커맨드 라인(Command Line)에서 다음과 같이 입력하여 명령어를 수행한다.
JEUS_HOME/bin$ xjc.cmd -help
사용 방법은 다음과 같다.
Usage: xjc [-options ...] <schema file/URL/dir/jar> ... [-b <bindinfo>] ... If dir is specified, all schema files in it will be compiled. If jar is specified, /META-INF/sun-jaxb.episode binding file will be compiled. Options: -nv : do not perform strict validation of the input schema(s) -extension : allow vendor extensions - do not strictly follow the Compatibility Rules and App E.2 from the JAXB Spec -b <file/dir> : specify external bindings files (each <file> must have its own -b) If a directory is given, **/*.xjb is searched -d <dir> : generated files will go into this directory -p <pkg> : specifies the target package -httpproxy <proxy> : set HTTP/HTTPS proxy. Format is [user[:password]@]proxyHost:proxyPort -httpproxyfile <f> : Works like -httpproxy but takes the argument in a file to protect password -classpath <arg> : specify where to find user class files -catalog <file> : specify catalog files to resolve external entity references support TR9401, XCatalog, and OASIS XML Catalog format. -readOnly : generated files will be in read-only mode -npa : suppress generation of package level annotations(**/package-info.java) -no-header : suppress generation of a file header with timestamp -target 2.0 : behave like XJC 2.0 and generate code that doesnt use any 2.1 features. -xmlschema : treat input as W3C XML Schema (default) -relaxng : treat input as RELAX NG (experimental, unsupported) -relaxng-compact : treat input as RELAX NG compact syntax (experimental, unsupported) -dtd : treat input as XML DTD (experimental, unsupported) -wsdl : treat input as WSDL and compile schemas inside it(experimental,unsupported) -verbose : be extra verbose -quiet : suppress compiler output -help : display this help message -version : display version information Extensions: -Xlocator : enable source location support for generated code -Xsync-methods : generate accessor methods with the 'synchronized' keyword -mark-generated : mark the generated code as @javax.annotation. Generated -episode <FILE> : generate the episode file for separate compilation
JEUS 7 웹 서비스는 XJC의 Ant Task도 지원하는데 보다 자세한 설명은 “JEUS Reference Book”의 “4.12. xjc” 및 “JEUS Reference Book”의 “5.5.5. xjc”를 참고한다.
다음은 하나의 스키마와 XML 문서를 JAXB를 이용하여 메모리상의 Java 객체로 바꿔서 XML 문서의 콘텐츠들을 프로그래밍적(programmatic)으로 다루는 예이다.
전체적인 흐름은 다음과 같다.
하나의 XML 문서를 언마셜링하여 Java 객체로 변환한다.
변환된 Java 객체에 대해 프로그래밍적으로 가공을 한다.
Java 객체를 다시 XML 문서로 마셜링(이 예제에서는 출력)한다.
다음은 이 예제의 build.xml의 일부분이다.
[예 19.1] << build.xml >>
... <project basedir="." default="run"> ... <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask"> <classpath refid="classpath" /> </taskdef> <target name="compile" description="Compile all Java source files"> <echo message="Compiling the schema..." /> <mkdir dir="gen-src" /> <xjc extension="true" schema="po.xsd" package="primer.myPo" destdir="gen-src"> <produces dir="gen-src/primer.myPo" includes="**/*.java" /> </xjc> <echo message="Compiling the java source files..." /> <mkdir dir="classes" /> <javac destdir="classes" debug="on"> <src path="src" /> <src path="gen-src" /> <classpath refid="classpath" /> </javac> </target> <target name="run" depends="compile" description="Run the sample app"> <echo message="Running the sample application..." /> <java classname="Main" fork="true"> <classpath refid="classpath" /> </java> </target> ... </project>
다음은 이 예제의 Main.java에 대한 설명이다.
[예 19.2] << Main.java >>
Schema schema = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI). newSchema(new File("src/conf/ts.xsd")); JAXBContext jc = JAXBContext.newInstance("com.tmaxsoft"); // Unmarshaller unmarshaller = jc.createUnmarshaller(); unmarshaller.setSchema(schema); ... // Marshaller marshaller = jc.createMarshaller(); marshaller.setSchema(schema); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); ...
이전에 build.xml의 XJC Ant Task를 사용하여 생성한 Java 클래스들의 패키지 이름을
이용하여 JAXB 컨텍스트 객체를 생성하고 이를 이용하여 Unmarshaller와 Marshaller를 생성한다. 그리고 스키마에
맞게 구현된 XML 문서인지를 판단하기 위한 Schema 객체를 생성하여 Unmarshaller와 Marshaller에
등록한다.
[예 19.3] << Main.java (계속) >>
Object ts = unmarshaller.unmarshal(new File("src/conf/tsInput.xml")); TmaxSoftType tst = (TmaxSoftType) ((JAXBElement) ts).getValue(); Address address = tst.getAddress1(); address.setName("John Bob"); address.setStreet("242 Main Street"); address.setCity("Beverly Hills");
poInput.xml이라는 XML 문서를 언마셜링한다. 그리고 언마셜링된 Java 객체를
수정한다.
화면에 출력(마셜링)한다.
JEUS 7 웹 서비스는 스키마로부터 Java 클래스를 생성하는 스키마 컴파일러인 XJC와 함께 사용자가 미리 작성한 Java 클래스들로부터 특정 XML 스키마를 작성할 수 있는 툴을 제공한다. 이러한 툴을 스키마 생성기(generator)라 하는데 본 절에서는 JEUS 7 웹 서비스가 기본으로 제공하는 스키마 생성기인 Schemagen에 대해 설명한다.
기본적인 동작 방법은 커맨드 라인(Command Line)에서 다음과 같이 입력하여 명령을 수행한다.
JEUS_HOME/bin$ schemagen.cmd -help
사용 방법은 다음과 같다.
Usage: schemagen [-options ...] <java files> Options: -d <path> : specify where to place processor and javac generated class files -cp <path> : specify where to find user specified files -classpath <path> : specify where to find user specified files -episode <file> : generate episode file for separate compilation -version : display version information -help : display this usage message
JEUS 7 웹 서비스는 Schemagen의 Ant Task도 지원하는데 보다 자세한 설명은 “JEUS Reference Book”의 “4.13. schemagen” 및 “JEUS Reference Book”의 “5.5.6. schemagen”을 참고한다.
전체적인 흐름은 다음과 같다.
소스 레벨에서 Schemagen 툴을 사용하여 Java 소스들로 스키마를 생성한다.
Java 소스들을 컴파일한다.
컴파일된 Java 소스에 대해 프로그래밍적으로 데이터를 입력하여 Java 오브젝트를 생성한다.
Java 오브젝트를 앞에서 얻은 스키마를 이용하여 마셜링(이 예제에서는 출력)한다.
다음은 이 예제 build.xml의 한 부분이다.
[예 19.5] << build.xml >>
... <project basedir="." default="run"> ... <taskdef name="schemagen" classname="com.sun.tools.jxc.SchemaGenTask"> <classpath refid="classpath" /> </taskdef> <target name="compile" description="Compile all Java source files"> <echo message="Generating schemas..." /> <mkdir dir="schemas" /> <schemagen destdir="schemas"> <src path="src" /> <classpath refid="classpath" /> </schemagen> <echo message="Compiling the java source files..." /> <mkdir dir="classes" /> <javac destdir="classes" debug="on"> <src path="src" /> <classpath refid="classpath" /> </javac> </target> <target name="run" depends="compile" description="Run the sample app"> <echo message="Running the sample application..." /> <java classname="Main" fork="true"> <classpath refid="classpath" /> </java> </target> ... </project>
다음은 이 예제에서 하나의 스키마를 나타내는 Java 클래스들이다.
BusinessCard.java
Address.java
jaxb.index
package-info.java
Main.java
이 중 Main.java에 대해서만 간략히 알아본다.
[예 19.6] << Main.java >>
BusinessCard card = new BusinessCard("John Doe", "Sr. Widget Designer", "Acme, Inc.", new Address(null, "123 Widget Way", "Anytown", "MA", (short) 12345), "123.456.7890", null, "123.456.7891", "John.Doe@Acme.ORG"); JAXBContext context = JAXBContext.newInstance(BusinessCard.class); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); m.marshal(card, new FileOutputStream(new File("src/conf/bcard.xml"))); ...
컴파일된 Java 소스를 이용하여 Java 오브젝트를 하나 생성하고 Marshaller를 하나 등록하여 bcard.xml이라는 파일에 마셜링한다.
[예 19.7] << Main.java (계속) >>
Unmarshaller um = context.createUnmarshaller(); Schema schema = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI) .newSchema(Main.class.getResource("schema1.xsd")); um.setSchema(schema); Object bce = um.unmarshal(new File("src/conf/bcard.xml")); m.marshal(bce, System.out);
생성된 스키마 파일을 이용하여 Unmarshaller를 하나 생성하고 앞에서 마셜링한 bcard.xml
파일을 Unmarshaller한다. 이를 다시 화면에 출력(Marshaller)한다.
XML과 Java는 그 성격상 플랫폼에 독립적이라는 면에서 여러 방면에서 함께 사용되었다. JEUS 7 웹 서비스는 XML 문서를 다루기 위한 Java 표준의 API를 지원한다. 이 표준은 Java의 표준 단체인 JCP가 명시한 XML 문서를 다루는 방식에 대한 표준(http://jcp.org/en/jsr/detail?id=206)을 따르고 있다. JAXP의 주요 API는 다음과 같다.
JEUS 7 웹 서비스는 XML을 파싱할 때 사용하는 Java 스트리밍 방식 또한 지원한다. 이 표준은 Java의 표준 단체인 JCP가 명시한 Java 스트리밍 XML 파서를 위한 API에 관한 표준(http://www.jcp.org/en/jsr/detail?id=173)을 따르고 있다.