如何使一些 xjc 生成的类成为自定义异常的子类,以便您可以实际抛出它们,并由 JAXBContext 处理?通常 web 服务会返回定义的各种错误,这些错误确实应该是一个异常,但由于它们不是你需要不必要地包装它们。
2 回答
即使您可以创建一个从您扩展而来的JAXB (JSR-222)模型,Exception
也无法从中创建一个JAXBContext
。我建议将其包装Exception
在与 JAXB 兼容的域模型中。
Java 模型 (Foo)
下面是一个简单的 Java 类,它扩展了Exception
.
package forum12840627;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Foo extends Exception {
}
演示
下面的演示代码尝试JAXBContext
在 Java 模型上创建一个。
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
文件进行配置。
了解更多信息
- http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
- http://blog.bdoughan.com/2011/12/eclipselink-moxy-is-jaxb-provider-in.html
更新#2
JAXB 参考实现的最新版本现在似乎可以处理这个用例以及 MOXy。我最初的可移植性问题可能不是什么大问题。
是的,我终于找到了一些东西!继承插件能够使生成的类从类继承或实现额外的接口。
你需要包括类似的东西
<bindings node="//xsd:complexType[@name='WhateverException']">
<inheritance:extends>foo.bar.WhateverException</inheritance:extends>
</bindings>
进入绑定文件并覆盖 getStackTrace() 以返回 null ,这样它就不会被编组。
Unfortunately you might run into trouble with some JAXB implementations (see Blaise Doughan's answer) - I haven't found a workaround for that yet. So you can either use a not quite nonportable solution, or wrap the JAXB objects into Exceptions.