我们正在升级到JAXB-RI实现的新版本。但是,从com.sun.xml.bind:jaxb-impl:2.2.7
开始,我们的解组代码失败。如果我们切换回2.2.6版,它将正确解组。
我尝试了对象类上注释的各种组合。问题似乎出在XmlBars.getBars
方法周围,该方法不再返回子Bar元素。
我已经使用org.glassfish.jaxb:jaxb-runtime
和最新的Moxy进行了尝试,它们表现出相同的行为。
此JUnit5测试中显示了失败的示例:
package com.company;
import org.junit.jupiter.api.Test;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
class XmlBarsTest {
private static final String XML = "<Bars><Bar><Name>name1</Name></Bar><Bar><Name>name2</Name></Bar></Bars>";
@Test
public void deserializeXmlBars() throws JAXBException {
StringReader reader = new StringReader(XML);
JAXBContext context = JAXBContext.newInstance(XmlBars.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
XmlBars deserializeBars = (XmlBars) unmarshaller.unmarshal(reader);
List<XmlBar> bars = deserializeBars.getBars();
assertEquals(2, bars.size(), "Missing bars");
}
}
支持类是XmlBars:
package com.company;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import java.util.ArrayList;
import java.util.List;
import static java.util.stream.Collectors.toList;
@XmlRootElement(name = "Bars")
public class XmlBars {
@XmlTransient
private List<Bar> bars;
public XmlBars() {
bars = new ArrayList<>();
}
public XmlBars(List<Bar> bars) {
this.bars = bars;
}
@XmlElement(name = "Bar")
public List<XmlBar> getBars() {
return bars == null ?
null :
bars.stream()
.map(XmlBar::new)
.collect(toList());
}
public void setBars(List<XmlBar> list) {
this.bars = list.stream()
.map(XmlBar::getBar)
.collect(toList());
}
}
XmlBar:
package com.company;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
public class XmlBar {
@XmlTransient
private Bar bar;
public XmlBar() {
bar = new Bar();
}
public XmlBar(Bar bar) {
this.bar = bar;
}
Bar getBar() {
return bar;
}
@XmlElement(name = "Name")
public String getName() {
return bar.getName();
}
public void setName(String name) {
bar.setName(name);
}
}
和酒吧:
package com.company;
public class Bar {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
以及支持的pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<!-- Works with 2.2.6. Fails with 2.2.7 -->
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
</plugins>
</build>
</project>
如果我将XmlBars
修改为以下内容,它将起作用:
package com.company;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import java.util.ArrayList;
import java.util.List;
import static java.util.stream.Collectors.toList;
@XmlRootElement(name = "Bars")
public class XmlBars {
@XmlTransient
private List<Bar> bars;
/* Adding this enables the annotations to work as before */
private List<XmlBar> xmlBars;
public XmlBars() {
bars = new ArrayList<>();
xmlBars = new ArrayList<>();
}
public XmlBars(List<Bar> bars) {
this.bars = bars;
this.xmlBars = bars.stream()
.map(XmlBar::new)
.collect(toList());
}
@XmlElement(name = "Bar")
public List<XmlBar> getBars() {
return xmlBars;
}
public void setBars(List<XmlBar> list) {
this.bars = list.stream()
.map(XmlBar::getBar)
.collect(toList());
this.xmlBars = list;
}
}
所以,问题是,如何注释原始版本以防止需要维护本地属性?
答案 0 :(得分:0)
我们找不到解决方案。因此,我们重新设计了类,使其具有带有常规getter和setter的属性。