Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do i make an abstract class work with JAXB

Dear fellow java coders, I have used an example from http://www.vogella.com/articles/JAXB/article.html

for JAXB XML usage for my 3 classes, UserStorage, User, and UserTest

it works fine, but it's just the unmarchialing of

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 "main" javax.xml.bind.UnmarshalException: Unable to create an instance of platform.User - with linked exception: [java.lang.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) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501) at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:400) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2756) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648) at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.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) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194) at platform.UserTest.main(UserTest.java:77) Caused by: java.lang.InstantiationException at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at 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 more

Is there any solution for this, so i could bind the User class to the XML, as i can save the XML file with user details, but it's when i want to retrieve it, it conplains that User class is abstract, I have an admin, broker, shareholder sub classes, but so far, in my user test class, i have created only 4 admins to test on, thanks and hope you can help.

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

// private static UserStorage instance; // end of james.wyche JAXB codes.

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;
}
like image 966
wyche5000 Avatar asked Apr 22 '12 11:04

wyche5000


People also ask

How do you implement an abstract class?

To implement features of an abstract class, we inherit subclasses from it and create objects of the subclass. A subclass must override all abstract methods of an abstract class. However, if the subclass is declared abstract, it's not mandatory to override abstract methods.

Can you run an abstract class?

We can run abstract class in java like any other class if it has main() method.

Can you cast something as an abstract class?

Q: Can you cast to an abstract class? A: Sure - of course you can.


1 Answers

Why this is failing is because Jaxb will attempt to create an instance of User. which is abstract and therefore the failure.

On your abstract class add the annotations

@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

see the javadoc for each(XmlTransient, XmlSeeAlso)

What this will do is prevent jaxb from trying to initialize your abstract class.

The only downside to this method I found is there will be extra namespace information added to the xml that gets created.

like image 186
Sean Avatar answered Oct 18 '22 21:10

Sean