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

Potential data loss in field of type xs:dateTime

Open h908714124 opened this issue 4 years ago • 3 comments

JAXB appears to silently lose data if an XMLGregorianCalendar, which corresponds to the XML Schema type dateTime doesn't specify the "time" fields hours, minutes and seconds.

See this unit test:

https://github.com/h908714124/wsdl2java-gradle6-bug/blob/master/generator/src/test/java/com/foo/bar/zoinks/DataTest.java

In this test, if you marshal data2 again, you see that the form of the xml string even changes on re-marshal:

System.out.println(marshal(data1));
System.out.println(marshal(data2));

which prints the following

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Data xmlns="http://foo.com/bar/zoinks"><created></created></Data>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Data xmlns="http://foo.com/bar/zoinks"/>

One possible solution would be to automatically pad the output of calendar.toString() to the right, using the pattern T00:00:00. Then, the string 2010-11-20 would become 2010-11-20T00:00:00. This might lead to a different calendar being created on unmarshal (one which has the time fields set to zero, as opposed to not having them set at all), so just throwing an exception instead might be preferable.

h908714124 avatar Jul 24 '20 09:07 h908714124

Of course, using java.time types in the generated java classes would also fix this.

h908714124 avatar Jul 24 '20 11:07 h908714124

Maybe it should also be mentioned that the time fields can be omitted for a field of type xs:date, which also corresponds to XMLGregorianCalendar. In that case, specifying them has no effect: The calendar will be "rounded" to the start of the day.

h908714124 avatar Jul 24 '20 11:07 h908714124

@h908714124 I think that the original test is incomplete because of XMLGregorianCalendar expects every field filled:

private String marshal(Data data) throws JAXBException {
  Marshaller marshaller = jaxbContext.createMarshaller();
  StringWriter writer = new StringWriter();
  ValidationEventCollector validationCollector = new ValidationEventCollector() {
    @Override
    public boolean handleEvent(ValidationEvent event) {
      return super.handleEvent(event);
    }
  };
  marshaller.setEventHandler(validationCollector);
  marshaller.marshal(objectFactory.createData(data), writer);
  if(validationCollector.hasEvents()) {
    for(ValidationEvent event:validationCollector.getEvents()) {
      String msg = event.getMessage();
      System.out.println(msg);
    }
  }
  return writer.toString();
}
created 1: 2010-11-20
Invalid set of fields set for XMLGregorianCalendar type dateTime.  Seconds not set.  Minutes not set.  Hour not set.
created 2: null

Otherwise, then it would have to change RuntimeBuiltinLeafInfoImpl class to adapt the correct format:

https://github.com/eclipse-ee4j/jaxb-ri/blob/master/jaxb-ri/runtime/impl/src/main/java/org/glassfish/jaxb/runtime/v2/model/impl/RuntimeEnumLeafInfoImpl.java

Regards, Antonio.

antoniosanct avatar Oct 24 '23 22:10 antoniosanct