2012-04-22 4 views
6

Cari programmatori collega java, ho usato un esempio da http://www.vogella.com/articles/JAXB/article.htmlCome faccio a fare un lavoro di classe astratta con JAXB

per l'utilizzo di XML JAXB per le mie 3 classi, UserStorage, l'utente, e UserTest

esso funziona bene, ma è solo l'unmarchialing di

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 

Exception in thread javax.xml.bind.UnmarshalException "principale": impossibile per creare un Instan ce of platform.User - con eccezione collegata: [java.lang.InstantiationException] in com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent (UnmarshallingContext.java:648) allo com. sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError (Loader.java:236) a com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance (UnmarshallingContext.java : 615) a com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader.startElement (StructureLoader.java:170) a com.sun.xml.internal.bind.v2.runtime.unmarshaller .UnmarshallingContext._startElement (UnmarshallingContext.java:487) a com.sun .xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement (UnmarshallingContext.java:465) a com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement (SAXConnector.java: 135) a com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement (AbstractSAXParser.java:501) a com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement (XMLNSDocumentScannerImpl.java:400) a com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $ FragmentContentDriver.next (XMLDocumentFragmentScannerImpl.java:2756) a com.sun.org.apache.xerces.internal. impl.XMLDocumentScannerImpl.next (XMLDocumentScannerImpl.jav un: 648) a com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next (XMLNSDocumentScannerImpl.java:140) a com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl. scanDocument (XMLDocumentFragmentScannerImpl.java:511) a com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse (XML11Configuration.java:808) a com.sun.org.apache.xerces.internal. parsers.XML11Configuration.parse (XML11Configuration.java:737) a com.sun.org.apache.xerces.internal.parsers.XMLParser.parse (XMLParser.java:119) a com.sun.org.apache. xerces.internal.parsers.AbstractSAXParser.parse (AbstractSAXPars er.java:1205) a com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $ JAXPSAXParser.parse (SAXParserImpl.java:522) a com.sun.xml.internal.bind.v2. runtime.unmarshaller.UnmarshallerImpl.unmarshal0 (UnmarshallerImpl.java:200) a com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal (UnmarshallerImpl.java:173) a javax.xml. bind.helpers.AbstractUnmarshallerImpl.unmarshal (AbstractUnmarshallerImpl.java:137) a javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal (AbstractUnmarshallerImpl.java:194) a platform.UserTest.main (UserTest.java:77) causato da: java.lang.InstantiationException a sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance (InstantiationExceptionConstructorAccessorImpl.java:30) a java.lang.reflect.Constructor.newInstance (Constructor.java:513) a com.sun.xml.internal.bind.v2. ClassFactory.create0 (ClassFactory.java:112) a com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.createInstance (ClassBeanInfoImpl.java:231) a com.sun.xml.internal.bind.v2 .runtime.unmarshaller.UnmarshallingContext.createInstance (UnmarshallingContext.java:609) ... altri 20

c'è qualche soluzione per questo , quindi potrei associare la classe User all'XML, dato che posso salvare il file XML con i dettagli dell'utente, ma è quando voglio recuperarlo, esso spiega che la classe User è astratta, ho un amministratore, broker, sottocategorie di shareholder , ma finora, nella mia classe di test utente, ho creato solo 4 amministratori da testare, grazie e spero che tu possa aiutare.

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 = ""; 

// esempio UserStorage statica privato; // fine di james.wyche Codici 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; 
} 

risposta

0

che non può funzionare, perché JAXB deve creare nuove istanze (oggetti) delle classi quando unmarshalling il codice XML. E se un tag dal xml è associato a una classe astratta, non può istanziare un oggetto da quella classe. È necessario rendere la classe utente non astratta o associare il tag xml a una sottoclasse concreta dell'utente.

9

Perché questo non funziona è perché Jaxb tenterà di creare un'istanza di Utente. che è astratto e quindi il fallimento.

Sulla vostra classe astratta aggiungere le annotazioni

@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 

consultare Javadoc per ogni (XmlTransient, XmlSeeAlso)

Che cosa questo farà si impedisce JAXB dal tentativo di inizializzare la classe astratta.

L'unico lato negativo di questo metodo che ho trovato è l'aggiunta di ulteriori informazioni sullo spazio dei nomi per l'xml che viene creato.

+2

Aggiunta XmlTransient sulla super classe rimuoverà la relazione di ereditarietà che non può essere desiderato, vedi: http://blog.bdoughan.com/ Ricerca/etichetta/XmlTransient. L'articolo che riempie potrebbe aiutare: http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html –

+0

grazie, dare un'occhiata – Sean

6

È necessario aggiungere un'annotazione XmlSeeAlso alla classe Utente con gli attributi Admin e tutte le altre classi concrete che sottoclassi la classe User.

@XmlSeeAlso({Admin.class}) 

PS, non dimenticare di aggiungere il tag Xml @XmlRootElement alla classe di amministrazione.

+1

Grazie mille Noam, Jan e Sean, ho risolto usando le tue soluzioni :) – wyche5000

0

è necessario specificare il tipo concrete di ogni elemento:

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