วันพฤหัสบดีที่ 15 กันยายน พ.ศ. 2554

มาทำความรู้จักกับ JAXB

มาทำความรู้จักกับ JAXB
JAXB คืออะไร??
  • JAXB คือ โครงสร้างของ Java สำหรับการทำ XML Binding
โครงสร้างของ JAXB
1.      XML Schema :
 An XML schema ใช้รูปประโยค XML  เพื่ออธิบายความสัมพันธ์ระหว่าง องค์ประกอบ คุณสมบัติ และหน่วยต่างๆ ใน XML document วัตถุประสงค์ของ XML schema คือการกำหนด class ของ XML document ให้เป็นไปตามกฎระเบียบและข้อจำกัดของโครงสร้างข้อมูล
2.      Binding Customizations :
โดยปกติแล้ว JAXB binding จะคอมไพเลอร์ความสัมพันธ์ระหว่าง Java classes และ packages เพื่อ source ของXML schema บนพื้นฐานของกฎ ส่วนใหญ่กฎความสัมพันธ์เป็นสิ่งที่มากพอที่จะสร้างเซตของ schema of -derived classes ที่มีประสิทธิภาพจากความหลากหลายของ schema


3.      Binding Compiler :
คอมไพเลอร์ของ  JAXB binding เป็นแกนหลักของโมเดลการประมวลผล JAXB ฟังก์ชันเปลี่ยนแปลงหรือสัมพันธ์หรือเป็น source ของ XML schema เพื่อกำหนดเซตของคลาส JAXB ใน Java programming language
4.      Implementation of javax.xml.bind :
กรอบการดำเนินงานของ JAXB binding คือการ runtime API ที่มี interfaces สำหรับ unmarshal marshal และ validating XML content ใน  Java application. กรอบการทำงานของ binding ประกอบด้วย interfaces ในแพคเกจ javax.xml.bind
5.      Schema-Derived Classes:
ส่วนนี้เป็น class ของ schema-derived ที่ได้จากการ generated โดย binding JAXB compiler  class ที่เฉพาเจาะจงจะแตกต่างกันขึ้นอยู่กับ input ใน schema
6.      Java Application :
ในส่วนของ JAXB นี้ Java application คือ client application ที่ใช้กรอบการทำงานของ JAXB binding กับข้อมูลในส่วนของ unmarshal XML ตรวจสอบและปรับเปลี่ยน object ใน Java และ marshal Java กลับมาเป็น XML data
7.      XML Input Documents:
ในส่วน XML คือการ unmarshal ข้อมูลเข้าสู่ JAXB binding ก็คือ XML document ที่ได้จากการที่  Java แสดงออกมาในรูปแบบของต้นไม้
8.      XML Output Documents :
การนำข้อมูล XML มาทำการ marshal ให้ออกมาเป็น XML document ใน JAXB การทำmarshalเกี่ยวข้องกับการแยก XML ในรูปต้นไม้ และเขียนออกมา XML document แสดงข้อมูลที่ถูกต้องของ XML document เดิมและใช้ได้กับ source schema






กระบวนการการทำ JAXB Binding

1.      Generate classes:
ใน XML schema ใช้ input เข้าไป compile ใน JAXB binding เพื่อทำการ generate classe ของ JAXB  ตาม schema นั้นๆ
2.      Compile classes :
สิ่งที่ได้จากการ generate ทั้งหมดไม่ว่าจะเป็น class , source files, and application code จะต้องถูกคอมไพล์
3.      Unmarshal:
XML documents ที่สร้างขึ้นจะเขียนตามข้อจำกัดต่างๆ ใน source schema เป็นการ unmarshal โดยกระบวนการ JAXB binding สังเกตว่า JAXB ยังสนับสนุนการทำ unmarshal ข้อมูล XML จากแหล่งที่มาอื่นๆนอกจากไฟล์หรือเอกสาร document เช่น DOM nodes, string buffers, SAX Sources และอื่นๆ
4.      Generate content tree:
กระบวนการทำ unmarshal จะ generate ต้นไม้ของ object ต่างๆ  ยกตัวอย่างเช่น การ generated JAXB class ในต้นไม้จะแสดงโครงสร้างและส่วนประกอบต่างๆ ของ XML documents


5.      Validate (optional) :
กระบวนการทำ unmarshal  จะเลือกตัวที่เกี่ยวข้องกับการตรวจความถูกต้องของ source XML documents ก่อนที่จะทำการ generate ต้นไม้ สังเกตว่าถ้าหากเราทำการ modify ส่วนประกอบของต้นไม้ ในขั้นตอนที่ 6 เราสามารถดำเนินการตรวจสอบ JAXB เพื่อตรวจสอบการเปลี่ยนแปลงก่อนที่จะทำการ marshal ส่วนประกอบต่างๆ กลับเข้าไปใน XML document
6.      Process content :
              application ของผู้ใช้สามารถปรับเปลี่ยนแก้ไขข้อมูล XML ที่แสดงในรูปต้นไม้ด้วยวิธีการ generate interfaces ที่ได้จากการคอมไพล์ binding
7.      Marshal:
              การประมวลผลต้นไม้ คือ การ marshal  ออกไปหนึ่งหรือมากกว่าหนึ่งเอกสาร ส่วนประกอบต่างๆจะถูกตรวจสอบก่อนการทำ marshal


การทำ Marshal
              การทำ Marshal คือการให้โปรแกรมของผู้ใช้ที่มีความสามารถในการแปลง JAXB ที่ได้จากต้นไม้ Java กลับเข้ามาในข้อมูล XML โดยปกติ  Marchal จะใช้ UTF-8 encoding เมื่อทำการ generate ข้อมูล XML โปรแกรมของผู้ใช้จะไม่ทำการตรวจสอบส่วนประกอบของต้นไม้ก่อนที่จะทำ marshal รวมไปถึงไม่มีข้อกำหนดว่าส่วนประกอบของต้นไม้จะมีความถูกต้องตาม schema เดิมเพื่อทำการ marshal กลับเข้าสู่ข้อมูล XML

การทำ Unmarshal
              การทำ Unmarshal คือการให้โปรแกรมของผู้ใช้ที่มีความสามารถในการแปลง XML data ให้กลายเป็น JAXB-derived Java objects

การตรวจสอบความถูกต้อง (Validation)
              ในกระบวนการตรวจสอบว่าเอกสาร XML มีคุณสมบัติตรงตามข้อจำกัดทั้งหมดใน schema  ใน JAXB 1.0 จัดเตรียมการตรวจสอบความถูกต้องตอนที่ทำunmarshal รวมถึงตรวจสอบความต้องการการใช้งานในต้นไม้ ส่วนใน JAXB 2.0 จะตรวจสอบความถูกต้องเฉพาะเวลาทำ unmarshal และ marshal เท่านั้น



ข้อดีของ JAXB
Ø JAXB จำเป็นต้องมี DTD เพื่อให้การ JAXB ทำให้เกิดความถูกต้องของ XML
Ø การวิเคราะห์แบบ JAXB ทำได้เร็วกว่าการวิเคราะห์แบบ SAX
Ø ต้นไม้ที่สร้างขึ้นโดย JAXB มีขนาดเล็กกว่าต้นไม้ที่ได้จากวิธี DOM
Ø ต้นไม้ที่ได้จาก JAXB ใช้งานกับโปรแกรมที่มีความเฉพาะได้ง่ายกว่า
Ø สามารถแก้ไขต้นไม้และบันทึกเป็น XML ได้

ข้อเสียของ JAXB
Ø JAXB จำเป็นต้องมี DTD ดังนั้นจะไม่สามารถใช้ JAXB ในกระบวนการ XML ทั่วไป (เช่น การเขียนตัว editor XML หรือเครื่องมืออื่นๆ)
Ø คุณจะต้องทำงานล่วงหน้าเพื่อบอก JAXB ว่าต้นไม้ชนิดไหนที่คุณต้องการสร้าง


ตัวอย่างการ Run Program
Ø ตัวอย่างการสร้าง XmlSchemaType Class โดยใช้โปรแกรม NetBeans IDE มีขั้นตอนดังนี้
1.       เปิดโปรแกรม NetBeans IDE, เลือก FileOpen Project.
 
2.       ในหน้าต่าง Open Project, เลือก tut-install/javaeetutorial5/examples/jaxb/.
 
3.       เลือก the j2s-xmlSchemaType-class folder.
4.       เลือก the Open as Main Project check box.
5.       คลิก Open Project.
6.       คลิกขวาที่  j2s-xmlSchemaType-class project จากนั้นเลือก Run


<?xml version="1.0" encoding="UTF-8"?>
<project name="jaxb-ant-tasks" default="default">
    <import file="${ant.file.command-line-ant-tasks}/../common-properties.xml"/>
    <import file="${ant.file.command-line-ant-tasks}/../app-server-ant.xml"/>
   
    <property name="xjc.src.dir" value="${src.generated.dir}"/>
   
    <target name="check-jdk6-environment">
        <condition property="is.clean.jdk6">
            <and>
                <contains string="${java.version}" substring="1.6"/>
                <not>
                    <available classname="javax.xml.bind.annotation.XmlSeeAlso">
                        <classpath>
                            <fileset dir="${java.home}/lib">
                                <include name="*.jar"/>
                            </fileset>
                        </classpath>
                    </available>
                </not>
            </and>
        </condition>
        <condition property="is.jaxb.20">
            <and>
                <not>
                    <available classname="javax.xml.bind.annotation.XmlSeeAlso">
                        <classpath>
                            <fileset dir="${javaee.home}/lib">
                                <include name="*.jar"/>
                            </fileset>
                        </classpath>
                    </available>
                </not>
            </and>
        </condition>
        <condition property="is.jaxb.21">
            <available classname="javax.xml.bind.annotation.XmlSeeAlso">
                <classpath>
                    <fileset dir="${javaee.home}/lib">
                        <include name="*.jar"/>
                    </fileset>
                </classpath>
            </available>
        </condition>
       
    </target>
   
    <target name="update-endorsed"
            if="is.clean.jdk6"
            depends="check-jdk6-environment">
        <echo message="Updating ${java.home} with JAX-WS and JAXB 2.1 API."/>
        <mkdir dir="${java.home}/lib/endorsed"/>
        <copy file="${javaee.home}/lib/endorsed/webservices-api.jar"
              todir="${java.home}/lib/endorsed"/>
    </target>
   
    <target name="schemagen-init" depends="init, check-jdk6-environment">
        <taskdef name="schemagen"
            classname="com.sun.tools.jxc.SchemaGenTask">
            <classpath refid="javaee.classpath"/>
        </taskdef>
    </target>
   
    <target name="schemagen-generate" depends="schemagen-init">
        <echo message="Generating schemas..." />
        <schemagen destdir="${schemagen.destdir}" fork="true">
            <src path="${src.dir}" />
            <classpath refid="javaee.classpath"/>
        </schemagen>
    </target>
   
    <target name="xjc-init" depends="init, check-jdk6-environment">
        <taskdef name="xjc"
            classname="com.sun.tools.xjc.XJCTask">
            <classpath refid="javaee.classpath"/>
        </taskdef>
    </target>
   
    <target name="xjc-generate" depends="xjc-init">
        <antcall target="xjc-generate-binding"/>
        <antcall target="xjc-generate-nobinding"/>
    </target>
   
    <target name="xjc-generate-binding" if="xjc.binding.file">
        <echo message="Compiling the schema..." />
        <xjc schema="${xjc.schema}"
            package="${xjc.package.name}"
            destdir="${xjc.src.dir}"
            binding="${xjc.binding.file}">
            <depends dir="." includes="*.xsd"/>
            <produces dir="${xjc.src.dir}" includes="**/*.java"/>
        </xjc>
    </target>
   
    <target name="xjc-generate-nobinding" unless="xjc.binding.file">
        <echo message="Compiling the schema..." />
        <xjc schema="${xjc.schema}"
            package="${xjc.package.name}"
            destdir="${xjc.src.dir}">
            <depends dir="." includes="*.xsd"/>
            <produces dir="${xjc.src.dir}" includes="**/*.java"/>
        </xjc>
    </target>
   
    <target name="runapp" depends="compile,run-20,run-21"/>
   
    <target name="run-20" if="is.jaxb.20">
        <java classname="${main.class}" fork="true">
            <classpath refid="javaee.classpath"/>
            <classpath path="${run.classpath}"/>
        </java>
    </target>
   
    <target name="run-21" if="is.jaxb.21">
        <java classname="${main.class}" fork="true">
            <classpath refid="javaee.classpath"/>
            <classpath path="${run.classpath}"/>
            <jvmarg line="-Djava.endorsed.dirs=${javaee.home}/lib/endorsed"/>
        </java>
    </target>
   
</project>










Ø การสร้างและการรันการตรวจสอบตัวอย่าง Unmashal โดยการใช้  NetBeans IDE
1.       ใน   NetBeans IDE, เลือกไฟล์เปิดโครงการ

2.       ในการโต้ตอบโครงการเปิดให้นำทางไปยัง tut-install/javaeetutorial5/examples/jaxb /


3.       เลือกโฟลเดอร์แก้ไข Marshal -


4.       เลือก เปิดเป็นกล่องตรวจสอบโครงการหลัก
5.       คลิก เปิดโครงการ

6.       คลิกขวาที่โครงการ marshal validate และเลือก Run


จะได้ Code ในการทำ Unmarshal ดังนี้
<?xml version="1.0" encoding="UTF-8"?>
<project name="jaxb-ant-tasks" default="default">
    <import file="${ant.file.command-line-ant-tasks}/../common-properties.xml"/>
    <import file="${ant.file.command-line-ant-tasks}/../app-server-ant.xml"/>
    <property name="xjc.src.dir" value="${src.generated.dir}"/>
  
    <target name="check-jdk6-environment">
        <condition property="is.clean.jdk6">
            <and>
                <contains string="${java.version}" substring="1.6"/>
                <not>
                    <available classname="javax.xml.bind.annotation.XmlSeeAlso">
                        <classpath>
                            <fileset dir="${java.home}/lib">
                                <include name="*.jar"/>
                            </fileset>
                        </classpath>
                    </available>
                </not>
            </and>
        </condition>
        <condition property="is.jaxb.20">
            <and>
                <not>
                    <available classname="javax.xml.bind.annotation.XmlSeeAlso">
                        <classpath>
                            <fileset dir="${javaee.home}/lib">
                                <include name="*.jar"/>
                            </fileset>
                        </classpath>
                    </available>
                </not>
            </and>
        </condition>
        <condition property="is.jaxb.21">
            <available classname="javax.xml.bind.annotation.XmlSeeAlso">
                <classpath>
                    <fileset dir="${javaee.home}/lib">
                        <include name="*.jar"/>
                    </fileset>
                </classpath>
            </available>
        </condition>
       
    </target>
   
    <target name="update-endorsed"
            if="is.clean.jdk6"
            depends="check-jdk6-environment">
        <echo message="Updating ${java.home} with JAX-WS and JAXB 2.1 API."/>
        <mkdir dir="${java.home}/lib/endorsed"/>
        <copy file="${javaee.home}/lib/endorsed/webservices-api.jar"
              todir="${java.home}/lib/endorsed"/>
    </target>
    
    <target name="schemagen-init" depends="init, check-jdk6-environment">
        <taskdef name="schemagen"
            classname="com.sun.tools.jxc.SchemaGenTask">
            <classpath refid="javaee.classpath"/>
        </taskdef>
    </target>
   
    <target name="schemagen-generate" depends="schemagen-init">
        <echo message="Generating schemas..." />
        <schemagen destdir="${schemagen.destdir}" fork="true">
            <src path="${src.dir}" />
            <classpath refid="javaee.classpath"/>
        </schemagen>
    </target>
   
    <target name="xjc-init" depends="init, check-jdk6-environment">
        <taskdef name="xjc"
            classname="com.sun.tools.xjc.XJCTask">
            <classpath refid="javaee.classpath"/>
        </taskdef>
    </target>
   
    <target name="xjc-generate" depends="xjc-init">
        <antcall target="xjc-generate-binding"/>
        <antcall target="xjc-generate-nobinding"/>
    </target>
   
    <target name="xjc-generate-binding" if="xjc.binding.file">
        <echo message="Compiling the schema..." />
        <xjc schema="${xjc.schema}"
            package="${xjc.package.name}"
            destdir="${xjc.src.dir}"
            binding="${xjc.binding.file}">
            <depends dir="." includes="*.xsd"/>
            <produces dir="${xjc.src.dir}" includes="**/*.java"/>
        </xjc>
    </target>
   
    <target name="xjc-generate-nobinding" unless="xjc.binding.file">
        <echo message="Compiling the schema..." />
        <xjc schema="${xjc.schema}"
            package="${xjc.package.name}"
            destdir="${xjc.src.dir}">
            <depends dir="." includes="*.xsd"/>
            <produces dir="${xjc.src.dir}" includes="**/*.java"/>
        </xjc>
    </target>
   
    <target name="runapp" depends="compile,run-20,run-21"/>
   
    <target name="run-20" if="is.jaxb.20">
        <java classname="${main.class}" fork="true">
            <classpath refid="javaee.classpath"/>
            <classpath path="${run.classpath}"/>
        </java>
    </target>
   
    <target name="run-21" if="is.jaxb.21">
        <java classname="${main.class}" fork="true">
            <classpath refid="javaee.classpath"/>
            <classpath path="${run.classpath}"/>
            <jvmarg line="-Djava.endorsed.dirs=${javaee.home}/lib/endorsed"/>
        </java>
    </target>
   
</project>






























Ø การสร้างและใช้ตัวอย่างในการปรับเปลี่ยน Marshal ใช้ NetBeans IDE
1.       ใน   NetBeans IDE, เลือกไฟล์เปิดโครงการ

2.       ในการโต้ตอบโครงการเปิดให้นำทางไปยัง tut-install/javaeetutorial5/examples/jaxb /


3.       เลือกโฟลเดอร์แก้ไข Marshal -


4.       เลือก เปิดเป็นกล่องตรวจสอบโครงการหลัก


5.       คลิก เปิดโครงการ

6.       คลิกขวาที่โครงการปรับเปลี่ยน marshal และเลือก Run


จะได้ Code ในการทำ Marshal ดังนี้
<?xml version="1.0" encoding="UTF-8"?>
<project name="jaxb-ant-tasks" default="default">
    <import file="${ant.file.command-line-ant-tasks}/../common-properties.xml"/>
    <import file="${ant.file.command-line-ant-tasks}/../app-server-ant.xml"/>
   
    <property name="xjc.src.dir" value="${src.generated.dir}"/>
   
    <target name="check-jdk6-environment">
        <condition property="is.clean.jdk6">
            <and>
                <contains string="${java.version}" substring="1.6"/>
                <not>
                    <available classname="javax.xml.bind.annotation.XmlSeeAlso">
                        <classpath>
                            <fileset dir="${java.home}/lib">
                                <include name="*.jar"/>
                            </fileset>
                        </classpath>
                    </available>
                </not>
            </and>
        </condition>
        <condition property="is.jaxb.20">
            <and>
                <not>
                    <available classname="javax.xml.bind.annotation.XmlSeeAlso">
                        <classpath>
                            <fileset dir="${javaee.home}/lib">
                                <include name="*.jar"/>
                            </fileset>
                        </classpath>
                    </available>
                </not>
            </and>
        </condition>
        <condition property="is.jaxb.21">
            <available classname="javax.xml.bind.annotation.XmlSeeAlso">
                <classpath>
                    <fileset dir="${javaee.home}/lib">
                        <include name="*.jar"/>
                    </fileset>
                </classpath>
            </available>
        </condition>
       
    </target>
   
    <target name="update-endorsed"
            if="is.clean.jdk6"
            depends="check-jdk6-environment">
        <echo message="Updating ${java.home} with JAX-WS and JAXB 2.1 API."/>
        <mkdir dir="${java.home}/lib/endorsed"/>
        <copy file="${javaee.home}/lib/endorsed/webservices-api.jar"
              todir="${java.home}/lib/endorsed"/>
    </target>
   
    <target name="schemagen-init" depends="init, check-jdk6-environment">
        <taskdef name="schemagen"
            classname="com.sun.tools.jxc.SchemaGenTask">
            <classpath refid="javaee.classpath"/>
        </taskdef>
    </target>
   
    <target name="schemagen-generate" depends="schemagen-init">
        <echo message="Generating schemas..." />
        <schemagen destdir="${schemagen.destdir}" fork="true">
            <src path="${src.dir}" />
            <classpath refid="javaee.classpath"/>
        </schemagen>
    </target>
   
    <target name="xjc-init" depends="init, check-jdk6-environment">
        <taskdef name="xjc"
            classname="com.sun.tools.xjc.XJCTask">
            <classpath refid="javaee.classpath"/>
        </taskdef>
    </target>
   
    <target name="xjc-generate" depends="xjc-init">
        <antcall target="xjc-generate-binding"/>
        <antcall target="xjc-generate-nobinding"/>
    </target>
   
    <target name="xjc-generate-binding" if="xjc.binding.file">
        <echo message="Compiling the schema..." />
        <xjc schema="${xjc.schema}"
            package="${xjc.package.name}"
            destdir="${xjc.src.dir}"
            binding="${xjc.binding.file}">
            <depends dir="." includes="*.xsd"/>
            <produces dir="${xjc.src.dir}" includes="**/*.java"/>
        </xjc>
    </target>
   
    <target name="xjc-generate-nobinding" unless="xjc.binding.file">
        <echo message="Compiling the schema..." />
        <xjc schema="${xjc.schema}"
            package="${xjc.package.name}"
            destdir="${xjc.src.dir}">
            <depends dir="." includes="*.xsd"/>
            <produces dir="${xjc.src.dir}" includes="**/*.java"/>
        </xjc>
    </target>
   
    <target name="runapp" depends="compile,run-20,run-21"/>
   
    <target name="run-20" if="is.jaxb.20">
        <java classname="${main.class}" fork="true">
            <classpath refid="javaee.classpath"/>
            <classpath path="${run.classpath}"/>
        </java>
    </target>
   
    <target name="run-21" if="is.jaxb.21">
        <java classname="${main.class}" fork="true">
            <classpath refid="javaee.classpath"/>
            <classpath path="${run.classpath}"/>
            <jvmarg line="-Djava.endorsed.dirs=${javaee.home}/lib/endorsed"/>
        </java>
    </target>
   
</project>

ไม่มีความคิดเห็น:

แสดงความคิดเห็น