2013-04-08 96 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