Java调用Web服务报错:javax.servlet.ServletException: java.lang.NullPointerException
嘿,这个JAXB序列化的空指针问题我熟!先看你贴的错误栈:
SEVERE: Servlet.service() for servlet [Jersey RESTful Application] in context with path [/sove] threw exception [java.lang.NullPointerException] with root cause java.lang.NullPointerException at com.sun.xml.internal.bind.v2.runtime.reflect.ListTransducedAccessorImpl.useNamespace(ListTransducedAccessorImpl.java:63) at com.sun.xml.internal.bind.v2.runtime.property.AttributeProperty.hasSerializeURIAc...
这个错误本质是JAXB在处理列表类型属性时遇到了null值——具体是ListTransducedAccessorImpl类在尝试处理列表的命名空间逻辑时,访问了一个未初始化的null对象。给你几个针对性的解决方向:
优先检查实体类的列表属性初始化
这是最常见的原因!确保你的JAXB实体类里所有List类型的属性,在声明时就完成初始化,不要只定义不赋值:// 正确写法:初始化空列表 private List<YourEntity> items = new ArrayList<>(); // 错误写法:只声明,默认是null private List<YourEntity> items;JAXB序列化/反序列化时,如果列表属性是null,内部处理逻辑会直接触发空指针。
排查Jersey的JAXB提供者配置
如果你自定义了Jersey的MessageBodyWriter或者ContextResolver<JAXBContext>,检查这些自定义逻辑里有没有遗漏对空列表的处理。比如有些自定义序列化器会默认假设列表不为null,直接调用size()或者其他方法,导致NPE。验证请求/响应的XML数据
如果是接收客户端XML请求时出错,确认客户端发送的XML中对应的列表节点是否存在但为空,或者完全缺失。可以在服务端加日志打印接收的实体对象,确认列表属性是否为null;如果是响应时出错,检查你要返回的实体对象里的列表有没有被正确赋值。考虑替换或升级JAXB实现
你用的是JDK内置的com.sun.xml.internal.bind(Java 8及以前默认的JAXB),这个版本有一些老bug。如果上述方法都无效,可以考虑换成独立的JAXB实现(比如EclipseLink MOXy),或者升级到Java 11+——Java 11之后JAXB作为独立模块存在,修复了不少早期的空指针问题。
内容的提问来源于stack exchange,提问作者Veysel

