Using Java 1.6 wsimport
I generated source from a WSDL for a web service. One of the fields in the request structure has type xs:dateTime
in the XML schema included by the WSDL and type javax.xml.datatype.XMLGregorianCalendar
in the generated code.
Through manual testing with soapUI I have determined that the following serialized values are accepted by the web service: 2011-12-08
, 2011-12-08Z
. The following are not accepted and the response in this case is an empty reply (not an explicit error): 2011-12-08T20:00:00
, 2011-12-08T20:00:00-05:00
. The service itself is .NET powered if that matters.
My thought is that the server should accept the full date/time and reject the date only, but the other way around is what is happening. But I am under no assumption that maintainers of the server will be open to change. So I have attempted to convince the client to send a date only.
I can't convince my client code to serialize an XMLGregorianCalendar
object into a date only. Well actually I can, except when the generated code does it. When the generated client code (produced by wsimport
) does it, the serialized value is the empty string, and the server correctly returns an error. I verified this using a packet sniffer.
Here is how I'm creating and populating the date field in the request:
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.util.TimeZone;
// also import GeneratedRequest from generated packages
private makeRequest() {
GeneratedRequest request;
// ...
request.setDateField(xmlDayNow(TimeZone.getTimeZone("America/New_York"),
6)); // broadcast day starts at 6 am EST
// ...
}
@XmlSchemaType(name="date")
private static XMLGregorianCalendar xmlDayNow(TimeZone tz, int localHourStart)
throws MyException {
GregorianCalendar cal = gregorianBroadcastDayNow(tz, localHourStart);
XMLGregorianCalendar result;
try {
result = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(
cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1,
cal.get(Calendar.DAY_OF_MONTH), DatatypeConstants.FIELD_UNDEFINED)
.normalize();
} catch (DatatypeConfigurationException e) {
throw new MyException("XMLGregorianCalendar issue", e);
}
return result;
}
protected static GregorianCalendar gregorianBroadcastDayNow(TimeZone tz,
int localHourStart) {
GregorianCalendar now = new GregorianCalendar(tz);
if (now.get(GregorianCalendar.HOUR_OF_DAY) < localHourStart) {
now.add(GregorianCalendar.DAY_OF_MONTH, -1);
}
return now;
}
The implementation class for XMLGregorianCalendar in my case is com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl
. In the debugger, or if I add log output, calling the date object's toXMLFormat()
method returns a date only, such as 2011-12-09
. Using a debugger to inspect the date object itself, I see that its year
, day
and month
fields are populated, and all the others are either null
or -2147483648
which is the value of DatatypeConstants.FIELD_UNDEFINED
. According to all documentation and Internet search results I have found, my date object is correctly formed.
Am I crazy? Is the server really in error? Is the refusal of the generated client code to send a date only correct? Is this a justifiable "undefined behavior" case? Is the wrong implementation class being used (could that possibly matter anyway)? Is there some known issue with wsimport
that's affecting me?