JaxB EclipseLink / MOXy: предположительно пустая дата маршалируется как сегодняшняя, а не записывает для нее узел - PullRequest
3 голосов
/ 09 января 2012

Еще раз у меня есть вопрос об Eclipselink / MOXy с файлом отображения внешних метаданных.

У меня есть справочный xml, который применяется к классу.Этот XML-файл содержит данные, относящиеся к некоторым, но не всегда ко всем свойствам, которые может содержать класс.

У меня также есть настраиваемый адаптер даты и времени, установленный для полей даты.

Моя проблема заключается в том, чтоxml, который я unmarshalling, не содержит никаких данных для свойства endDate, но когда я делаю этот простой тест:

  • Unmarshall ссылается xml на класс
  • Маршалл этого класса в новыйXML-файл
  • Сравните два xml-файла

Это свойство endDate (которое не должно быть маршалировано, поскольку оно не было установлено) маршалируется как 01.09.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 генерирует новую датудля пустого поля, как я могу сказать ему через внешний файл сопоставления метаданных не генерировать узлы для пустых или нулевых значений?Я попытался установить required = false в файле метаданных, и я попытался провести тестирование с помощью моего пользовательского DateTimeAdapter, если значения были нулевыми, но, похоже, Jaxb создает новый объект Date и передает его методу маршала Adapter.Я не могу придумать какой-либо способ помешать ему сделать это.

Что касается моих предыдущих вопросов, я не имею никакого контроля над входящими XML или классами модели.

Обратите внимание: эти данныеПример, который я написал, может быть неточным, поскольку я не могу предоставить реальные данные или имена, могут быть некоторые ошибки при наборе.

Спасибо за вашу помощь.

1 Ответ

2 голосов
/ 09 января 2012

Я 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>
...