问题
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.
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.
Here is the 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;
}
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.
The XML looks something like:
...
<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>
The product class is something like this
@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;
...
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;
...
回答1:
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.
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;
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.
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.
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;
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.
来源:https://stackoverflow.com/questions/49885939/jaxb2marshaller-fails-after-upgrading-from-jdk-1-8-0-77-to-1-8-0-162