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. 使用调试器检查日期对象本身,我看到它的year、day和month字段已填充,所有其他字段要么是null,要么-2147483648是 的值DatatypeConstants.FIELD_UNDEFINED。根据我找到的所有文档和互联网搜索结果,我的日期对象的格式正确。
我疯了吗?难道服务器真的出错了?生成的客户端代码拒绝仅发送日期是否正确?这是一个合理的“未定义行为”案例吗?是否使用了错误的实现类(无论如何这可能很重要)?是否存在wsimport影响我的已知问题?
我看到了我不认识的 .NET Web 服务的不直观的实现细节。在我的分析中,我观察到提供完整的日期/时间序列化字符串会导致服务器发出空响应,但不会出现显式错误。
这是因为在服务器上,他们实际上使用日期/时间对象,但强制所有时间为东部标准时间午夜。因此,只有当我将请求中的时间强制为美国东部时间午夜时,响应才会填充结果,而我并没有这样做。(如果未给出时区,则服务器假定为 EST;如果根本未给出时间,则假定为午夜 EST。)
因此,就我而言,解决方案是修改客户端代码,以在创建请求时强制将时区设置为 Olson America/New_York,并将本地时间强制设置为 Olson 。00:00:00