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
JAXBプロバイダーとしてEclipseLinkJAXB(MOXy)を使用している場合、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と同様にこのユースケースを処理しているように見えます。私の元々の移植性の懸念はそれほど問題ではないかもしれません。
そうそう、やっと見つけた!Inheritance プラグインは、生成されたクラスをクラスから継承させたり、追加のインターフェースを実装したりできます。
次のようなものを含める必要があります
<bindings node="//xsd:complexType[@name='WhateverException']">
<inheritance:extends>foo.bar.WhateverException</inheritance:extends>
</bindings>
バインディング ファイルに追加し、getStackTrace() をオーバーライドして、マーシャリングされないように null を返します。
残念ながら、一部の JAXB 実装で問題が発生する可能性があります ( Blaise Doughan の回答を参照)。その回避策はまだ見つかりません。そのため、あまり移植性のないソリューションを使用するか、JAXB オブジェクトを例外にラップすることができます。