xsd:datetime和XmlGregorianCalendar导致NullPointerException

4
以下内容可行:
public Date getDate() {
    return date;
}

并且会生成类似以下的内容:
<date>2010-03-23T17:43:50.879Z</date>

我可以使用XmlGregorianCalendar来很好地返回xsd:date或xsd:time类型:

@XmlSchemaType(name="date")
public XmlGregorianCalendar getDate() {
    return date;
}

它会生成类似于以下内容:

<date>2010-03-23</date>

但是尝试以这种方式返回xsd:datetime:

@XmlSchemaType(name="datetime")
public XmlGregorianCalendar getDate() {
     return date;
}

导致此堆栈跟踪:
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)

这段话完全没有提到我的代码。

我正在使用Tomcat 6.0.24和Java 1.6.0_16-b01。

1个回答

10

我找到了基本的问题:应该是"dateTime"而不是"datetime",然而这个问题还有一些更深层次的方面。

首先,跟踪信息没有给我太多帮助,我花了一些时间才找到正确的源代码 (jaxb-ri-2_2.src.zip)。第864行是这样的:

int bitField = xmlGregorianCalendarFieldRef.get(type);

并且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);
    }
所以 xmlGregorianCalendarFieldRef 本身不能为 null,但是如果调用 get() 方法时使用的键不存在于映射中,则返回值将为 null。当 JVM 尝试取消装箱时,就会抛出 NullPointerException
这段代码有些粗糙;未检查类型值,这就是我们得到这个相当晦涩消息的原因。
很明显,我随后查找了 DatatypeConstants.DATETIME 的值并找到了大小写错误。
这也让我相信我应该使用类似以下的东西:
@XmlSchemaType(name=DatatypeConstants.DATETIME)
public XmlGregorianCalendar getDate() {
    return date;
}

为了增加保护,但是那个常量是一个QName而不是字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接