Marshalling of negative years in XmlGregorianCalendar is incorrect
previously tracked via: https://bugs.openjdk.java.net/browse/JDK-8172162
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 :
- I have JAXB-annotated class where I have some field of type javax.xml.datatype.XMLGregorianCalendar with annotations @XmlElement(name = "dateTimeField") @XmlSchemaType(name = "dateTime")
- 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)
- I am unmarshal the xml and receive the instance JAXB-annotated class.
- The value of year is correct in instance.
- I am marshal the object and see that negative year is printed as "00-1"
Comments:
- If I remove annotation @XmlSchemaType(name = "dateTime") the everything work as expected.
- 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);
}