Я хочу создать тест JUnit для тестирования кода JAXB:

@XmlRootElement(name = "reconcile")
public class Reconcile {

    @XmlElement(name = "start_date")
    @XmlJavaTypeAdapter(LocalDateTimeXmlAdapter.class)
    public LocalDateTime start_date;
    @XmlElement(name = "end_date")
    @XmlJavaTypeAdapter(LocalDateTimeXmlAdapter.class)
    public LocalDateTime end_date;
    @XmlElement(name = "page")
    public String page;

    //// getters and setters
}

Я попробовал этот тест JUnit для приведенного выше кода:

import java.time.LocalDateTime;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.datalis.plugin.reconcile.Reconcile;
import org.junit.jupiter.api.Test;

public class ReconciliationTest {

    @Test
    public void uniqueTransactionIdLenght() throws JAXBException {

        Reconcile reconcile = new Reconcile();
        reconcile.start_date = LocalDateTime.of(2018, 4, 8, 11, 2, 44);
        reconcile.end_date = LocalDateTime.of(2018, 11, 8, 11, 2, 44);
        reconcile.page = "1";

        JAXBContext jaxbContext = JAXBContext.newInstance(Reconcile.class);
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(reconcile, System.out);
    }
}

Но когда я запускаю код, я получаю:

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions
    at org.datalis.plugin.jaxb.ReconciliationTest.uniqueTransactionIdLenght(ReconciliationTest.java:22)

На этой линии

JAXBContext jaxbContext = JAXBContext.newInstance(Reconcile.class);

Есть ли способ решить проблему?

1
Peter Penzov 5 Окт 2018 в 09:26

1 ответ

Лучший ответ

Глядя на сообщение об ошибке, которое вы упоминаете в комментариях:

Класс имеет два свойства с одинаковым именем "end_date", эта проблема связана со следующим местоположением: в общедоступном java.time.LocalDateTime

Проблема, наверное, в следующем:

У вас либо нет аннотации @XmlAccessorType (поэтому используется тип доступа по умолчанию), либо она есть, но с неправильным типом доступа.

Попробуйте поместить эту аннотацию в свой класс:

@XmlAccessorType(XmlAccessType.FIELD)

Пояснение:

JAXB может обрабатывать ваши классы по-разному. Он может либо смотреть на пары геттер / сеттер, либо напрямую смотреть на поля. Это тип доступа.

Тип доступа по умолчанию - XmlAccessType.PUBLIC_MEMBER, что немного странно: он будет смотреть как на общедоступные пары получателей / установщиков, так и на общедоступные поля.

Если вы помещаете аннотации, такие как @XmlElement в поля, но у вас также есть методы получения / установки для этих полей, тогда JAXB найдет средство получения / установки, а также найдет поле, потому что оно явно аннотировано, а затем подумайте, что есть два свойства с одинаковыми именами: одно определяется получателем / установщиком, а другое определяется полем.

Решение состоит в том, чтобы сообщить JAXB, что он должен смотреть только на поля, используя XmlAccessType.FIELD или помещая аннотации @XmlElement в метод получения или установки вместо поля.

Это немного странно, но так работает JAXB ...

Обратите внимание, что вы можете поместить @XmlAccessorType(XmlAccessType.FIELD) не только в класс, но и во весь пакет, поместив его в файл package-info.java - таким образом вам не придется помещать его в каждый из ваших классы модели предметной области.

2
Jesper 5 Окт 2018 в 07:26