FULL PRODUCT VERSION :
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 10.0.14393]
A DESCRIPTION OF THE PROBLEM :
1. I have JAXB-annotated class where I have some field of type javax.xml.datatype.XMLGregorianCalendar with annotations @XmlElement(name = "dateTimeField") @XmlSchemaType(name = "dateTime")
2. I have valid xml representation of instance of class from item (1) where the value of XMLGregorianCalendar field contains negative year value (-0001 for example)
3. I am unmarshal the xml and receive the instance JAXB-annotated class.
4. The value of year is correct in instance.
5. I am marshal the object and see that negative year is printed as "00-1"
Comments:
1. If I remove annotation @XmlSchemaType(name = "dateTime") the everything work as expected.
2. Full runnable example is attached.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the source code below
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
-0001-12-31T23:59:59.999Z
ACTUAL -
00-1-12-31T23:59:59.999Z
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package com.afilin.java8;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.datatype.XMLGregorianCalendar;
import java.io.StringReader;
import java.io.StringWriter;
public class NegativeYearsBug {
@XmlRootElement(name="root")
private static class JaxbExample {
@XmlElement(name = "dateTimeField")
@XmlSchemaType(name = "dateTime")
private XMLGregorianCalendar dateTimeField;
public XMLGregorianCalendar getDateTimeField() {
return dateTimeField;
}
}
public static void main(String[] args) throws Exception {
String xml = "<root><dateTimeField>-0001-12-31T23:59:59.999Z</dateTimeField></root>";
JAXBContext jaxbContext = JAXBContext.newInstance(JaxbExample.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
JaxbExample unmarshalledObject = (JaxbExample) unmarshaller.unmarshal(new StringReader(xml));
Marshaller marshaller = jaxbContext.createMarshaller();
StringWriter stringWriter = new StringWriter();
marshaller.marshal(unmarshalledObject, stringWriter);
assert xml.equals(stringWriter.toString()) : "Actual value: " + stringWriter.toString();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
change implementation of
com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl#printNumber(StringBuilder out, BigInteger number, int nDigits) {
BigInteger absoluteValue = number.abs();
String s = absoluteValue.toString();
if(number.signum() < 0) {
out.append("-");
}
for(int i = s.length(); i < nDigits; ++i) {
out.append('0');
}
out.append(s);
}
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 10.0.14393]
A DESCRIPTION OF THE PROBLEM :
1. I have JAXB-annotated class where I have some field of type javax.xml.datatype.XMLGregorianCalendar with annotations @XmlElement(name = "dateTimeField") @XmlSchemaType(name = "dateTime")
2. I have valid xml representation of instance of class from item (1) where the value of XMLGregorianCalendar field contains negative year value (-0001 for example)
3. I am unmarshal the xml and receive the instance JAXB-annotated class.
4. The value of year is correct in instance.
5. I am marshal the object and see that negative year is printed as "00-1"
Comments:
1. If I remove annotation @XmlSchemaType(name = "dateTime") the everything work as expected.
2. Full runnable example is attached.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the source code below
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
-0001-12-31T23:59:59.999Z
ACTUAL -
00-1-12-31T23:59:59.999Z
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package com.afilin.java8;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.datatype.XMLGregorianCalendar;
import java.io.StringReader;
import java.io.StringWriter;
public class NegativeYearsBug {
@XmlRootElement(name="root")
private static class JaxbExample {
@XmlElement(name = "dateTimeField")
@XmlSchemaType(name = "dateTime")
private XMLGregorianCalendar dateTimeField;
public XMLGregorianCalendar getDateTimeField() {
return dateTimeField;
}
}
public static void main(String[] args) throws Exception {
String xml = "<root><dateTimeField>-0001-12-31T23:59:59.999Z</dateTimeField></root>";
JAXBContext jaxbContext = JAXBContext.newInstance(JaxbExample.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
JaxbExample unmarshalledObject = (JaxbExample) unmarshaller.unmarshal(new StringReader(xml));
Marshaller marshaller = jaxbContext.createMarshaller();
StringWriter stringWriter = new StringWriter();
marshaller.marshal(unmarshalledObject, stringWriter);
assert xml.equals(stringWriter.toString()) : "Actual value: " + stringWriter.toString();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
change implementation of
com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl#printNumber(StringBuilder out, BigInteger number, int nDigits) {
BigInteger absoluteValue = number.abs();
String s = absoluteValue.toString();
if(number.signum() < 0) {
out.append("-");
}
for(int i = s.length(); i < nDigits; ++i) {
out.append('0');
}
out.append(s);
}