2012-04-22 9 views
6

Estimados codificadores compañero de java, he utilizado un ejemplo de http://www.vogella.com/articles/JAXB/article.html¿Cómo puedo hacer un trabajo de la clase abstracta con JAXB

para el uso de XML JAXB para mis 3 clases, UserStorage, el usuario y UserTest

se funciona bien, pero es sólo el unmarchialing de

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 

Excepción en hilo javax.xml.bind.UnmarshalException "principal": No se puede para crear un Instan ce de platform.User - con excepción vinculado: [java.lang.InstantiationException] en com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent (UnmarshallingContext.java:648) en com. sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError (Loader.java:236) en com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance (UnmarshallingContext.java : 615) en com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader.startElement (StructureLoader.java:170) en com.sun.xml.internal.bind.v2.runtime.unmarshaller .UnmarshallingContext._startElement (UnmarshallingContext.java:487) en com.sun .xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement (UnmarshallingContext.java:465) en com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement (SAXConnector.java: 135) en com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement (AbstractSAXParser.java:501) en com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement (XMLNSDocumentScannerImpl.java:400) en com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $ FragmentContentDriver.next (XMLDocumentFragmentScannerImpl.java:2756) en com.sun.org.apache.xerces.internal. impl.XMLDocumentScannerImpl.next (XMLDocumentScannerImpl.jav a: 648) en com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next (XMLNSDocumentScannerImpl.java:140) en com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl. scanDocument (XMLDocumentFragmentScannerImpl.java:511) en com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse (XML11Configuration.java:808) en com.sun.org.apache.xerces.internal. parsers.XML11Configuration.parse (XML11Configuration.java:737) en com.sun.org.apache.xerces.internal.parsers.XMLParser.parse (XMLParser.java:119) en com.sun.org.apache. xerces.internal.parsers.AbstractSAXParser.parse (AbstractSAXPars er.java:1205) en com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $ JAXPSAXParser.parse (SAXParserImpl.java:522) en com.sun.xml.internal.bind.v2. runtime.unmarshaller.UnmarshallerImpl.unmarshal0 (UnmarshallerImpl.java:200) en com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal (UnmarshallerImpl.java:173) en javax.xml. bind.helpers.AbstractUnmarshallerImpl.unmarshal (AbstractUnmarshallerImpl.java:137) en javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal (AbstractUnmarshallerImpl.java:194) en platform.UserTest.main (UserTest.java:77) causada por: java.lang.InstantiationException en sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance (InstantiationExceptionConstructorAccessorImpl.java:30) en java.lang.reflect.Constructor.newInstance (Constructor.java:513) en com.sun.xml.internal.bind.v2. ClassFactory.create0 (ClassFactory.java:112) en com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.createInstance (ClassBeanInfoImpl.java:231) en com.sun.xml.internal.bind.v2 .runtime.unmarshaller.UnmarshallingContext.createInstance (UnmarshallingContext.java:609) ... 20 más

¿hay alguna solución para esto , así podría vincular la clase User al XML, ya que puedo guardar el archivo XML con los detalles del usuario, pero es cuando quiero recuperarlo, comprueba que la clase User es abstracta, tengo una subclase admin, broker, accionista , pero hasta ahora, en mi clase de prueba de usuario, he creado solo 4 administradores para probar, gracias y espero que puedan ayudar.

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

// ejemplo UserStorage estática privada; // fin de james.wyche códigos 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; 
} 

Respuesta

0

que no puede trabajar, porque tiene JAXB para crear nuevas instancias (objetos) de sus clases cuando unmarshalling el código XML. Y si una etiqueta del xml está vinculada a una clase abstracta, simplemente no puede instanciar un objeto de esa clase. O bien debe hacer que la clase de usuario sea no abstracta o enlazar la etiqueta xml a una subclase concreta de usuario.

9

Por qué esto está fallando es porque Jaxb intentará crear una instancia de Usuario. que es abstracto y, por lo tanto, el fracaso.

En su clase abstracta añadir las anotaciones

@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 

consulte el Javadoc para cada uno (XmlTransient, XmlSeeAlso)

Lo que esto va a hacer es evitar que jaxb de intentar inicializar la clase abstracta.

El único inconveniente de este método que encontré es que se agregará información de espacio de nombres adicional al xml que se crea.

+2

Adición XmlTransient en la superclase eliminará la relación de herencia, que puede no ser deseado, consulte: http://blog.bdoughan.com/ búsqueda/etiqueta/XmlTransient. El artículo puede ayudar: http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html –

+0

gracias, echaremos un vistazo – Sean

6

Debe agregar una anotación XmlSeeAlso a la clase Usuario con los atributos Admin y todas las otras clases concretas que subclasifican la clase User.

@XmlSeeAlso({Admin.class}) 

PD, no olvide agregar la etiqueta Xml @XmlRootElement a la clase Admin.

+1

Muchas gracias Noam, Jan y Sean, lo arreglé usando tus soluciones :) – wyche5000

0

tiene que especificar el tipo de cada elemento concrete:

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