如何使用JAXB Marshaller编组java.lang.Exception? [英] How to marshall java.lang.Exception using JAXB Marshaller?

查看:132
本文介绍了如何使用JAXB Marshaller编组java.lang.Exception?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编组java.lang.Exception,但没有成功。这是我的代码 -

I am trying to marshall java.lang.Exception, but without success. Here's my code -

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);
    }
}

这是我想要编组的课程 -

This is the class I want to marshall -

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; }

}

我收到以下异常 -

I get the following 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。如何解决这个问题?

This is because I am trying to marshall java.lang.Exception. How to solve this problem?

推荐答案

还有其他方法,例如评论者引用的方法。但是这是另一种方式......

There are other ways of doing it, such as the one referenced by the commenter. But here's another way...

Java中的 Throwable 类(超级类异常)在 java.io.Serializable 的意义上是可序列化的。这意味着您可以将其写入字节流,然后从这些字节重新组合。 (您的应用程序可能包含写得不好的非序列化 Throwable 的子类。如果是这种情况,则以下操作无效。)

The Throwable class in Java (superclass of Exception) is serializable in the sense of java.io.Serializable. This means that you can write it to a byte stream and then recompose it later from those bytes. (It's possible that your application might have poorly-written non-serializable subclasses of Throwable. If that's the case, the following won't work.)

所以解决这个问题的一种方法是编写一个自定义适配器来序列化 Throwable (或 Exception )到字节。在XML中,您会看到这些字节的十六进制。然后在接收端,您可以取消序列化,然后使用(完全复制)您开始的 Throwable

So one way to deal with this is to write a custom adapter that serializes the Throwable (or Exception) to bytes. And in the XML, you see the hex for those bytes. Then on the receiving end you can un-serialize and then work with (an exact replica of) the Throwable you started with.

关于这种方式的不好的部分是,在XML中,Exception不是人类可读的。好的部分是它非常简单。在 TestReport 类中,将此注释放在 Exception getter上:

The bad part about this way is that the Exception is not human-readable inside the XML. The good part is that it's really simple. On your TestReport class, put this annotation on your Exception getter:

@XmlJavaTypeAdapter(ThrowableAdapter.class)
public Exception getException() { return exception; }

public void setException(Exception exception) { this.exception = exception; }

然后将此适配器类添加到项目中:

And then add this adapter class to your project:

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将包含如下元素:

Then your XML will contain an element like this:

<exception>AED...</exception>

除了代替 ... 你会看到一个巨大的十六进制字符串。当它在另一侧没有编组时,它就像原版一样。

except in instead of ... you'll see a huge hex string. When it's un-marshalled on the other side, it'll be just like the original.

这篇关于如何使用JAXB Marshaller编组java.lang.Exception?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆