Reputation: 6794
My web application is using Apache CXF and JAVA8, and facing below error in response if user send xs:datetime
input(seconds 00) as
<urn1:dateTimeVal>2016-04-29T20:00:00</urn1:dateTimeVal>
ERROR :
org.apache.cxf.interceptor.Fault: Marshalling Error: cvc-datatype-valid.1.2.1: '2016-04-29T20:00' is not a valid value for 'dateTime'.
I debug and analysed that if user send dateTimeVal
as 2016-04-29T20:00:00
then CXF validations for input are passed and XML value is UnMarshaled to java.time.LocalDateTime
as 2016-05-05T20:00
, and at the time of returning the response, the Marshaling error occurs due to loss of seconds part(00).
Any help/hint are appreciated.
P.S : You can try with below snippet :
java.time.LocalDateTime dt= java.time.LocalDateTime.of(2016, Month.MAY, 5, 20, 00, 00);
System.out.println(dt);
Note : Above code sample is just for understanding to print datetime value. But actual return type expected in web application is java.time.LocalDateTime
OUTPUT EXPECTED : 2016-05-05T20:00:00
OUTPUT ACTUAL : 2016-05-05T20:00
EDIT : The binding (JAXB) content for the field is :
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
@XmlSchemaType(name = "dateTime")
@Generated(value = "com.sun.tools.xjc.Driver", date = "2016-05-03T05:28:57+05:30", comments = "JAXB RI v2.2.11")
@NotNull
protected LocalDateTime dateTimeVal;
AND LocalDateTimeAdapter
File is
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAccessor;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class LocalDateTimeAdapter
extends XmlAdapter<String, LocalDateTime>
{
public static LocalDateTime parse(String value)
{
DateTimeFormatter dateTimeAndZoneformatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
DateTimeFormatter dateTimeformatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
TemporalAccessor ta = null;
try
{
ta = dateTimeformatter.parse(value);
}
catch (DateTimeParseException ex)
{
ta = dateTimeAndZoneformatter.parse(value);
}
return LocalDateTime.from(ta);
}
public static String print(LocalDateTime value)
{
return value.toString();
}
public LocalDateTime unmarshal(String value)
{
return parse(value);
}
public String marshal(LocalDateTime value)
{
return print(value);
}
}
Upvotes: 11
Views: 7511
Reputation: 6471
The problem appears to be in LocalDateTimeAdapter.print()
. LocalDateTime.toString()
omits the seconds when the seconds value is 0.
If you change it to
public static String print(LocalDateTime value)
{
return value.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
it will provide the seconds as well when marshaling.
To see a quick example, note the results of the following snippet:
System.out.println(LocalDateTime.of(2016,1,1,0,0,0,0).toString());
System.out.println(LocalDateTime.of(2016,1,1,0,0,0,0).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
The output it gives is
2016-01-01T00:00
2016-01-01T00:00:00
In the documentation for LocalDateTime.toString()
it explains this behavior:
The output will be one of the following ISO-8601 formats:
- uuuu-MM-dd'T'HH:mm
- uuuu-MM-dd'T'HH:mm:ss
- uuuu-MM-dd'T'HH:mm:ss.SSS
- uuuu-MM-dd'T'HH:mm:ss.SSSSSS
- uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS
The format used will be the shortest that outputs the full value of the time where the omitted parts are implied to be zero.
Upvotes: 8
Reputation: 1864
You may want to use
System.out.println (DateTimeFormatter.ISO_LOCAL_DATE_TIME.format (dt));
It gives:
2016-05-05T20:00:00
Upvotes: 4