我想创建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);
有什么办法解决这个问题?
答案 0 :(得分:2)
查看您在评论中提到的错误消息:
类具有两个具有相同名称“ end_date”的属性,此问题与以下位置有关:公共java.time.LocalDateTime
问题可能是这样的:
您没有@XmlAccessorType
注释(以便使用默认访问类型),或者您有,但是访问类型错误。
尝试将此注释放在您的班级上:
@XmlAccessorType(XmlAccessType.FIELD)
说明:
JAXB可以用不同的方式对待您的班级。它既可以查看getter / setter对,也可以直接查看字段。这是访问类型。
默认访问类型为XmlAccessType.PUBLIC_MEMBER
,这有点奇怪:它将查看公共获取器/设置器对以及公共字段。
如果在字段上放置诸如@XmlElement
之类的注释,但对于这些字段也具有getter / setter方法,则JAXB将找到getter / setter,并且还将找到该字段,因为它已被显式注释,并且那么它将认为有两个具有相同名称的属性:一个由getter / setter定义,而另一个由字段定义。
解决方案是通过使用XmlAccessType.FIELD
或通过将@XmlElement
批注放置在getter或setter方法上而不是在字段上来告诉JAXB,它只应查看字段。
有点古怪,但这就是JAXB的工作方式...
请注意,您不仅可以将@XmlAccessorType(XmlAccessType.FIELD)
放在一个类上,还可以将其放在整个包中,只需将其放在package-info.java
文件中-这样就不必将它放在每个您的域模型类之一。