【发布时间】:2012-10-11 13:26:07
【问题描述】:
如何使一些 xjc 生成的类成为自定义异常的子类,这样您就可以实际抛出它们,并且可以由 JAXBContext 处理?通常 web 服务会返回各种定义的错误,这些错误确实应该是一个异常,但由于它们不是你需要不必要地包装它们。
【问题讨论】:
如何使一些 xjc 生成的类成为自定义异常的子类,这样您就可以实际抛出它们,并且可以由 JAXBContext 处理?通常 web 服务会返回各种定义的错误,这些错误确实应该是一个异常,但由于它们不是你需要不必要地包装它们。
【问题讨论】:
即使您可以创建从Exception 扩展的JAXB (JSR-222) 模型,您也无法从中创建JAXBContext。我建议将Exception 包装在与 JAXB 兼容的域模型中。
Java 模型(Foo)
下面是一个简单的 Java 类,它扩展了 Exception。
package forum12840627;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Foo extends Exception {
}
演示
下面的演示代码尝试在 Java 模型上创建 JAXBContext。
package forum12840627;
import javax.xml.bind.JAXBContext;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Foo.class);
}
}
输出
以下是运行演示代码返回的异常。问题是Exception 不是有效的 JAXB 类,并且 JAXB 实现在处理 Java 模型时会引入超类。 (注意:在您自己的领域模型中,您可以使用@XmlTransient 注释超类以防止它们被处理:http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html)
Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.lang.StackTraceElement does not have a no-arg default constructor.
this problem is related to the following location:
at java.lang.StackTraceElement
at public java.lang.StackTraceElement[] java.lang.Throwable.getStackTrace()
at java.lang.Throwable
at java.lang.Exception
at forum12840627.Foo
at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:102)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:472)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:302)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1140)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:154)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:121)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:363)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522)
at forum12840627.Demo.main(Demo.java:8)
更新 #1
如果您使用 EclipseLink JAXB (MOXy) 作为您的 JAXB 提供程序,那么您将不会看到此异常,因为 javax.* 和 java.* 包中的类不被视为域类。 MOXy 是 WebLogic 12c 环境中的默认 JAXB 提供程序,也可以使用 jaxb.properties 文件进行配置。
更多信息
更新 #2
最新版本的 JAXB 参考实现现在似乎可以处理这个用例以及 MOXy。我最初的可移植性问题可能不是什么大问题。
【讨论】:
XmlAdapter 解决方案。
是的,我终于找到了一些东西! Inheritance plugin 能够使生成的类继承自类或实现额外的接口。
你需要包含类似的东西
<bindings node="//xsd:complexType[@name='WhateverException']">
<inheritance:extends>foo.bar.WhateverException</inheritance:extends>
</bindings>
进入绑定文件并覆盖 getStackTrace() 以返回 null,这样它就不会被编组。
不幸的是,您可能会遇到一些 JAXB 实现的麻烦(请参阅Blaise Doughan's answer) - 我还没有找到解决方法。因此,您可以使用不太便携的解决方案,或者将 JAXB 对象包装到异常中。
【讨论】: