从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

查看:152
本文介绍了从JDK 1.8.0.77升级到1.8.0.162后,Jaxb2Marshaller失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个让我难过。我有一个Java String Batch应用程序,在针对Java 1.8.0.77运行时运行时没有任何错误。它读入XML文件并将其完美地写入数据库。

This one has me stumped. I have a Java String Batch app that runs without any error when run against Java 1.8.0.77. It reads in an XML file and writes it to a DB flawlessly.

更新到JDK 1.8.0.162之后,读取器根本不起作用,即使将日志记录设置为DEBUG也不会发送任何错误消息。更改回Java 1.8.0.77可以解决此问题。我们的服务器运行162,所以我必须在162工作。

After updating to JDK 1.8.0.162 the reader simply does not work and does not send any error messages even with logging set to DEBUG. Changing back to Java 1.8.0.77 resolves the issue. Our servers are running 162 though so I have to make this work in 162.

这是读者:

      @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运行它时,我得到完整的产品记录所有子类都用文件中的数据填充。当我针对Java 1.0.8.162运行它时,我只返回产品标记上的3个属性,而不是内部的任何字段。

When I run it against Java 1.0.8.77 I get the full product record and all subclasses back filled in with data from the file. When I run it against Java 1.0.8.162 I only get back the 3 attributes on the product tag and none of the fields inside.

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>

产品类别是这样的

@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中运行时,这些相同的记录失败

Again, it works without any issue at all in 1.8.0.77. I have run millions of records through it in testing. Those same records fail when run in 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.0_152。我在下面的答案中更多地作为实验结果而不是文献参考,因为我一直在努力寻找相关文档来支持我的发现。如果其他人可以找到相关文档,我有兴趣看到它。

I hit a similar issue to this earlier this year. I was upgrading a project from Java 1.8.0_92 to 1.8.0_152, and some JAXB unmarshalling that had worked with 1.8.0_92 stopped working with 1.8.0_152. I present in my answer below more as results of experimentation rather than as reference to documentation, as I have struggled to find relevant documentation to back up my findings. If anyone else can find relevant documentation, I'd be interested to see it.

我的理解是,如果Java类中的字段或属性没有 @XmlElement 注释,JAXB将字段或属性视为具有注释 @XmlElement(name =fieldName)或者 @XmlElement(name =propertyName)视情况而定。因此,例如, Product 类中未注释的字段将被视为如下:

My understanding is that if a field or property in a Java class does not have an @XmlElement annotation, JAXB treats the field or property as if it had the annotation @XmlElement(name = "fieldName") or @XmlElement(name = "propertyName") as appropriate. So, for example, the un-annotated fields in your Product class would be treated as follows:

@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允许元素单独匹配本地名称,而不管命名空间如何,但是从更新111开始,元素命名空间也必须匹配。如果您没有指定命名空间(特别是,如果您根本没有指定 @XmlElement 注释),则假定使用默认命名空间。

Furthermore, between Java 8 updates 101 and 111, the way namespaces were handled in JAXB changed. Java 8 update 101 allowed elements to match on local names alone, regardless of namespace, but as of update 111 element namespaces also have to match. If you don't specify a namespace (in particular, if you don't specify an @XmlElement annotation at all), the default namespace is assumed.

Product 元素的子元素不在默认命名空间中,因此它们不再与 @XmlElement匹配上面的注释。但是,例如,尝试将 xmlns =添加到 Rating 元素中。您应该会发现该产品的评级已被读入。

The child elements of your Product elements are not in the default namespace so they no longer match the @XmlElement annotations above. However, try adding xmlns="" to a Rating element, for example. You should find that the rating for that product gets read in.

因此,您的问题的一个可能解决方案是添加 @XmlElement 带有名称空间的注释,适用于所有子元素。这就是我需要做的就是解决我遇到的问题:我已经有了必要的 @XmlElement 注释,我只需要在一个这样的注释中添加命名空间。但是,我怀疑你有更多的子元素,并且你指定的示例文档已从更大的真实文档中删除。考虑到这一点,使用相关注释创建 package-info.java 文件可能会更快,并将其放在包含POJO的包中(希望他们'全部在同一个包中):

One possible solution to your problem is therefore to add @XmlElement annotations, complete with namespaces, to all child elements. This is what I needed to do to fix the problem I had: I already had the necessary @XmlElement annotations, I just needed to add a namespace to one such annotation. However, I suspect you have a lot more child elements, and that the sample document you have specified has been cut down from a much larger real document. With that in mind, it would probably be quicker to create a package-info.java file with the relevant annotation and put this in the package that contains your POJOs (hopefully they're all in the same package):

@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项目中,我发现解组出现了上班。使用XML文档中的值填充 Product 类中的子属性。我采用了 package-info.java 文件的想法。 htmlrel =nofollow noreferrer>此页

I added this to a small Java project I created to test your code and I found that the unmarshalling appeared to work. Child properties in the Product class were being populated with values from the XML document. I took the idea of using a package-info.java file from this page.

这篇关于从JDK 1.8.0.77升级到1.8.0.162后,Jaxb2Marshaller失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆