无法从 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

如何克隆JAXB对象

C# 中的 Jaxb 等效项

C# 中的 Jaxb 等效项