无法从 JAXB 发现 QNAme 类:java.util.Map
Posted
技术标签:
【中文标题】无法从 JAXB 发现 QNAme 类:java.util.Map【英文标题】:Cannot Discover QNAme from JAXB for class: java.util.Map 【发布时间】:2014-03-05 03:21:03 【问题描述】:我正在尝试使用 Spring Wadl 生成器:https://github.com/autentia/wadl-tools。
AFAIK,这个工具使用了与Tomasz Nurkiewicz@tomasz-nurkiewicz 相同的想法:从 Spring 获取 RequestMappingHandlerMapping,检查每个元素并生成适当的 WADL。
在内部,该工具将使用 JAXB 在控制器中创建参数的 XML。尽可能好,但在我的应用程序中运行不佳。
我遇到了以下异常:
2014-02-07 15:33:41,827 WARN user=unauthenticatedUser com.autentia.xml.namespace.QNameBuilder - Cannot discover QName from JAXB annotations for class: java.util.Map. Preparing generic QName.com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.util.Map is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.util.Map
来自(简化的stacktrack)
at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:106)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:471)
(...)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:248)
(...)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at com.autentia.xml.namespace.QNameBuilder.discoverQNameFromJaxb(QNameBuilder.java:68)
(...)
at com.autentia.web.rest.wadl.builder.ApplicationBuilder.build(ApplicationBuilder.java:36)
问题
我可以强制一个默认适配器连接到接口吗?
通常人们可以只为特定适配器的接口添加注释,但我不想更改和/或分析数百个类。
相关链接
java.util.List is an interface, and JAXB can't handle interfaces http://blog.bdoughan.com/2013/03/jaxb-and-javautilmap.html https://weblogs.java.net/blog/2006/06/06/jaxb-and-interfaces已编辑
很遗憾,我无法更改 REST API。
来自javadoc of MessageWriter:
支持将 Java 类型转换为流的提供者的合同。要添加 MessageBodyWriter 实现,请使用 @Provider 注释实现类。
WADL 应按原样提供服务信息。例如,通过注释添加 MessageBodyWriter 会更改 API。由于我可以更改 QNameBuilder.discoverQNameFromJaxb,是否有可能在这个“时刻”将 MessageBodyWriter 更改/提供为 java.util.Map 并改回 WADL 生成?
【问题讨论】:
【参考方案1】:导致问题的原因
JAXB (JSR-222) 实现可以将java.util.Map
作为映射字段/属性处理,但不能将其作为根级别对象处理。您可能有一个对应于 RESTful 操作的方法,该方法返回一个 Map
。
如何解决
-
您可以引入一个具有
Map
类型的映射字段/属性的新域对象,而不是将Map
作为根级别对象,并改用它。
为Map
类实现MessageBodyReader
/MessageBodyWriter
,以便使用它而不是使用JAXB。
更新
我不想改变和分析数百个课程
你不会的。您只需添加一个MessageBodyReader
/MessageBodyWriter
来识别Map
类(对于“application/xml”媒体类型)来对其进行特殊处理。另一种方法是不断收到异常。
基本上我无法更改 REST API。
您不会更改 REST API。您需要确保您的 MessageBodyReader
/MessaggeBodyWriter
正常工作。
通过使用低等级的黑魔法,可能会提供 Map 的 MessageBodyWriter 并在此之后删除?
这并不是真正的低级或黑魔法。您可以仅为 Map
类提供特殊处理。
【讨论】:
很遗憾,我无法更改 REST API。 WADL 应按原样提供服务信息。 (我将添加更多有问题的信息)。 我更新了这个问题,更清楚地说明“我不想改变和分析数百个课程”的意思。基本上我无法更改 REST API。通过使用低级别的黑魔法,是否可以为 Map 提供 MessageBodyWriter 并在此之后删除? @blaise.doughan - 只要深入研究,我就会意识到它有多么复杂。我正在使用 AFAIK 的 Spring MVC,开箱即用它不会识别 \@Provider 注释(实际上,包含 MessageBodyWriter 的 JSR 311 目前也在 CLASSPATH 中)。 该解决方案的最大问题是@Provider 注释。我需要添加 JSR 311 + 提供一种让 Spring 理解此注释的方法。以上是关于无法从 JAXB 发现 QNAme 类:java.util.Map的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jaxb2-maven-plugin 2.x 从 WSDL 生成 Java 类?
Java SAXParser:`localName` 和 `qName` 之间的区别
NoClassDefFoundError:由于缺少依赖关系,无法加载类groovy.xml.jaxb.JaxbGroovyMethods javax / xml / bind / Unmarshall