3

もう一度、外部メタデータ マッピング ファイルを使用した Eclipselink/MOXy について質問があります。

クラスに適用される参照xmlがあります。この xml には、クラスに含めることができるすべてのプロパティではなく、一部のプロパティに適用されるデータが含まれています。

また、日付フィールド用にカスタムの日時アダプターを設定しています。

私の問題は、アンマーシャリングしている xml に endDate プロパティのデータが含まれていないことですが、この簡単なテストを実行すると、次のようになります。

  • クラスへの参照 xml を非整列化する
  • そのクラスを新しい xml ファイルにマーシャリングします
  • 2 つの xml ファイルを比較する

そのプロパティ endDate (設定されていないためマーシャリングされるべきではありません) は、09/01/2012 17:05:28 としてマーシャリングされます (現在の時刻に設定された新しい Date() として常にマーシャリングされます)。

サンプルの XML メタデータ ファイルを次に示します。

<?xml version="1.0"?>
<xml-bindings  xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
                version="2.1">
    <java-types>
        <java-type name="sample.clazz.Task" xml-accessor-type="NONE">
            <xml-root-element name="Task" />
            <xml-type prop-order="startDate endDate id ci ch cr" />
            <java-attributes>
                <xml-element java-attribute="startDate" xml-path="StartDate/text()">
                    <xml-java-type-adapter value="utils.JaxBDateTimeAdapter" type="java.util.Date"/>
                </xml-element>
                <xml-element java-attribute="endDate" required="false" xml-path="EndDate/text()">
                    <xml-java-type-adapter value="utils.JaxBDateTimeAdapter" type="java.util.Date"/>
                </xml-element>
                <xml-element java-attribute="id" xml-path="TaskId/text()" />
                <xml-element java-attribute="ci" xml-path="CIPR/text()" />
                <xml-element java-attribute="ch" xml-path="CHPR/text()" />
                <xml-element java-attribute="cr" xml-path="CRPR/text()" />
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

クラスは次のとおりです。

package sample.clazz;

public class Task{

    private int id;
    private Date startDate;
    private Date endDate;
    private String ci;
    private String ch;
    private String cr;

    public Task(){

    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public Date getStartDate() {
        return startDate;
    }
    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }
    public Date getEndDate() {
        return endDate;
    }
    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }
    public String getCi() {
        return ci;
    }
    public void setCi(String ci) {
        this.ci = ci;
    }
    public String getCh() {
        return ch;
    }
    public void setCh(String ch) {
        this.ch = ch;
    }
    public String getCr() {
        return cr;
    }
    public void setCr(String cr) {
        this.cr = cr;
    }

}

ここに私のカスタム DateTimeAdapter があります:

package utils;

import java.util.Date;

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

public class JaxBDateTimeAdapter extends XmlAdapter<String, Date>  {


    @Override
    public String marshal(Date d) throws Exception {
        if(d != null){
            return DateUtil.getFormatedDateTimeString(d);
        }
        else{
            return null;
        }
    }

    @Override
    public Date unmarshal(String d) throws Exception {
        if(d != null && !"".equals(d)){
            return DateUtil.getDateFromString(d);
        }
        else{
            return null;
        }
    }
}

ここに私の参照XMLがあります

<?xml version="1.0" encoding="UTF-8"?>
<Task>
    <TaskId>147</TaskId>
    <CRPR>0087</CRPR>
    <CIPR>A683557</CIPR>
    <CHPR>BV</CHPR>
    <StartDate>22/01/2009 20:56:29</StartDate>
</Task>

オブジェクトを再マーシャリングするときに取得する XML は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<Task>
    <TaskId>147</TaskId>
    <CRPR>0087</CRPR>
    <CIPR>A683557</CIPR>
    <CHPR>BV</CHPR>
    <StartDate>01/01/2012 20:56:29</StartDate>
    <EndDate>09/01/2012 17:05:28</EndDate> <!-- That element should not exist ! -->
</Task>

Jaxb は空のフィールドに対して新しい日付を生成するようですが、空の値または null 値のノードを生成しないように、外部メタデータ マッピング ファイルを介して彼に伝えるにはどうすればよいですか? メタデータ ファイルで required=false を設定しようとし、値が null であるかどうかをカスタム DateTimeAdapter でテストしようとしましたが、Jaxb が新しい Date オブジェクトを作成し、それを Adapter のマーシャル メソッドに渡すようです。彼がこれをするのを防ぐ方法は考えられません。

以前の質問と同様に、受信する XML やモデル クラスを制御することはできません。

注:このデータは私が書いたサンプルです。実際のデータや名前を公開できないため、正確ではない可能性があります。入力エラーがある可能性があります。

ご協力いただきありがとうございます。

4

1 に答える 1

2

私はEclipseLink JAXB (MOXy)のリーダーですが、問題を再現できませんでした。DateUtilあなたのクラスに問題がある可能性があります。以下は私が試したことです:

oxm.xml

メタデータ ファイルに小さな変更を加えました。基本的に、個々の要素xml-bindingsではなく、要素のパッケージ名を指定するように変更しました。java-type

<?xml version="1.0"?>
<xml-bindings  
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    version="2.3"
    package-name="sample.clazz">
    <java-types>
        <java-type name="Task" xml-accessor-type="NONE">
            <xml-root-element name="Task" />
            <xml-type prop-order="startDate endDate id ci ch cr" />
            <java-attributes>
                <xml-element java-attribute="startDate" xml-path="StartDate/text()">
                    <xml-java-type-adapter value="forum8791782.JaxBDateTimeAdapter" type="java.util.Date"/>
                </xml-element>
                <xml-element java-attribute="endDate" required="false" xml-path="EndDate/text()">
                    <xml-java-type-adapter value="forum8791782.JaxBDateTimeAdapter" type="java.util.Date"/>
                </xml-element>
                <xml-element java-attribute="id" xml-path="TaskId/text()" />
                <xml-element java-attribute="ci" xml-path="CIPR/text()" />
                <xml-element java-attribute="ch" xml-path="CHPR/text()" />
                <xml-element java-attribute="cr" xml-path="CRPR/text()" />
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

DateUtil

DateUtil質問での実装を提供しなかったため、次を使用しました。私の推測では、あなたの実装にはDateUtil、あなたが見ている出力を引き起こしているコードがあると思います:

package forum8791782;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {

    private static SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");

    public static String getFormatedDateTimeString(Date d) {
        return formatter.format(d);
    }

    public static Date getDateFromString(String d) {
        try {
            return formatter.parse(d);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

}

デモ

以下は、この例を実行するために使用したコードです。 input.xmlは、質問で引用した参照 XML です。

package forum8791782;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;

import org.eclipse.persistence.Version;
import org.eclipse.persistence.jaxb.JAXBContextFactory;

import sample.clazz.Task;

public class Demo {

    public static void main(String[] args) throws Exception {
        System.out.println(Version.getVersionString());

        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum8791782/oxm.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Task.class}, properties);

        File xml = new File("src/forum8791782/input.xml");
        Unmarshaller u = jc.createUnmarshaller();
        Task task = (Task) u.unmarshal(xml);

        Marshaller m = jc.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        m.marshal(task, System.out);
    }

}

出力

以下は、サンプル コードを実行した結果の出力です。EndDate書き出された要素が表示されません。

2.3.2.v20111125-r10461
<?xml version="1.0" encoding="UTF-8"?>
<Task>
   <StartDate>22/01/2009 20:56:29</StartDate>
   <TaskId>147</TaskId>
   <CIPR>A683557</CIPR>
   <CHPR>BV</CHPR>
   <CRPR>0087</CRPR>
</Task>
于 2012-01-09T17:27:51.140 に答える