无法使用JBoss Marshalling API序列化org.dom4j.Document

时间:2015-02-26 11:11:04

标签: java serialization jboss marshalling dom4j

尝试使用 JBoss编组API org.dom4j.Document 作为属性序列化Java对象时,我遇到了一个问题。

我正在使用JDK 1.7

enter image description here

与dom4j 1.5.2相同的问题。

Java对象:

package test.t4;
import org.dom4j.Document;
public class Movie implements java.io.Serializable {

    private static final long serialVersionUID = 1L;

    private String title;
    private String director;
    private transient int code;
    private int year;
    private Document docXml;

    public Movie() {
        super();
    }

    public Movie(String title, String director, int code, int year) {
        super();
        this.title = title;
        this.director = director;
        this.code = code;
        this.year = year;
    }

    //Getters and Setters

    @Override
    public String toString() {
        return "Movie [title=" + title + ", director=" + director + ", year="
                + year + ", docXml=" + docXml + "]";
    }

}

主类:

package test.t4;

import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.jboss.marshalling.Marshaller;
import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;
import org.jboss.marshalling.river.RiverMarshallerFactory;

public final class WriteExample {

    final static String file = "D:/TEST/serialization/jboss40.ser";

    public static void main(String[] args) {

        Document docXml = null;
        Movie mov0 = new Movie("The Hobbit: An Unexpected Journey",
                "Peter Jackson", 123456780, 2012);
        docXml = createDocument();
        mov0.setDocXml(docXml);

        Map<String, Movie> maps = new HashMap<String, Movie>();
        maps.put("Hobbit", mov0);

        System.out.println("maps : " + maps);

        goMarshall(maps);
      //serialize(maps);//When using the native Serialization Java API, the serialization works.
    }

public static void serialize(Map<String, Movie> maps) {
    try {
        FileOutputStream fileOut = new FileOutputStream(fileJDKSerialize);
        ObjectOutputStream out = new ObjectOutputStream(fileOut);
        out.writeObject(maps);
        out.close();
        fileOut.close();
        System.out
                .printf("Serialized data is saved in " + fileJDKSerialize);
    } catch (IOException i) {
        i.printStackTrace();
    }
}

    public static Document createDocument() {
        Document document = DocumentHelper.createDocument();
        Element starring = document.addElement("Starring");

        Element actor1 = starring.addElement("actor")
                .addAttribute("name", "Martin Freeman")
                .addAttribute("character", "Bilbo").addText("Good morning.");
        Element actor2 = starring
                .addElement("actor")
                .addAttribute("name", "Ian McKellen")
                .addAttribute("character", "Gandalf")
                .addText(
                        "What do you mean? Do you mean to wish me a good morning or do you mean that it is a good morning whether I want it or not? Or perhaps you mean to say that you feel good on this particular morning. Or are you simply stating that this is a morning to be good on? ");

        return document;
    }

public static void goMarshall(Object obj) {
    // Get the factory for the "river" marshalling protocol
    final MarshallerFactory marshallerFactory = new RiverMarshallerFactory();// Marshalling.getProvidedMarshallerFactory("river");

    // Create a configuration
    final MarshallingConfiguration configuration = new MarshallingConfiguration();
    // Use version 3
    configuration.setVersion(3);
    FileOutputStream os = null;
    try {

        final Marshaller marshaller = marshallerFactory
                .createMarshaller(configuration);
        os = new FileOutputStream(file);
        marshaller.start(Marshalling.createByteOutput(os));
        marshaller.writeObject(obj);
        marshaller.finish();
        os.close();

    } catch (IOException e) {
        System.err.print("Marshalling failed: ");
        e.printStackTrace();
    }
}
}

错误StackTrace:

  

地图:{霍比特人=电影[标题=霍比特人:意想不到的旅程,   导演=彼得杰克逊,年= 2012年,   docXml=org.dom4j.tree.DefaultDocument@570c16b7 [文件:名称无效]]}   编组失败:java.io.NotActiveException:writeFields()可能只是   在尚未编写字段时调用   org.jboss.marshalling.river.RiverObjectOutputStream.defaultWriteObject(RiverObjectOutputStream.java:162)     在org.dom4j.QName.writeObject(QName.java:239)处   sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:606)at   org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:271)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:976)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:569)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:569)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:569)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)     在   org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)     在   org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)     在   org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)     在   org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)     在   java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:343)     在java.util.HashMap.writeObject(HashMap.java:1129)at   sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:606)at   org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:271)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:976)     在   org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)     在   org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)     在   org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)     at test.t4.WriteExample.goMarshall(WriteExample.java:119)at   test.t4.WriteExample.main(WriteExample.java:43)引起:an   发生的异常:在字段qname中的字段属性中   对象中字段docXml中的字段内容中的字段内容   java.util.HashMap@9ffb6306

org.dom4j.QName 对象中精确检测到该问题。

2 个答案:

答案 0 :(得分:1)

Java序列化规范中解释了发生这种情况的原因:

  

该类的writeObject方法(如果实现)负责   保存班级的状态。 ObjectOutputStream的   defaultWriteObject或writeFields方法必须调用一次(并且只能调用   在写入任何可能需要的数据之前   相应的readObject方法恢复对象的状态;   即使没有写入可选数据,defaultWriteObject或writeFields   必须仍然被调用一次。如果是defaultWriteObject或writeFields   然后,在写入可选数据(如果有)之前不会调用一次   在以下情况下,实例反序列化的行为是不确定的   ObjectInputStream无法解析定义的类   有问题的writeObject方法。

注意句子“... defaultWriteObject或writeFields方法必须一次(只有一次)之前编写任何可选数据......”(强调添加) 。

QName类在编写可选数据后调用writeFields ,因此违反了规范。 也就是说,我一直在考虑试图找到一种方法来对这种限制更加宽容,但是现在还没有一个简单的修复,没有在两端添加一个类替换来换掉一个类。这是以兼容的方式正确序列化的。

感谢David Lloydhttps://issues.jboss.org/browse/JBMAR-174

<强>更新

问题:谢谢David,我现在明白了。但是我还有一个问题,当使用本机Java Serialization API时,没有遇到问题并且序列化工作(dom4j中的规范违规似乎并没有打扰受质疑的Java API)。 JBoss编组有什么区别吗? (我更新了上面的例子。)

答案:是的,因为Oracle序列化实现比规范更宽松。

Java序列化规范以获取更多详细信息:http://docs.oracle.com/javase/7/docs/platform/serialization/spec/output.html#861

答案 1 :(得分:0)

无答案;请不要upvote 有一些双重结束;尝试使用资源可以简化事情。 虽然错误信息对我来说仍然没有意义。

    try (Marshaller marshaller = marshallerFactory
                .createMarshaller(configuration)) {
        try (FileOutputStream os = new FileOutputStream(file) {

            marshaller.start(Marshalling.createByteOutput(os));
            marshaller.writeObject(obj);
            marshaller.finish();
        }
    } catch (IOException e) {
        System.err.print("Marshalling failed: ");
        e.printStackTrace();
    }