xsd:datetime和XmlGregorianCalendar导致NullPointerException

Dra*_*mon 3 java datetime tomcat jax-ws jaxb

以下作品:

public Date getDate() {
    return date;
}
Run Code Online (Sandbox Code Playgroud)

并产生类似的东西:

<date>2010-03-23T17:43:50.879Z</date>
Run Code Online (Sandbox Code Playgroud)

我可以使用XmlGregorianCalendar返回xsd:date或xsd:time类型:

@XmlSchemaType(name="date")
public XmlGregorianCalendar getDate() {
    return date;
}
Run Code Online (Sandbox Code Playgroud)

它产生的东西如下:

<date>2010-03-23</date>
Run Code Online (Sandbox Code Playgroud)

但尝试返回xsd:datetime如下:

@XmlSchemaType(name="datetime")
public XmlGregorianCalendar getDate() {
     return date;
}
Run Code Online (Sandbox Code Playgroud)

导致此堆栈跟踪:

java.lang.NullPointerException
    at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl.checkXmlGregorianCalendarFieldRef(RuntimeBuiltinLeafInfoImpl.java:864)
    at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl.access$200(RuntimeBuiltinLeafInfoImpl.java:111)
    at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$13.print(RuntimeBuiltinLeafInfoImpl.java:536)
...snip...
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:619)
Run Code Online (Sandbox Code Playgroud)

根本没有提到我的代码.

我正在使用tomcat 6.0.24,java 1.6.0_16-b01

Dra*_*mon 9

好吧,我找到了基本的问题:它应该"dateTime"不是"datetime",但是有一些更深层次的方面.

首先,跟踪给了我很少的帮助,我花了一些时间找到正确的来源(jaxb-ri-2_2.src.zip).864行是这样的:

int bitField = xmlGregorianCalendarFieldRef.get(type);
Run Code Online (Sandbox Code Playgroud)

xmlGregorianCalendarFieldRef定义为:

private static final Map<QName, Integer> xmlGregorianCalendarFieldRef =
            new HashMap<QName, Integer>();
    static {
            Map<QName, Integer> f = xmlGregorianCalendarFieldRef;
            f.put(DatatypeConstants.DATETIME,   0x1111111);
            f.put(DatatypeConstants.DATE,       0x1111000);
            f.put(DatatypeConstants.TIME,       0x1000111);
            f.put(DatatypeConstants.GDAY,       0x1001000);
            f.put(DatatypeConstants.GMONTH,     0x1010000);
            f.put(DatatypeConstants.GYEAR,      0x1100000);
            f.put(DatatypeConstants.GYEARMONTH, 0x1110000);
            f.put(DatatypeConstants.GMONTHDAY,  0x1011000);
    }
Run Code Online (Sandbox Code Playgroud)

因此,xmlGregorianCalendarFieldRef它本身不能为null,但是如果get()使用地图中不存在的键调用它,它将返回null,并且NullPointerException当JVM尝试将其取消时将抛出它.

这段代码有点草率; 不检查类型值,这就是为什么我们得到这个相当神秘的消息.

显然我然后查了价值DatatypeConstants.DATETIME并发现了案例错误.

这也让我相信我应该使用类似的东西:

@XmlSchemaType(name=DatatypeConstants.DATETIME)
public XmlGregorianCalendar getDate() {
    return date;
}
Run Code Online (Sandbox Code Playgroud)

为了增加保护,该常量QName不是字符串.