XMLGregorianCalendar 日期序列化为空字符串

wbe*_*rry 5 java validation jax-ws

我使用 Java 1.6wsimport从 Web 服务的 WSDL 生成源代码。请求结构中的字段之一具有xs:dateTimeWSDL 包含的 XML 模式中的类型和javax.xml.datatype.XMLGregorianCalendar生成的代码中的类型。

通过使用soapUI进行手动测试,我确定Web服务接受以下序列化值:2011-12-08, 2011-12-08Z。不接受以下内容,在这种情况下的响应是空回复(不是显式错误):2011-12-08T20:00:00, 2011-12-08T20:00:00-05:00。如果这很重要的话,服务本身是由 .NET 提供支持的。

我的想法是服务器应该接受完整的日期/时间并仅拒绝日期,但相反的是正在发生的情况。但我并不认为服务器的维护者会愿意改变。所以我试图说服客户只发送一个日期。

我无法说服我的客户端代码将XMLGregorianCalendar对象仅序列化为日期。事实上我可以,除非生成的代码可以做到这一点。当生成的客户端代码(由 生成wsimport)执行此操作时,序列化值是空字符串,并且服务器正确返回错误。我使用数据包嗅探器验证了这一点。

以下是我在请求中创建和填充日期字段的方法:

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;
}
Run Code Online (Sandbox Code Playgroud)

在我的例子中,XMLGregorianCalendar 的实现类是com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl. 在调试器中,或者如果我添加日志输出,调用日期对象的toXMLFormat()方法仅返回日期,例如2011-12-09. 使用调试器检查日期对象本身,我看到它的yeardaymonth字段已填充,所有其他字段要么是null,要么-2147483648是 的值DatatypeConstants.FIELD_UNDEFINED。根据我找到的所有文档和互联网搜索结果,我的日期对象的格式正确。

我疯了吗?难道服务器真的出错了?生成的客户端代码拒绝仅发送日期是否正确?这是一个合理的“未定义行为”案例吗?是否使用了错误的实现类(无论如何这可能很重要)?是否存在wsimport影响我的已知问题?

wbe*_*rry 1

我看到了我不认识的 .NET Web 服务的不直观的实现细节。在我的分析中,我观察到提供完整的日期/时间序列化字符串会导致服务器发出空响应,但不会出现显式错误。

这是因为在服务器上,他们实际上使用日期/时间对象,但强制所有时间为东部标准时间午夜。因此,只有当我将请求中的时间强制为美国东部时间午夜时,响应才会填充结果,而我并没有这样做。(如果未给出时区,则服务器假定为 EST;如果根本未给出时间,则假定为午夜 EST。)

因此,就我而言,解决方案是修改客户端代码,以在创建请求时强制将时区设置为 Olson America/New_York,并将本地时间强制设置为 Olson 。00:00:00