2011年6月3日 星期五

Apache Betwixt - JavaBean to XML, XML to JavaBean

最近用到把JavaBean 轉成 XML , 再把XML轉成JavaBean,用到的的Apache commons下面的一個項目,Commons Betwixt ,betwixt 提供了一個機制,可以把XML 跟JavaBean做Mapping, 主要是透過XMLIntrospector和XMLBeanInfo來完成,如果有一個良好的schema時,JAXP和Castor可以自動生成beans來解析和處理XML。
而Betwixt,只需要編寫beans,而不需要關注XML schemas,並且提供了比較簡單的命名規範(使用getter,setter,adder方法)。
在網路上有看到一編文章在比較Betwixt & Xstream 的不同處,Betwixt 在解析XML時是使用SAX, 而Xstream是使用DOM,Xstream使用上似乎比Betwixt來的方便一些,個人在使用Betwixt時碰到一些設定會讓Betwixt抓不到相對應的bean。另外一個是Jdk 6裡面帶的StAx,有興趣的可以看看, Introduction to StAX


XML Parser API Feature Summary
Feature
StAX
SAX
DOM
TrAX
API Type
Pull, streaming
Push, streaming
In memory tree
XSLT Rule
Ease of Use
High
Medium
High
Medium
XPath Capability
No
No
Yes
Yes
CPU and Memory Efficiency
Good
Good
Varies
Varies
Forward Only
Yes
Yes
No
No
Read XML
Yes
Yes
Yes
Yes
Write XML
Yes
No
Yes
Yes
Create, Read, Update, Delete
No
No
Yes
No
這邊針對Betwixt 做簡單的使用介紹,
首先要下載Betwixt, 可以在 這邊 找到

首先要將Bean轉成XML,先看看最後轉出來的XML長什麼樣子
<?xml version='1.0' encoding='UTF-8' ?>
<MailRootBean>
  <versionCheckObject>
    <version>1.0</version>
  </versionCheckObject>
  <mailInfoObject>
    <attachList>
      <attachementObject>
        <attachementDataStream>cGFja2FnZSBjb20uZ2ZhY3Rvci5lbWFpbGRpc2NvdmVyeS51dGlsczsNCg0KaW1wb3J0IGphdmEudXRpbC5BcnJheXM7DQoNCmltcG9ydCBqYXZheC5hbm5vdGF0aW9uLlBvc3RDb25zdHJ1Y3Q7DQoNCmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMubG9nZ2luZy5Mb2c7DQppbXBvcnQgb3JnLmFzcGVjdGoubGFuZy5Qcm9jZWVkaW5nSm9pblBvaW50Ow0KaW1wb3J0IG9yZy5hc3BlY3RqLmxhbmcuYW5ub3RhdGlvbi5Bcm91bmQ7DQppbXBvcnQgb3JnLmFzcGVjdGoubGFuZy5hbm5vdGF0aW9uLkFzcGVjdDsNCmltcG9ydCBvcmcuYXNwZWN0ai5sYW5nLmFubm90YXRpb24uUG9pbnRjdXQ7DQppbXBvcnQgb3JnLnNwcmluZ2ZyYW1ld29yay51dGlsLkFzc2VydDsNCmltcG9ydCBvcmcuc3ByaW5nZnJhbWV3b3JrLnV0aWwuU3RvcFdhdGNoOw0KDQoNCkBBc3BlY3QNCnB1YmxpYyBjbGFzcyBQcm9jZXNzVGltZUxvZ2dlciB7DQoJcHJpdmF0ZSBTdHJpbmcgYmVmb3JlTWVzc2FnZTsNCglwcml2YXRlIFN0cmluZyBhZnRlck1lc3NhZ2U7DQoJcHJpdmF0ZSBzdGF0aWMgZmluYWwgTG9nIGxvZ2dlciA9IE15VXRpbHMuZ2V0TG9nKCk7IA0KCQ0KCUBQb2ludGN1dCgiZXhlY3V0aW9uKCogY29tLmdmYWN0b3IuZW1haWxkaXNjb3Zlcnkuc2VydmljZS4qLiooLi4pKSIpDQoJcHJpdmF0ZSB2b2lkIHRlc3RCZWFuRXhlY3V0aW9uKCkgeyB9DQogDQoJDQoJQFBvaW50Y3V0KCJleGVjdXRpb24oKiBjb20uZ2ZhY3Rvci5lbWFpbGRpc2NvdmVyeS5kYW8uaW1wbC4qLiooLi4pKSIpDQoJcHJpdmF0ZSB2b2lkIGRhb0V4ZWN1dGlvbigpIHsgfQ0KCQ0KCUBBcm91bmQoImRhb0V4ZWN1dGlvbigpIikNCglwdWJsaWMgT2JqZWN0IGRvUHJvY2VzcyhQcm9jZWVkaW5nSm9pblBvaW50IHBqcCkgdGhyb3dzIFRocm93YWJsZSB7DQoJCVN0cmluZyBjbGFzc05hbWUgPSBwanAuZ2V0VGFyZ2V0KCkuZ2V0Q2xhc3MoKS5nZXROYW1lKCk7DQoJCVN0cmluZyBtZXRob2QgPSBwanAuZ2V0U2lnbmF0dXJlKCkuZ2V0TmFtZSgpOw0KCQlsb2dnZXIuaW5mbyhTdHJpbmcuZm9ybWF0KHRoaXMuYmVmb3JlTWVzc2FnZSxjbGFzc05hbWUsIG1ldGhvZCxBcnJheXMudG9TdHJpbmcocGpwLmdldEFyZ3MoKSkpKTsNCgkJDQoJCVN0b3BXYXRjaCB3YXRjaCA9IG5ldyBTdG9wV2F0Y2goKTsNCgkJd2F0Y2guc3RhcnQoKTsNCgkJT2JqZWN0IHJlc3VsdCA9IHBqcC5wcm9jZWVkKCk7DQoJCXdhdGNoLnN0b3AoKTsNCgkJDQoJCWxvZ2dlci5pbmZvKFN0cmluZy5mb3JtYXQodGhpcy5hZnRlck1lc3NhZ2UsbWV0aG9kLGNsYXNzTmFtZSwgQXJyYXlzLnRvU3RyaW5nKHBqcC5nZXRBcmdzKCkpKSk7DQoJCVN0cmluZyBsb2cgPSBjbGFzc05hbWUgKyAiIFJ1biAiICsgbWV0aG9kICsgIm1ldGhvZCBjb21wbGV0ZSBpbiAiKyB3YXRjaC5nZXRUb3RhbFRpbWVNaWxsaXMoKSArICIgbXMiOw0KCQlsb2dnZXIuaW5mbyhsb2cpOw0KCQlyZXR1cm4gcmVzdWx0Ow0KLy8JCS8vIERvIHdoYXQgeW91IHdhbnQgd2l0aCB0aGUgam9pbiBwb2ludCBhcmd1bWVudHMNCi8vCQlmb3IgKCBPYmplY3Qgb2JqZWN0IDogam9pblBvaW50LmdldEFyZ3MoKSkgew0KLy8JCQkNCi8vCQkJbG9nZ2VyLmluZm8oIioqKioqKiBBT1Agb2JqZWN0ID0iICsgb2JqZWN0KTsNCi8vCQl9DQovLwkJcmV0dXJuIGpvaW5Qb2ludDsNCgkJDQoJfQ0KCQ0KCUBQb3N0Q29uc3RydWN0DQoJcHVibGljIHZvaWQgaW5pdGlhbGl6ZSgpIHsNCgkgICAgQXNzZXJ0Lm5vdE51bGwodGhpcy5iZWZvcmVNZXNzYWdlLA0KCSAgICAgICAgIlRoZSBbYmVmb3JlTWVzc2FnZV0gcHJvcGVydHkgb2YgWyIgKyBnZXRDbGFzcygpLmdldE5hbWUoKSArDQoJICAgICAgICAiXSBtdXN0IGJlIHNldC4iKTsNCgkgICAgQXNzZXJ0Lm5vdE51bGwodGhpcy5hZnRlck1lc3NhZ2UsDQoJICAgICAgICAiVGhlIFthZnRlck1lc3NhZ2VdIHByb3BlcnR5IG9mIFsiICsgZ2V0Q2xhc3MoKS5nZXROYW1lKCkgKw0KCSAgICAgICAgIl0gbXVzdCBiZSBzZXQuIik7DQoJfQ0KCXB1YmxpYyB2b2lkIHNldEJlZm9yZU1lc3NhZ2UoU3RyaW5nIGJlZm9yZU1lc3NhZ2UpIHsNCgkgICAgdGhpcy5iZWZvcmVNZXNzYWdlID0gYmVmb3JlTWVzc2FnZTsNCgl9DQoJcHVibGljIHZvaWQgc2V0QWZ0ZXJNZXNzYWdlKFN0cmluZyBhZnRlck1lc3NhZ2UpIHsNCgkgICAgdGhpcy5hZnRlck1lc3NhZ2UgPSBhZnRlck1lc3NhZ2U7DQoJfQ0KfQ0K</attachementDataStream>
        <attachmentContentType>text/plain;
 name="ProcessTimeLogger.java"</attachmentContentType>
        <attachmentFileName>ProcessTimeLogger.java</attachmentFileName>
      </attachementObject>
      <attachementObject>
        <attachementDataStream>cGFja2FnZSBjb20uZ2ZhY3Rvci5lbWFpbGRpc2NvdmVyeS51dGlsczsNCg0KaW1wb3J0IHN0YXRpYyBjb20uZ2ZhY3Rvci5lbWFpbGRpc2NvdmVyeS51dGlscy5UcmFuc2FjdGlvbkluZGljYXRpbmdVdGlsLmdldFRyYW5zYWN0aW9uU3RhdHVzOw0KDQppbXBvcnQgb3JnLmFwYWNoZS5sb2c0ai5zcGkuRmlsdGVyOw0KaW1wb3J0IG9yZy5hcGFjaGUubG9nNGouc3BpLkxvZ2dpbmdFdmVudDsNCg0KcHVibGljIGNsYXNzIFRyYW5zYWN0aW9uSW5kaWNhdGluZ0ZpbHRlciBleHRlbmRzIEZpbHRlciB7DQogICAgQE92ZXJyaWRlDQogICAgcHVibGljIGludCBkZWNpZGUoTG9nZ2luZ0V2ZW50IGxvZ2dpbmdFdmVudCkgew0KICAgICAgICBsb2dnaW5nRXZlbnQuc2V0UHJvcGVydHkoInhhTmFtZSIsIGdldFRyYW5zYWN0aW9uU3RhdHVzKHRydWUpICk7DQogICAgICAgIGxvZ2dpbmdFdmVudC5zZXRQcm9wZXJ0eSgieGFTdGF0dXMiLCBnZXRUcmFuc2FjdGlvblN0YXR1cyhmYWxzZSkgKTsNCiAgICAgICAgcmV0dXJuIEZpbHRlci5ORVVUUkFMOw0KICAgIH0gIA0KfQ0K</attachementDataStream>
        <attachmentContentType>text/plain;
 name="TransactionIndicatingFilter.java"</attachmentContentType>
        <attachmentFileName>TransactionIndicatingFilter.java</attachmentFileName>
      </attachementObject>
      <attachementObject>
        <attachementDataStream>cGFja2FnZSBjb20uZ2ZhY3Rvci5lbWFpbGRpc2NvdmVyeS51dGlsczsNCg0KcHVibGljIGNsYXNzIFRyYW5zYWN0aW9uSW5kaWNhdGluZ1V0aWwgew0KCXByaXZhdGUgZmluYWwgc3RhdGljIFN0cmluZyBUU01fQ0xBU1NOQU1FID0gIm9yZy5zcHJpbmdmcmFtZXdvcmsudHJhbnNhY3Rpb24uc3VwcG9ydC5UcmFuc2FjdGlvblN5bmNocm9uaXphdGlvbk1hbmFnZXIiOw0KDQoJcHVibGljIHN0YXRpYyBTdHJpbmcgZ2V0VHJhbnNhY3Rpb25TdGF0dXMoYm9vbGVhbiB2ZXJib3NlKSB7DQoJCVN0cmluZyBzdGF0dXMgPSBudWxsOw0KDQoJCXRyeSB7DQoJCQlDbGFzc0xvYWRlciBjb250ZXh0Q2xhc3NMb2FkZXIgPSBUaHJlYWQuY3VycmVudFRocmVhZCgpLmdldENvbnRleHRDbGFzc0xvYWRlcigpOw0KCQkJDQoJCQlpZiAoY29udGV4dENsYXNzTG9hZGVyICE9IG51bGwpIHsNCgkJCQlDbGFzcyB0c21DbGFzcyA9IGNvbnRleHRDbGFzc0xvYWRlci5sb2FkQ2xhc3MoVFNNX0NMQVNTTkFNRSk7DQoJCQkJQm9vbGVhbiBpc0FjdGl2ZSA9IChCb29sZWFuKSB0c21DbGFzcy5nZXRNZXRob2QoImlzQWN0dWFsVHJhbnNhY3Rpb25BY3RpdmUiLCBudWxsKS5pbnZva2UobnVsbCwgbnVsbCk7DQoJCQkJDQoJCQkJaWYgKCF2ZXJib3NlKSB7DQoJCQkJCXN0YXR1cyA9IChpc0FjdGl2ZSkgPyAiWytdICIgOiAiWy1dICI7DQoJCQkJfSBlbHNlIHsNCgkJCQkJU3RyaW5nIHRyYW5zYWN0aW9uTmFtZSA9IChTdHJpbmcpIHRzbUNsYXNzLmdldE1ldGhvZCgiZ2V0Q3VycmVudFRyYW5zYWN0aW9uTmFtZSIsIG51bGwpLmludm9rZShudWxsLG51bGwpOw0KCQkJCQkNCgkJCQkJc3RhdHVzID0gKGlzQWN0aXZlKSA/ICJbIiArIHRyYW5zYWN0aW9uTmFtZSArICJdICIgOiAiW25vIHRyYW5zYWN0aW9uXSAiOw0KCQkJCX0NCgkJCX0gZWxzZSB7DQoJCQkJc3RhdHVzID0gKHZlcmJvc2UpID8gIltjY2wgdW5hdmFpbGFibGVdICIgOiAiW3ggXSI7DQoJCQl9DQoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7DQoJCQlzdGF0dXMgPSAodmVyYm9zZSkgPyAiW3NwcmluZyB1bmF2YWlsYWJsZV0gIiA6ICJbeCBdIjsNCgkJfQ0KCQlyZXR1cm4gc3RhdHVzOw0KCX0NCn0NCg==</attachementDataStream>
        <attachmentContentType>text/plain;
 name="TransactionIndicatingUtil.java"</attachmentContentType>
        <attachmentFileName>TransactionIndicatingUtil.java</attachmentFileName>
      </attachementObject>
    </attachList>
    <bccRecipipent/>
    <body>testests</body>
    <bodyContentType>text/plain; charset=UTF-8; format=flowed</bodyContentType>
    <ccRecipipent/>
    <mailId>&lt;4DE4AC51.9060806@mydomain.james&gt;</mailId>
    <sender>admin@mydomain.james</sender>
    <subject>testes</subject>
    <toRecipipent>test@mydomain.james</toRecipipent>
  </mailInfoObject>
</MailRootBean>

這邊總供是分成3個Bean, Root的MailRootBean, 在root裡面包含2個區塊,versionCheckObject,mailInfoObject, 寫入的時候會將直接透過write寫入, 但是讀取的時候會以MailRootBean為mapping, code如下

MailInfoObject.java
package com.mypackage.MailXmlObject;

import java.util.ArrayList;

public class MailInfoObject {
 private String mailId; 
 private String sender;
 private String ToRecipipent;
 private String CcRecipipent;
 private String BccRecipipent;
 private String Subject;
 private String BodyContentType;
 private String body;
 private ArrayList<AttachementObject> attachList = new ArrayList<AttachementObject>();
 
 
 
 public String getSender() {
  return sender;
 }
 public void setSender(String sender) {
  this.sender = sender;
 }
 public String getToRecipipent() {
  return ToRecipipent;
 }
 public void setToRecipipent(String toRecipipent) {
  ToRecipipent = toRecipipent;
 }
 public String getCcRecipipent() {
  return CcRecipipent;
 }
 public void setCcRecipipent(String ccRecipipent) {
  CcRecipipent = ccRecipipent;
 }
 public String getBccRecipipent() {
  return BccRecipipent;
 }
 public void setBccRecipipent(String bccRecipipent) {
  BccRecipipent = bccRecipipent;
 }
 public String getSubject() {
  return Subject;
 }
 public void setSubject(String subject) {
  Subject = subject;
 }
 public String getBodyContentType() {
  return BodyContentType;
 }
 public void setBodyContentType(String bodyContentType) {
  BodyContentType = bodyContentType;
 }
 public String getBody() {
  return body;
 }
 public void setBody(String body) {
  this.body = body;
 }
 public ArrayList<AttachementObject> getAttachList() {
  return attachList;
 }
 public void setAttachList(ArrayList<AttachementObject> attachList) {
  this.attachList = attachList;
 }  

 public void addAttachementObject(AttachementObject attachementObject) {
  attachList.add(attachementObject);
 }
 public String getMailId() {
  return mailId;
 }
 public void setMailId(String mailId) {
  this.mailId = mailId;
 }
 
 @Override
 public String toString(){
  StringBuilder resultBuilder = new StringBuilder();  
  resultBuilder.append("mailId : "   this.getMailId()   "\n");
  resultBuilder.append("sender : "   this.getSender()   "\n");
  resultBuilder.append("ToRecipipent : "   this.getToRecipipent() "\n");
  resultBuilder.append("CcRecipipent : "   this.getCcRecipipent() "\n");
  resultBuilder.append("BccRecipipent : "   this.getBccRecipipent() "\n");
  resultBuilder.append("Subject : "   this.getSubject() "\n");
  resultBuilder.append("BodyContentType : "   this.getBodyContentType() "\n");
  resultBuilder.append("body : "   this.getBody() "\n");
  resultBuilder.append("attachList : "  attachList "\n");
  if(attachList != null){
   resultBuilder.append("attachList size ="   attachList.size() "\n");
   for (int i = 0; i < attachList.size(); i  ) {
    resultBuilder.append(attachList.get(i).toString() "\n");
   }
  }
  
  return resultBuilder.toString();
  
 }
}


AttachementObject.java
package com.mypackage.MailXmlObject;

public class AttachementObject {
 private String attachmentContentType;
 private String attachmentFileName;
 private String attachementDataStream;
 public String getAttachmentContentType() {
  return attachmentContentType;
 }
 public void setAttachmentContentType(String attachmentContentType) {
  this.attachmentContentType = attachmentContentType;
 }
 public String getAttachmentFileName() {
  return attachmentFileName;
 }
 public void setAttachmentFileName(String attachmentFileName) {
  this.attachmentFileName = attachmentFileName;
 }
 public String getAttachementDataStream() {
  return attachementDataStream;
 }
 public void setAttachementDataStream(String attachementDataStream) {
  this.attachementDataStream = attachementDataStream;
 }
 
 @Override
 public String toString(){
  StringBuilder resultBuilder = new StringBuilder();
  resultBuilder.append("attachmentFileName : "  this.getAttachmentFileName() "\n");
  resultBuilder.append("attachmentContentType : "  this.getAttachmentContentType() "\n");
  resultBuilder.append("attachementDataStream : "  this.getAttachementDataStream() "\n");
  return resultBuilder.toString();
 }
}

versionChkObj.java
package com.mypackage.MailXmlObject;

public class VersionCheckObject {
 private String version;

 public String getVersion() {
  return version;
 }

 public void setVersion(String version) {
  this.version = version;
 }
 
 
}

BetwixtXmlBuilder.java
/**
 * 
 */
package com.mypackage.xmlbuilder;


import java.beans.IntrospectionException;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;

import org.apache.commons.betwixt.io.BeanReader;
import org.apache.commons.betwixt.io.BeanWriter;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;

import com.mypackage.MailXmlObject.MailInfoObject;
import com.mypackage.MailXmlObject.MailRootBean;
import com.mypackage.MailXmlObject.VersionCheckObject;

/**
 * @author momo
 *
 */
public class BetwixtXmlBuilder extends AbstractXmlBuilder {
 MailInfoObject mailobject;
 VersionCheckObject versionChkObj;
 
 public BetwixtXmlBuilder(){
  
 }
 public BetwixtXmlBuilder(MailInfoObject mailobj,VersionCheckObject verchkobj){
  this.mailobject = mailobj;
  this.versionChkObj = verchkobj;
 }
 
 /* (non-Javadoc)
  * @see com.mypackage.xmlbuilder.AbstractXmlBuilder#builderXml()
  */
 @Override
 public void builderXml() {
  try{
   String fileName = this.defaultFilePath this.mailobject.getMailId() ".xml";
   fileName = fileName.replaceAll("<", "");
   fileName = fileName.replaceAll(">", "");
   
   StringWriter outputWriter = new StringWriter();
   outputWriter.write("<?xml version='1.0' encoding='UTF-8' ?>\n");
   outputWriter.write("<MailRootBean>\n");
   BeanWriter beanWriter = new BeanWriter(outputWriter);
   beanWriter.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(false);
   beanWriter.getBindingConfiguration().setMapIDs(false);
   beanWriter.enablePrettyPrint( );
   beanWriter.write("versionCheckObject",this.versionChkObj );
   beanWriter.write("mailInfoObject",this.mailobject );
   //write to files
   outputWriter.write("</MailRootBean>\n");
   BufferedWriter out = new BufferedWriter(new FileWriter(fileName));
   out.write(outputWriter.toString());
   out.close();
   
   beanWriter.close();
         outputWriter.close();
  }catch(Exception ex){
   
  }
  
 }

 
 

}

這邊會先建立一個StringWriter, 先寫入XML version tag, 跟root tag, 然後再透過BeanWriter的constructor 傳入一個StringWriter 物件, 然後設定setAttributesForPrimitives 為false , setAttributesForPrimitives設定為false 的差異如下,
setAttributesForPrimitives = true
<root>
    <age>21</age>
</root>
setAttributesForPrimitives = false
<root age="21"/>

setMapIDs 設成false , 代表不自動生成ID,
然後再透過beanwrite將2個bean寫入,
beanWriter.write("versionCheckObject",this.versionChkObj );
beanWriter.write("mailInfoObject",this.mailobject );
這會將versionChkObj bean 寫入到xml , tag 為versionCheckObject, 另一個為mailInfoObject,
這樣就能簡單的把Bean轉入成 XML ,


讀取XML並且轉回成Bean物件, 如果有看到上面的MailInfoObject.java 的話可以注意到有一個method
public void addAttachementObject(AttachementObject attachementObject) {
  attachList.add(attachementObject);
 }
這個method如果你是用eclipse 生成bean的getter&setter的話,要手動加上這段, 主要是因為在mailInfoObject 的XML tag裡面包含了Attachement file , 而Attachement 的格式如下
<attachList>
      <attachementObject>
        <attachementDataStream>cGFja2FnZSBjb20uZ2ZhY3Rvci5lbWFpbGRpc2NvdmVyeS51dGlsczsNCg0KaW1wb3J0IGphdmEudXRpbC5BcnJheXM7DQoNCmltcG9ydCBqYXZheC5hbm5vdGF0aW9uLlBvc3RDb25zdHJ1Y3Q7DQoNCmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMubG9nZ2luZy5Mb2c7DQppbXBvcnQgb3JnLmFzcGVjdGoubGFuZy5Qcm9jZWVkaW5nSm9pblBvaW50Ow0KaW1wb3J0IG9yZy5hc3BlY3RqLmxhbmcuYW5ub3RhdGlvbi5Bcm91bmQ7DQppbXBvcnQgb3JnLmFzcGVjdGoubGFuZy5hbm5vdGF0aW9uLkFzcGVjdDsNCmltcG9ydCBvcmcuYXNwZWN0ai5sYW5nLmFubm90YXRpb24uUG9pbnRjdXQ7DQppbXBvcnQgb3JnLnNwcmluZ2ZyYW1ld29yay51dGlsLkFzc2VydDsNCmltcG9ydCBvcmcuc3ByaW5nZnJhbWV3b3JrLnV0aWwuU3RvcFdhdGNoOw0KDQoNCkBBc3BlY3QNCnB1YmxpYyBjbGFzcyBQcm9jZXNzVGltZUxvZ2dlciB7DQoJcHJpdmF0ZSBTdHJpbmcgYmVmb3JlTWVzc2FnZTsNCglwcml2YXRlIFN0cmluZyBhZnRlck1lc3NhZ2U7DQoJcHJpdmF0ZSBzdGF0aWMgZmluYWwgTG9nIGxvZ2dlciA9IE15VXRpbHMuZ2V0TG9nKCk7IA0KCQ0KCUBQb2ludGN1dCgiZXhlY3V0aW9uKCogY29tLmdmYWN0b3IuZW1haWxkaXNjb3Zlcnkuc2VydmljZS4qLiooLi4pKSIpDQoJcHJpdmF0ZSB2b2lkIHRlc3RCZWFuRXhlY3V0aW9uKCkgeyB9DQogDQoJDQoJQFBvaW50Y3V0KCJleGVjdXRpb24oKiBjb20uZ2ZhY3Rvci5lbWFpbGRpc2NvdmVyeS5kYW8uaW1wbC4qLiooLi4pKSIpDQoJcHJpdmF0ZSB2b2lkIGRhb0V4ZWN1dGlvbigpIHsgfQ0KCQ0KCUBBcm91bmQoImRhb0V4ZWN1dGlvbigpIikNCglwdWJsaWMgT2JqZWN0IGRvUHJvY2VzcyhQcm9jZWVkaW5nSm9pblBvaW50IHBqcCkgdGhyb3dzIFRocm93YWJsZSB7DQoJCVN0cmluZyBjbGFzc05hbWUgPSBwanAuZ2V0VGFyZ2V0KCkuZ2V0Q2xhc3MoKS5nZXROYW1lKCk7DQoJCVN0cmluZyBtZXRob2QgPSBwanAuZ2V0U2lnbmF0dXJlKCkuZ2V0TmFtZSgpOw0KCQlsb2dnZXIuaW5mbyhTdHJpbmcuZm9ybWF0KHRoaXMuYmVmb3JlTWVzc2FnZSxjbGFzc05hbWUsIG1ldGhvZCxBcnJheXMudG9TdHJpbmcocGpwLmdldEFyZ3MoKSkpKTsNCgkJDQoJCVN0b3BXYXRjaCB3YXRjaCA9IG5ldyBTdG9wV2F0Y2goKTsNCgkJd2F0Y2guc3RhcnQoKTsNCgkJT2JqZWN0IHJlc3VsdCA9IHBqcC5wcm9jZWVkKCk7DQoJCXdhdGNoLnN0b3AoKTsNCgkJDQoJCWxvZ2dlci5pbmZvKFN0cmluZy5mb3JtYXQodGhpcy5hZnRlck1lc3NhZ2UsbWV0aG9kLGNsYXNzTmFtZSwgQXJyYXlzLnRvU3RyaW5nKHBqcC5nZXRBcmdzKCkpKSk7DQoJCVN0cmluZyBsb2cgPSBjbGFzc05hbWUgKyAiIFJ1biAiICsgbWV0aG9kICsgIm1ldGhvZCBjb21wbGV0ZSBpbiAiKyB3YXRjaC5nZXRUb3RhbFRpbWVNaWxsaXMoKSArICIgbXMiOw0KCQlsb2dnZXIuaW5mbyhsb2cpOw0KCQlyZXR1cm4gcmVzdWx0Ow0KLy8JCS8vIERvIHdoYXQgeW91IHdhbnQgd2l0aCB0aGUgam9pbiBwb2ludCBhcmd1bWVudHMNCi8vCQlmb3IgKCBPYmplY3Qgb2JqZWN0IDogam9pblBvaW50LmdldEFyZ3MoKSkgew0KLy8JCQkNCi8vCQkJbG9nZ2VyLmluZm8oIioqKioqKiBBT1Agb2JqZWN0ID0iICsgb2JqZWN0KTsNCi8vCQl9DQovLwkJcmV0dXJuIGpvaW5Qb2ludDsNCgkJDQoJfQ0KCQ0KCUBQb3N0Q29uc3RydWN0DQoJcHVibGljIHZvaWQgaW5pdGlhbGl6ZSgpIHsNCgkgICAgQXNzZXJ0Lm5vdE51bGwodGhpcy5iZWZvcmVNZXNzYWdlLA0KCSAgICAgICAgIlRoZSBbYmVmb3JlTWVzc2FnZV0gcHJvcGVydHkgb2YgWyIgKyBnZXRDbGFzcygpLmdldE5hbWUoKSArDQoJICAgICAgICAiXSBtdXN0IGJlIHNldC4iKTsNCgkgICAgQXNzZXJ0Lm5vdE51bGwodGhpcy5hZnRlck1lc3NhZ2UsDQoJICAgICAgICAiVGhlIFthZnRlck1lc3NhZ2VdIHByb3BlcnR5IG9mIFsiICsgZ2V0Q2xhc3MoKS5nZXROYW1lKCkgKw0KCSAgICAgICAgIl0gbXVzdCBiZSBzZXQuIik7DQoJfQ0KCXB1YmxpYyB2b2lkIHNldEJlZm9yZU1lc3NhZ2UoU3RyaW5nIGJlZm9yZU1lc3NhZ2UpIHsNCgkgICAgdGhpcy5iZWZvcmVNZXNzYWdlID0gYmVmb3JlTWVzc2FnZTsNCgl9DQoJcHVibGljIHZvaWQgc2V0QWZ0ZXJNZXNzYWdlKFN0cmluZyBhZnRlck1lc3NhZ2UpIHsNCgkgICAgdGhpcy5hZnRlck1lc3NhZ2UgPSBhZnRlck1lc3NhZ2U7DQoJfQ0KfQ0K</attachementDataStream>
        <attachmentContentType>text/plain;
 name="ProcessTimeLogger.java"</attachmentContentType>
        <attachmentFileName>ProcessTimeLogger.java</attachmentFileName>
      </attachementObject>
      <attachementObject>
        <attachementDataStream>cGFja2FnZSBjb20uZ2ZhY3Rvci5lbWFpbGRpc2NvdmVyeS51dGlsczsNCg0KaW1wb3J0IHN0YXRpYyBjb20uZ2ZhY3Rvci5lbWFpbGRpc2NvdmVyeS51dGlscy5UcmFuc2FjdGlvbkluZGljYXRpbmdVdGlsLmdldFRyYW5zYWN0aW9uU3RhdHVzOw0KDQppbXBvcnQgb3JnLmFwYWNoZS5sb2c0ai5zcGkuRmlsdGVyOw0KaW1wb3J0IG9yZy5hcGFjaGUubG9nNGouc3BpLkxvZ2dpbmdFdmVudDsNCg0KcHVibGljIGNsYXNzIFRyYW5zYWN0aW9uSW5kaWNhdGluZ0ZpbHRlciBleHRlbmRzIEZpbHRlciB7DQogICAgQE92ZXJyaWRlDQogICAgcHVibGljIGludCBkZWNpZGUoTG9nZ2luZ0V2ZW50IGxvZ2dpbmdFdmVudCkgew0KICAgICAgICBsb2dnaW5nRXZlbnQuc2V0UHJvcGVydHkoInhhTmFtZSIsIGdldFRyYW5zYWN0aW9uU3RhdHVzKHRydWUpICk7DQogICAgICAgIGxvZ2dpbmdFdmVudC5zZXRQcm9wZXJ0eSgieGFTdGF0dXMiLCBnZXRUcmFuc2FjdGlvblN0YXR1cyhmYWxzZSkgKTsNCiAgICAgICAgcmV0dXJuIEZpbHRlci5ORVVUUkFMOw0KICAgIH0gIA0KfQ0K</attachementDataStream>
        <attachmentContentType>text/plain;
 name="TransactionIndicatingFilter.java"</attachmentContentType>
        <attachmentFileName>TransactionIndicatingFilter.java</attachmentFileName>
      </attachementObject>
      <attachementObject>
        <attachementDataStream>cGFja2FnZSBjb20uZ2ZhY3Rvci5lbWFpbGRpc2NvdmVyeS51dGlsczsNCg0KcHVibGljIGNsYXNzIFRyYW5zYWN0aW9uSW5kaWNhdGluZ1V0aWwgew0KCXByaXZhdGUgZmluYWwgc3RhdGljIFN0cmluZyBUU01fQ0xBU1NOQU1FID0gIm9yZy5zcHJpbmdmcmFtZXdvcmsudHJhbnNhY3Rpb24uc3VwcG9ydC5UcmFuc2FjdGlvblN5bmNocm9uaXphdGlvbk1hbmFnZXIiOw0KDQoJcHVibGljIHN0YXRpYyBTdHJpbmcgZ2V0VHJhbnNhY3Rpb25TdGF0dXMoYm9vbGVhbiB2ZXJib3NlKSB7DQoJCVN0cmluZyBzdGF0dXMgPSBudWxsOw0KDQoJCXRyeSB7DQoJCQlDbGFzc0xvYWRlciBjb250ZXh0Q2xhc3NMb2FkZXIgPSBUaHJlYWQuY3VycmVudFRocmVhZCgpLmdldENvbnRleHRDbGFzc0xvYWRlcigpOw0KCQkJDQoJCQlpZiAoY29udGV4dENsYXNzTG9hZGVyICE9IG51bGwpIHsNCgkJCQlDbGFzcyB0c21DbGFzcyA9IGNvbnRleHRDbGFzc0xvYWRlci5sb2FkQ2xhc3MoVFNNX0NMQVNTTkFNRSk7DQoJCQkJQm9vbGVhbiBpc0FjdGl2ZSA9IChCb29sZWFuKSB0c21DbGFzcy5nZXRNZXRob2QoImlzQWN0dWFsVHJhbnNhY3Rpb25BY3RpdmUiLCBudWxsKS5pbnZva2UobnVsbCwgbnVsbCk7DQoJCQkJDQoJCQkJaWYgKCF2ZXJib3NlKSB7DQoJCQkJCXN0YXR1cyA9IChpc0FjdGl2ZSkgPyAiWytdICIgOiAiWy1dICI7DQoJCQkJfSBlbHNlIHsNCgkJCQkJU3RyaW5nIHRyYW5zYWN0aW9uTmFtZSA9IChTdHJpbmcpIHRzbUNsYXNzLmdldE1ldGhvZCgiZ2V0Q3VycmVudFRyYW5zYWN0aW9uTmFtZSIsIG51bGwpLmludm9rZShudWxsLG51bGwpOw0KCQkJCQkNCgkJCQkJc3RhdHVzID0gKGlzQWN0aXZlKSA/ICJbIiArIHRyYW5zYWN0aW9uTmFtZSArICJdICIgOiAiW25vIHRyYW5zYWN0aW9uXSAiOw0KCQkJCX0NCgkJCX0gZWxzZSB7DQoJCQkJc3RhdHVzID0gKHZlcmJvc2UpID8gIltjY2wgdW5hdmFpbGFibGVdICIgOiAiW3ggXSI7DQoJCQl9DQoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7DQoJCQlzdGF0dXMgPSAodmVyYm9zZSkgPyAiW3NwcmluZyB1bmF2YWlsYWJsZV0gIiA6ICJbeCBdIjsNCgkJfQ0KCQlyZXR1cm4gc3RhdHVzOw0KCX0NCn0NCg==</attachementDataStream>
        <attachmentContentType>text/plain;
 name="TransactionIndicatingUtil.java"</attachmentContentType>
        <attachmentFileName>TransactionIndicatingUtil.java</attachmentFileName>
      </attachementObject>
    </attachList>
這樣代表我們的mailInfoObject bean裡面包含的不單純是一個屬性,而是一個Collection類別,這邊是ArrayList , 所以首先要在Bean裡面加上一段。

讀取XML to Bean的code

File f = new File("C:/james-server-container-spring-3.0-M2/Mail-XML/4DE4AC51.9060806@mydomain.james.xml");
BeanReader reader = new BeanReader();  reader.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(false);
reader.getBindingConfiguration().setMapIDs(false);      
reader.registerBeanClass(&quot;MailRootBean&quot;, MailRootBean.class);
MailRootBean mailrootBean = (MailRootBean)reader.parse(f);//
System.out.println("mailrootBean = " mailrootBean);
System.out.println("mailrootbean.getVersionCheckObject = " mailrootBean.getVersionCheckObject().getVersion());
MailInfoObject obj = mailrootBean.getMailInfoObject();
System.out.println(obj);

沒問題的話這個在輸出的時候只有versionCheckObject會有值, 而mailInfoObject無法取到相關的值,因為他為null, 這主要是因為還缺少了一個.betwixt 的檔, 檔名跟bean name一樣, 如下
<?xml version='1.0'?>
<info>
 <element name='mailInfoObject'>
  <element name='attachList'>
            <element name='attachementObject' property='attachList' updater='addAttachementObject'/>
        </element>
        <addDefaults/>
 </element>
</info>

這邊的info tag為root, 代表這個bean開始的root block , 然後裡面的element name 為mailInfoObject, 在element name為mailInfoObject的下面有一個element 叫attachList, 而這個attachList裡面的屬性是attachementObject , property 為attachList(getAttachList), update則是要對這個list裡面的物件透過addAttachementObject來增加。

如無意外,bean將可以從xml讀取出來


Reference:
Betwixt Getting Started
Betwixt and List/ArrayList

沒有留言:

張貼留言