XMLGregorianCalendar 日期序列化为空字符串
我使用 Java 1.6 wsimport
从 Web 服务的 WSDL 生成源代码。请求结构中的字段之一在 WSDL 包含的 XML 模式中具有类型 xs:dateTime
,在生成的代码中具有类型 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;
}
在我的例子中,XMLGregorianCalendar 的实现类是 com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl。在调试器中,或者如果我添加日志输出,则调用日期对象的 toXMLFormat()
方法仅返回日期,例如 2011-12-09
。使用调试器检查日期对象本身,我看到它的年、日和月字段都已填充,所有其他字段都是null
或 -2147483648
,这是 DatatypeConstants.FIELD_UNDEFINED
的值。根据我找到的所有文档和互联网搜索结果,我的日期对象的格式正确。
我疯了吗?难道服务器真的出错了?生成的客户端代码拒绝仅发送日期是否正确?这是一个合理的“未定义行为”案例吗?是否使用了错误的实现类(无论如何这可能很重要)? wsimport
是否存在影响我的已知问题?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我发现 JAXB 的日期转换不应该留给他们自己的设备。不太熟悉 wsimport,但它允许您指定绑定文件吗?我使用 Joda 日期/时间,但我确信想法是相同的。将其添加到我的 binding.xjb 中:
使用这样的类:
I've found that JAXB's date conversions should not be left to their own devices. Not as familiar with wsimport, but does it allow you specify a binding file? I use Joda Date/Time but the idea is the same I'm sure. Added this to my binding.xjb:
With a class as such:
我看到了我不认识的 .NET Web 服务的不直观的实现细节。在我的分析中,我观察到提供完整的日期/时间序列化字符串会导致服务器发出空响应,但不会出现显式错误。
这是因为在服务器上,他们实际上使用日期/时间对象,但强制所有时间为东部标准时间午夜。因此,只有当我将请求中的时间强制为美国东部时间午夜时,响应才会填充结果,而我并没有这样做。 (如果没有给出时区,服务器假定为 EST;如果根本没有给出时间,则假定为午夜 EST。)
因此,就我而言,解决方案是修改客户端代码以强制时区为Olson
America/New_York
并在创建请求时强制将当地时间设置为00:00:00
。I was seeing an unintuitive implementation detail of .NET web services that I did not recognize. In my analysis I observed that providing a complete date/time serialized string resulted in an empty response from the server, but not an explicit error.
This was because on the server, they were in fact using date/time objects, but were forcing all of the times to midnight Eastern Standard Time. So the responses were only populated with results if I forced the time in the request to midnight EST, which I was not doing. (In the event that no time zone was given, the server assumed EST; and if no time was given at all, midnight EST was assumed.)
So in my case, the solution was to modify the client code to force the time zone to Olson
America/New_York
and force the local time to00:00:00
when creating the request.除了 Roy 的答案之外,这里还有 apache cxf 的有效绑定文件,其中
有 maven cxf codegen 配置/resources/binding.jxb
pom.xml 内
In addition to Roy's answer here is valid binding file for apache cxf with maven cxf codegen configuration
/resources/binding.jxb
inside pom.xml