2012-04-22 38 views
6

親愛的同學的java程序員一個抽象類的工作, 我用從http://www.vogella.com/articles/JAXB/article.html如何使與JAXB

爲JAXB XML使用一個例子我的3個班,UserStorage,用戶和UserTest

它工作正常,但它只是在線程「主要」 javax.xml.bind.UnmarshalException

JAXBContext context = JAXBContext.newInstance(UserStorage.class); 
       Marshaller m = context.createMarshaller(); 
       m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 

the User class is ABSTRACT!, so it throws an 

異常的unmarchialing:無法 創建instan用戶 - 帶有鏈接的異常:[com.un.InstantiationException] at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:648) at com。 sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:236) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java :615) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader.startElement(StructureLoader.java:170) at com.sun.xml.internal.bind.v2.runtime.unmarshaller .UnmarshallingContext._startElement(UnmarshallingContext.java:487) at com.sun .xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:465) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java: 135) 在 com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501) 在 com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement( XMLNSDocumentScannerImpl.java:400) 在 com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $ FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2756) 在 com.sun.org.apache.xerces.internal。 impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.jav一:648) 在 com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140) 在 com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl。 scanDocument(XMLDocumentFragmentScannerImpl.java:511) 在 com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808) 在 com.sun.org.apache.xerces.internal。 parsers.XML11Configuration.parse在 com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)(XML11Configuration.java:737) 在 com.sun.org.apache。 xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXPars er.java:1205) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $ JAXPSAXParser.parse(SAXParserImpl.java:522) at com.sun.xml.internal.bind.v2。 runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:200) 在 com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173) 在 javax.xml。 bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137) 在 javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194) 在platform.UserTest.main(UserTest.java:77)引起通過: java.lang。InstantiationException在 sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30) 在java.lang.reflect.Constructor.newInstance(Constructor.java:513) 在 com.sun.xml.internal.bind.v2。 ClassFactory.create0(ClassFactory.java:112) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.createInstance(ClassBeanInfoImpl.java:231)at com.sun.xml.internal.bind.v2 .runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:609) ...... 20多個

對此有任何解決方案,所以我可以將用戶類綁定到XML,因爲我可以用用戶詳細信息保存XML文件,但是當我想要檢索它時,它會認爲用戶類是抽象的,我有管理員,經紀人,股東子類,但到目前爲止,在我的用戶測試課上,我只創建了4個管理員進行測試,感謝並希望您能提供幫助。

import platform.UserStorage; 
import platform.User; 



public class UserTest { 

private static final String USER_XML = "user2.xml"; 

public static void main(String[] args) throws JAXBException, IOException { 

    ArrayList<User> userList = new ArrayList<User>(); 

    // create test users 
      User user1 = new Admin(); 
      user1.setName("Dave"); 
      user1.setPass("1234"); 
      user1.setDeleted(true); 
      user1.setBan(false); 
      userList.add(user1); 

      User user2 = new Admin(); 
      user2.setName("James"); 
      user2.setPass("1234"); 
      user2.setDeleted(true); 
      user2.setBan(false); 
      userList.add(user2); 

      User user3 = new Admin(); 
      user3.setName("Mike"); 
      user3.setPass("1234"); 
      user3.setDeleted(true); 
      user3.setBan(false); 
      userList.add(user3); 


      // create bookstore, assigning book 
      UserStorage userstore = new UserStorage(); 
      userstore.setListName("Test List"); 
      userstore.setUserList(userList); 

      // create JAXB context and instantiate marshaller 
      JAXBContext context = JAXBContext.newInstance(UserStorage.class); 
      Marshaller m = context.createMarshaller(); 
      m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 
      m.marshal(userstore, System.out); 

      Writer w = null; 
      try { 
       w = new FileWriter(USER_XML); 
       m.marshal(userstore, w); 
      } finally { 
       try { 
        w.close(); 
       } catch (Exception e) { 
       } 
      } 

      // get variables from our xml file, created before 
      System.out.println(); 
      System.out.println("Output from our XML File: "); 
      Unmarshaller um = context.createUnmarshaller(); 
      UserStorage userstore2 = (UserStorage) um.unmarshal(new FileReader(
        USER_XML)); 

      for (int i = 0; i < userstore2.getUsersList().toArray().length; i++) { 
       System.out.println("User " + (i + 1) + ": " 
         + userstore2.getUsersList().get(i).getName() + " Pass " 
         + userstore2.getUsersList().get(i).getPass()); 
      }} } 



package platform; 


import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlType; 


//If you want you can define the order in which the fields are written 
//Optional 

/** 
* @author dinesh.kaushish, james.wyche //updated XML properties. 
* 
*/ 
@XmlRootElement(name = "user") 
@XmlType(propOrder = { "name", "pass", "deleted", "ban" }) 

..

public abstract class User implements UserInterface { 

private String name; 
private String pass; 
private boolean deleted; 
private boolean ban; 

/** 
* @ author dinesh.kaushish 
* @param String username 
* return void 
*/ 

public void setName(String name) 
{ 
    this.name = name; 
} 

// If you like the variable name, e.g. "name", you can easily change this 
    // name for your XML-Output: 

/** 
* @author dinesh.kaushish 
* @param null 
* @return String user; 
*/ 
@XmlElement(name = "user") 
public String getName() 
{ 
    return this.name; 
} 

/** 
* @author dinesh.kaushish 
* @param String pwd 
* @return void 
*/ 
public void setPass(String pass) 
{ 
    this.pass=pass; 
} 

/** 
* @author dinesh.kaushish 
* @param void 
* @return String password 
*/ 
@XmlElement(name = "pass") 
public String getPass() 
{ 
    return pass; 
} 

/** 
* @author dinesh.kaushish 
* @param dFlag 
* @return void 
*/ 
public void setDeleted(boolean deleted) 
{ 
    this.deleted = deleted; 
} 

/** 
* @author dinesh.kaushish 
* @return boolean isDeleted 
*/ 
@XmlElement(name = "deleted") 
public boolean getDeleted() 
{ 
    return deleted; 
} 


/** 
* @author dinesh.kaushish 
* @param bFlag 
*/ 
public void setBan(boolean ban) 
{ 
    this.ban = ban; 
} 

/** 
* @author dinesh.kaushish 
* @return Boolean isBanned 
*/ 
@XmlElement(name = "ban") 
public Boolean getBan() 
{ 
    return ban; 
} 


public abstract void addUser(); 
public abstract void removeUser(); 
public abstract void verifyUser(); 
public abstract void passReset(); 
public abstract void faultReport(); 
public abstract void RequestsForAccess(); 
public abstract void UpdateDetails(); 
public abstract void BanUser(); 
public abstract void ChangePermissions(); 


    } 



package platform; 

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.util.HashMap; 

import javax.xml.stream.XMLEventReader; 
import javax.xml.stream.XMLInputFactory; 
import javax.xml.stream.XMLStreamException; 
import javax.xml.stream.events.XMLEvent; 

import java.util.ArrayList; 

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlElementWrapper; 
import javax.xml.bind.annotation.XmlRootElement; 





/** 
* @author michael.wambeek, james.wyche //added JAXB support. 
* 
*/ 
//This statement means that class "Bookstore.java" is the root-element of our example 
@XmlRootElement(namespace = "platform") 
public class UserStorage { 

// XmLElementWrapper generates a wrapper element around XML representation 
    @XmlElementWrapper(name = "userList") 
    // XmlElement sets the name of the entities 
    @XmlElement(name = "user") 
private ArrayList<User> userList; 
private String listName = ""; 

//私有靜態UserStorage實例; //結束james.wyche JAXB代碼。

public UserStorage(){ 

} 

/** 
* @author michael.wambeek 
* 
* Searches for a username and returns the password. 
* 
* @param username The username to search for 
* @return The password of the correct username or null 
* @throws Exception 
*/ 
public String findUser(String username) throws Exception{ 
    return search(username); 
} 

public boolean storeUser(String username, String password, UserType type){ 
    return true; 
} 

/** 
* @author james.wyche 
* @param userList 
*/ 
public void setUserList(ArrayList<User> userList) { 
    this.userList = userList; 
} 

/** 
* 
* @return UserList 
*/ 
public ArrayList<User> getUsersList() { 
    return userList; 
} 

回答

0

這是行不通的,因爲JAXB必須在解組xml的時候創建新類的實例(對象)。如果xml中的標籤綁定到抽象類,它就不能實例化該類中的對象。您必須使User類爲非抽象類型,或者將xml標籤綁定到User的具體子類。

9

爲什麼這是失敗的,因爲Jaxb將嘗試創建一個用戶實例。這是抽象的,因此是失敗的。

在您的抽象類中添加註釋

@XmlTransient //Prevents the mapping of a JavaBean property/type to XML representation 
@XmlSeeAlso({Admin.class, <other class>}) //Instructs JAXB to also bind other classes when binding this class 

看到每個(XmlTransientXmlSeeAlso)的Javadoc

這將完成爲防止JAXB從試圖初始化抽象類。

我發現這種方法唯一的缺點是會有額外的名稱空間信息添加到創建的XML中。

+2

的超類會清除可能不是所希望的繼承關係添加XmlTransient,請參閱:http://blog.bdoughan.com/搜索/標籤/ XmlTransient。豐滿文章可能會有所幫助:http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html – 2012-04-22 12:53:06

+0

謝謝,請看看 – Sean 2012-04-22 13:44:06

6

您需要添加一個XmlSeeAlso註釋到具有屬性Admin和User類的所有其他具體類的User類。

@XmlSeeAlso({Admin.class}) 

PS,別忘了將Xml標記@XmlRootElement添加到Admin類。

+1

非常感謝Noam,Jan和Sean,我修正了它使用你的解決方案:) – wyche5000 2012-04-22 13:27:20

0

您必須指定concrete類型每個元素:

<user xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Admin"> 
    ... 
</user>