2013-04-08 30 views
2

我写了一个包含HashMultiMap(来自Guava库)的bean类。我想使用JRE的XMLEncoder对XML进行编码。使用自定义的PersistenceDelegate我已经成功将bean写入文件。然而,当我试图反序列化XML我得到异常:Java Bean与XMLEncoder的持久性

java.lang.NoSuchMethodException: <unbound>=HashMultimap.put("pz1", "pz2")

我在做什么错?

// create the bean 
SomeBean sb = new SomeBean(); 

// add some data 
HashMultimap<String, String> stateMap = HashMultimap.create();  
stateMap.put("pz1", "pz2"); 
stateMap.put("pz3", "pz4"); 

sb.setStateMap(stateMap); 

// encode as xml 
FileOutputStream os = new FileOutputStream("myXMLFile.xml"); 
XMLEncoder encoder = new XMLEncoder(os); 
encoder.setPersistenceDelegate(HashMultimap.class, new CustomPersistenceDelegate()); 
encoder.writeObject(sb); 

// decode the xml 
FileInputStream is = new FileInputStream("myXMLFile.xml"); 
XMLDecoder decoder = new XMLDecoder(is); 
Object deSerializedObject = decoder.readObject(); 

class CustomPersistenceDelegate extends DefaultPersistenceDelegate 
{ 
    protected Expression instantiate(Object oldInstance, Encoder out) 
    { 
     return new Expression(oldInstance, oldInstance.getClass(), "create", null); 
    } 

    protected void initialize(Class<?> type, Object oldInstance, Object newInstance, 
           Encoder out) 
    { 
     super.initialize(type, oldInstance, newInstance, out); 

     com.google.common.collect.HashMultimap<String, String> m = 
      (com.google.common.collect.HashMultimap) oldInstance; 

     for (Map.Entry<String, String> entry : m.entries()) 
     { 
      out.writeStatement(new Statement(oldInstance, "put", 
      new Object[] { entry.getKey(), entry.getValue() })); 
     } 

    } 
} 

public class SomeBean 
{ 
    private HashMultimap<String, String> stateMap; 

    public HashMultimap<String, String> getStateMap() 
    { 
     return stateMap; 
    } 

    public void setStateMap(HashMultimap<String, String> stateMap) 
    { 
     this.stateMap = stateMap; 
    } 
} 
+0

我把你的代码,并把它放到Junit测试,并没有问题。它工作正常,没有例外。你可以发布完整的StackTrace吗?见[这里](http://txtup.net/Lndut) – 2013-04-08 21:06:46

+0

萨姆我没有得到一个完整的堆栈跟踪。相反,调试窗口显示如下:java.lang.Exception:Encoder:discarding statement HashMultimap.put(“pz3”,“pz4”); 继续... java.lang.Exception:Encoder:discarding statement HashMultimap.put(“pz1”,“pz2”); 继续... java.lang.NoSuchMethodException: = HashMultimap.put(“pz3”,“pz4”); 继续... java.lang.NoSuchMethodException: = HashMultimap.put(“pz1”,“pz2”); 继续... – javacavaj 2013-04-09 13:51:52

+0

山姆你能解码的对象?我解码时地图是空的。 – javacavaj 2013-04-09 15:25:58

回答

4

我还没有解决方案(还)。但是,这至少可以澄清问题。看起来,在Java 7 build 15和更高版本中进行的某些更改打破了您的Statement需要的查找方法。如果添加的ExceptionListener到XmlEncoder,它给你的是如何更好的主意失败:

 encoder.setExceptionListener(new ExceptionListener() { 
     @Override 
     public void exceptionThrown(Exception e) { 
      System.out.println("got exception. e=" + e); 
      e.printStackTrace(); 
     } 
    }); 

你会看到一个完整的堆栈跟踪,则:

java.lang.Exception: Encoder: discarding statement HashMultimap.put(Object, Object); 
at java.beans.Encoder.writeStatement(Encoder.java:306) 
at java.beans.XMLEncoder.writeStatement(XMLEncoder.java:400) 
at test2.XmlEncoderTest$CustomPersistenceDelegate.initialize(XmlEncoderTest.java:83) 
at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:118) 
at java.beans.Encoder.writeObject(Encoder.java:74) 
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:327) 
at java.beans.Encoder.writeExpression(Encoder.java:330) 
at java.beans.XMLEncoder.writeExpression(XMLEncoder.java:454) 
at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:115) 
at java.beans.Encoder.writeObject(Encoder.java:74) 
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:327) 
at java.beans.Encoder.writeExpression(Encoder.java:330) 
at java.beans.XMLEncoder.writeExpression(XMLEncoder.java:454) 
at java.beans.DefaultPersistenceDelegate.doProperty(DefaultPersistenceDelegate.java:194) 
at java.beans.DefaultPersistenceDelegate.initBean(DefaultPersistenceDelegate.java:253) 
at java.beans.DefaultPersistenceDelegate.initialize(DefaultPersistenceDelegate.java:400) 
at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:118) 
at java.beans.Encoder.writeObject(Encoder.java:74) 
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:327) 
at java.beans.Encoder.writeExpression(Encoder.java:330) 
at java.beans.XMLEncoder.writeExpression(XMLEncoder.java:454) 
at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:115) 
at java.beans.Encoder.writeObject(Encoder.java:74) 
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:327) 
at java.beans.Encoder.writeObject1(Encoder.java:258) 
at java.beans.Encoder.cloneStatement(Encoder.java:271) 
at java.beans.Encoder.writeStatement(Encoder.java:301) 
at java.beans.XMLEncoder.writeStatement(XMLEncoder.java:400) 
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:330) 

    ... 

Caused by: java.lang.NoSuchMethodException: HashMultimap.put(Object, Object); 
    at java.beans.Statement.invokeInternal(Statement.java:313) 
    at java.beans.Statement.access$000(Statement.java:58) 
    at java.beans.Statement$2.run(Statement.java:185) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.beans.Statement.invoke(Statement.java:182) 
    at java.beans.Statement.execute(Statement.java:173) 
    at java.beans.Encoder.writeStatement(Encoder.java:304) 
    ... 51 more 

通过部分显示引起它未能找到的方法。它看起来像这样发生,因为它无法正确匹配方法签名。它在Java Bean MethodFinder中失败,但由于JDK中没有包含源代码,所以我无法很好地追踪它。

如果我能找到确切的原因,我会更新这个。只是想在此期间为您提供更多信息。

UPDATE

我认为这是这些更高版本的bug。这是一个单元测试,它更直接地暴露错误(或意外行为)。下面的失败正是你的代码发生了什么:

@Test 
public void testMethodFinder() throws Exception { 

    Method m0 = MethodFinder.findMethod(this.getClass(), "setUp", new Class<?>[0]); 
    assertNotNull(m0); 

    // this is okay, because method is declared in the type referenced 
    Method m = MethodFinder.findMethod(Multimap.class, "put", new Class<?>[] { Object.class, Object.class }); 
    assertNotNull(m); 

    try { 
     // this fails, apparently because method is not declared in this subclass (is inherited from parent class) 
     Method m2 = MethodFinder.findMethod(HashMultimap.class, "put", new Class<?>[] { Object.class, Object.class }); 
     assertNotNull(m2); 
    } catch (Exception e) { 
     System.out.println("got exception. e=" + e); 
    } 
} 
+2

向Oracle提交的错误报告。干得不错! – javacavaj 2013-04-11 18:06:49