从 JDK 1.8.0.77 升级到 1.8.0.162 后 Jaxb2Marshaller 失败
Jaxb2Marshaller fails after upgrading from JDK 1.8.0.77 to 1.8.0.162
这个让我难住了。我有一个 Java 字符串批处理应用程序 运行 在 运行 对 Java 1.8.0.77 时没有任何错误。它读取 XML 文件并将其完美地写入数据库。
更新到 JDK 1.8.0.162 后,reader 根本不起作用,即使将日志记录设置为 DEBUG 也不会发送任何错误消息。改回 Java 1.8.0.77 可解决问题。我们的服务器是 运行ning 162,所以我必须在 162 中完成这项工作。
这里是 reader:
@Bean
ItemReader<Product> reviewItemReader() {
StaxEventItemReader<Product> xmlFileReader = new StaxEventItemReader<>();
xmlFileReader.setResource(new FileSystemResource(this.fileName));
xmlFileReader.setFragmentRootElementName("Product");
Jaxb2Marshaller feedMarshaller = new Jaxb2Marshaller();
feedMarshaller.setClassesToBeBound(Product.class);
xmlFileReader.setUnmarshaller(feedMarshaller);
return xmlFileReader;
}
当我 运行 它针对 Java 1.0.8.77 时,我得到了完整的产品记录和所有子classes 返回填充文件中的数据。当我 运行 它针对 Java 1.0.8.162 时,我只取回产品标签上的 3 个属性和内部字段的 none。
XML 看起来像:
...
<Product id="asdsada" removed="false" disabled="true">
<Descriptoin> Blah blah blah</Descriptoin>
<UPCs>
<UPC> 123423432</UPC>
</UPCs>
<Rating>5</Rating>
<Name>name here</Name>
<Categories>
<Category> Cat 1 </Category>
<Category> Cat 2 </Category>
<Category> Cat 3 </Category>
</Categories>
...
</Product>
<Product id="zxcvzxcvxcv" removed="true" disabled="false">
<Descriptoin> Blah blah blah</Descriptoin>
<UPCs>
<UPC> 123222423432</UPC>
</UPCs>
<Rating>5</Rating>
<Name>name here</Name>
<Categories>
<Category> Cat 1 </Category>
<Category> Cat 2 </Category>
<Category> Cat 3 </Category>
</Categories>
....
</Product>
产品class是这样的
@XmlRootElement(name = "Product", namespace = "FOO POWER")
public class Product {
@XmlAttribute(name = "removed")
public String removed;
@XmlAttribute(name = "disabled")
public String disabled;
@XmlAttribute(name = "id")
public String id;
public String Name;
public String Rating;
public UPCs UPCs;
public Brand Brand;
...
同样,它在 1.8.0.77 中完全没有问题。我在测试中有 运行 数百万条记录。当 1.8.0.162
中的 运行 时,这些相同的记录会失败
Someone asked to see what a child class looks like. They are pretty much like this:
public class Brand {
public String Name;
public Attributes Attributes;
public String ExternalId;
public String disabled;
...
今年早些时候我遇到了类似的问题。我正在将一个项目从 Java 1.8.0_92 升级到 1.8.0_152,一些在 1.8.0_92 上工作的 JAXB 解组停止在 1.8.[=40 上工作=].我在下面的回答中更多地是作为实验结果而不是参考文档,因为我一直在努力寻找相关文档来支持我的发现。如果其他人能找到相关文档,我很想看看。
我的理解是,如果Javaclass中的字段或属性没有@XmlElement
注解,JAXB会将该字段或属性 就好像它有适当的注释 @XmlElement(name = "fieldName")
或 @XmlElement(name = "propertyName")
一样。因此,例如,Product
class 中未注释的字段将按如下方式处理:
@XmlElement(name = "Name")
public String Name;
@XmlElement(name = "Rating")
public String Rating;
@XmlElement(name = "UPCs")
public UPCs UPCs;
@XmlElement(name = "Brand")
public Brand Brand;
此外,在 Java 8 次更新 101 和 111 之间,JAXB 中处理名称空间的方式发生了变化。 Java 8 update 101 允许元素单独匹配本地名称,而不管名称空间如何,但从 update 111 开始,元素名称空间也必须匹配。如果您不指定命名空间(特别是,如果您根本不指定 @XmlElement
注释),则假定为默认命名空间。
您的 Product
元素的子元素不在默认命名空间中,因此它们不再匹配上面的 @XmlElement
注释。但是,例如,尝试将 xmlns=""
添加到 Rating
元素。您应该会发现该产品的评级已被读入。
因此,您的问题的一个可能解决方案是向所有子元素添加 @XmlElement
注释,并附上命名空间。这就是我需要做的来解决我遇到的问题:我已经有了必要的 @XmlElement
注释,我只需要向一个这样的注释添加一个名称空间。但是,我怀疑您有更多的子元素,并且您指定的示例文档是从一个更大的真实文档中截取的。考虑到这一点,创建一个带有相关注释的 package-info.java
文件并将其放入包含您的 POJO 的包中(希望它们都在同一个包中)可能会更快:
@XmlSchema(
namespace = "FOO POWER",
elementFormDefault = XmlNsForm.QUALIFIED)
package your.package.name.here;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
我将其添加到我创建的一个小 Java 项目中以测试您的代码,我发现解组似乎有效。 Product
class 中的子属性正在使用 XML 文档中的值填充。我想到了使用 this page.
中的 package-info.java
文件
这个让我难住了。我有一个 Java 字符串批处理应用程序 运行 在 运行 对 Java 1.8.0.77 时没有任何错误。它读取 XML 文件并将其完美地写入数据库。
更新到 JDK 1.8.0.162 后,reader 根本不起作用,即使将日志记录设置为 DEBUG 也不会发送任何错误消息。改回 Java 1.8.0.77 可解决问题。我们的服务器是 运行ning 162,所以我必须在 162 中完成这项工作。
这里是 reader:
@Bean
ItemReader<Product> reviewItemReader() {
StaxEventItemReader<Product> xmlFileReader = new StaxEventItemReader<>();
xmlFileReader.setResource(new FileSystemResource(this.fileName));
xmlFileReader.setFragmentRootElementName("Product");
Jaxb2Marshaller feedMarshaller = new Jaxb2Marshaller();
feedMarshaller.setClassesToBeBound(Product.class);
xmlFileReader.setUnmarshaller(feedMarshaller);
return xmlFileReader;
}
当我 运行 它针对 Java 1.0.8.77 时,我得到了完整的产品记录和所有子classes 返回填充文件中的数据。当我 运行 它针对 Java 1.0.8.162 时,我只取回产品标签上的 3 个属性和内部字段的 none。
XML 看起来像:
...
<Product id="asdsada" removed="false" disabled="true">
<Descriptoin> Blah blah blah</Descriptoin>
<UPCs>
<UPC> 123423432</UPC>
</UPCs>
<Rating>5</Rating>
<Name>name here</Name>
<Categories>
<Category> Cat 1 </Category>
<Category> Cat 2 </Category>
<Category> Cat 3 </Category>
</Categories>
...
</Product>
<Product id="zxcvzxcvxcv" removed="true" disabled="false">
<Descriptoin> Blah blah blah</Descriptoin>
<UPCs>
<UPC> 123222423432</UPC>
</UPCs>
<Rating>5</Rating>
<Name>name here</Name>
<Categories>
<Category> Cat 1 </Category>
<Category> Cat 2 </Category>
<Category> Cat 3 </Category>
</Categories>
....
</Product>
产品class是这样的
@XmlRootElement(name = "Product", namespace = "FOO POWER")
public class Product {
@XmlAttribute(name = "removed")
public String removed;
@XmlAttribute(name = "disabled")
public String disabled;
@XmlAttribute(name = "id")
public String id;
public String Name;
public String Rating;
public UPCs UPCs;
public Brand Brand;
...
同样,它在 1.8.0.77 中完全没有问题。我在测试中有 运行 数百万条记录。当 1.8.0.162
中的 运行 时,这些相同的记录会失败Someone asked to see what a child class looks like. They are pretty much like this:
public class Brand {
public String Name;
public Attributes Attributes;
public String ExternalId;
public String disabled;
...
今年早些时候我遇到了类似的问题。我正在将一个项目从 Java 1.8.0_92 升级到 1.8.0_152,一些在 1.8.0_92 上工作的 JAXB 解组停止在 1.8.[=40 上工作=].我在下面的回答中更多地是作为实验结果而不是参考文档,因为我一直在努力寻找相关文档来支持我的发现。如果其他人能找到相关文档,我很想看看。
我的理解是,如果Javaclass中的字段或属性没有@XmlElement
注解,JAXB会将该字段或属性 就好像它有适当的注释 @XmlElement(name = "fieldName")
或 @XmlElement(name = "propertyName")
一样。因此,例如,Product
class 中未注释的字段将按如下方式处理:
@XmlElement(name = "Name")
public String Name;
@XmlElement(name = "Rating")
public String Rating;
@XmlElement(name = "UPCs")
public UPCs UPCs;
@XmlElement(name = "Brand")
public Brand Brand;
此外,在 Java 8 次更新 101 和 111 之间,JAXB 中处理名称空间的方式发生了变化。 Java 8 update 101 允许元素单独匹配本地名称,而不管名称空间如何,但从 update 111 开始,元素名称空间也必须匹配。如果您不指定命名空间(特别是,如果您根本不指定 @XmlElement
注释),则假定为默认命名空间。
您的 Product
元素的子元素不在默认命名空间中,因此它们不再匹配上面的 @XmlElement
注释。但是,例如,尝试将 xmlns=""
添加到 Rating
元素。您应该会发现该产品的评级已被读入。
因此,您的问题的一个可能解决方案是向所有子元素添加 @XmlElement
注释,并附上命名空间。这就是我需要做的来解决我遇到的问题:我已经有了必要的 @XmlElement
注释,我只需要向一个这样的注释添加一个名称空间。但是,我怀疑您有更多的子元素,并且您指定的示例文档是从一个更大的真实文档中截取的。考虑到这一点,创建一个带有相关注释的 package-info.java
文件并将其放入包含您的 POJO 的包中(希望它们都在同一个包中)可能会更快:
@XmlSchema(
namespace = "FOO POWER",
elementFormDefault = XmlNsForm.QUALIFIED)
package your.package.name.here;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
我将其添加到我创建的一个小 Java 项目中以测试您的代码,我发现解组似乎有效。 Product
class 中的子属性正在使用 XML 文档中的值填充。我想到了使用 this page.
package-info.java
文件