jaxb-v2 icon indicating copy to clipboard operation
jaxb-v2 copied to clipboard

Marshalling of negative years in XmlGregorianCalendar is incorrect

Open LanceAndersen opened this issue 7 years ago • 0 comments

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 :

  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); 

}

LanceAndersen avatar Apr 27 '18 21:04 LanceAndersen