我正在尝试编组java.lang.Exception,但没有成功。这是我的代码 -
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class JAXBTester
{
public static void main(String[] args) throws Exception
{
TestReport report = new TestReport();
report.setReportLog("Tests successful.");
File file = new File("TestReport.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(TestReport.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(report, file);
}
}
这是我想要编组的课程 -
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class TestReport
{
private String reportLog;
private Exception exception;
@XmlElement
public void setReportLog(String reportLog) { this.reportLog = reportLog; }
public String getReportLog() { return reportLog; }
@XmlElement
public void setException(Exception exception) { this.exception = exception; }
public Exception getException() { return exception; }
}
我收到以下异常 -
Exception in thread "main" com.sun.xml.internal.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 public java.lang.Exception TestReport.getException()
at TestReport
at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:451)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:283)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:126)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1142)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:130)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:248)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:235)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:445)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:637)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at JAXBTester.main(JAXBTester.java:14)
这是因为我试图编组java.lang.Exception。如何解决这个问题?
答案 0 :(得分:1)
还有其他方法,例如评论者引用的方法。但这是另一种方式......
Java中的Throwable
类(Exception
的超类)在java.io.Serializable
的意义上是可序列化的。这意味着您可以将其写入字节流,然后从这些字节重新组合。 (您的应用程序可能具有写得不好的不可序列化的Throwable
子类。如果是这种情况,则以下内容将不起作用。)
因此,解决此问题的一种方法是编写一个自定义适配器,将Throwable
(或Exception
)序列化为字节。在XML中,您会看到这些字节的十六进制。然后在接收端,您可以取消序列化,然后使用您开始使用的Throwable
(完全复制)。
这种方式的不好之处在于,异常在XML中不是人类可读的。好的部分是它非常简单。在TestReport
课程中,将此注释放在Exception
getter:
@XmlJavaTypeAdapter(ThrowableAdapter.class)
public Exception getException() { return exception; }
public void setException(Exception exception) { this.exception = exception; }
然后将此适配器类添加到您的项目中:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class ThrowableAdapter extends XmlAdapter<String, Throwable> {
private HexBinaryAdapter hexAdapter = new HexBinaryAdapter();
@Override
public String marshal(Throwable v) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(v);
oos.close();
byte[] serializedBytes = baos.toByteArray();
return hexAdapter.marshal(serializedBytes);
}
@Override
public Throwable unmarshal(String v) throws Exception {
byte[] serializedBytes = hexAdapter.unmarshal(v);
ByteArrayInputStream bais = new ByteArrayInputStream(serializedBytes);
ObjectInputStream ois = new ObjectInputStream(bais);
Throwable result = (Throwable) ois.readObject();
return result;
}
}
然后你的XML将包含这样的元素:
<exception>AED...</exception>
除了代替...
,你会看到一个巨大的十六进制字符串。如果它在另一侧没有编组,它就会像原版一样。
答案 1 :(得分:0)
你使用JRE 1.7吗?如果我使用随JRE一起分发的JAXB版本,我不会得到此异常。但是,如果我明确包含JAXB v.2.1.7,我会遇到这个问题。因此,我建议从类路径中删除所有jaxb实例,并使用Java运行时中包含的实例。
JRE 6似乎使用2.1.x,而JRE 7 2.2.x可能正确处理Throwable实现中的更改。
运行
可以找到JDK中包含的JAXB版本<JDK_HOME>/bin/xjc -version