Pertanyaan Bagaimana cara membuat kelas abstrak bekerja dengan JAXB


Halo sesama penghobi java, Saya telah menggunakan contoh dari http://www.vogella.com/articles/JAXB/article.html

untuk penggunaan XML JAXB untuk 3 kelas saya, UserStorage, User, dan UserTest

itu berfungsi dengan baik, tapi itu hanya unmarchialing

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 

Pengecualian dalam utas "utama" javax.xml.bind.UnmarshalException: Tidak dapat   untuk membuat instance platform.User    - dengan pengecualian terkait: [java.lang.InstantiationException] di com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent (UnmarshallingContext.java:648)     di   com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError (Loader.java:236)     di   com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance (UnmarshallingContext.java:615)     di   com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader.startElement (StructureLoader.java:170)     di   com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement (UnmarshallingContext.java:487)     di   com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement (UnmarshallingContext.java:465)     di   com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement (SAXConnector.java:135)     di   com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement (AbstractSAXParser.java:501)     di   com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement (XMLNSDocumentScannerImpl.java:400)     di   com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $ FragmentContentDriver.next (XMLDocumentFragmentScannerImpl.java:2756)     di   com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next (XMLDocumentScannerImpl.java:648)     di   com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next (XMLNSDocumentScannerImpl.java:140)     di   com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument (XMLDocumentFragmentScannerImpl.java:511)     di   com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse (XML11Configuration.java:808)     di   com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse (XML11Configuration.java:737)     di   com.sun.org.apache.xerces.internal.parsers.XMLParser.parse (XMLParser.java:119)     di   com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse (AbstractSAXParser.java:1205)     di   com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $ JAXPSAXParser.parse (SAXParserImpl.java:522)     di   com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0 (UnmarshallerImpl.java:200)     di   com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal (UnmarshallerImpl.java:173)     di   javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal (AbstractUnmarshallerImpl.java:137)     di   javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal (AbstractUnmarshallerImpl.java:194)     di platform.UserTest.main (UserTest.java:77) Disebabkan oleh:   java.lang.InstantiationException di   sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance (InstantiationExceptionConstructorAccessorImpl.java:30)     di java.lang.reflect.Constructor.newInstance (Constructor.java:513)     di   com.sun.xml.internal.bind.v2.ClassFactory.create0 (ClassFactory.java:112)     di   com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.createInstance (ClassBeanInfoImpl.java:231) di   com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance (UnmarshallingContext.java:609)     ... 20 lagi

Apakah ada solusi untuk ini, sehingga saya dapat mengikat kelas Pengguna ke XML, karena saya dapat menyimpan file XML dengan detail pengguna, tetapi ketika saya ingin mengambilnya, itu menegaskan bahwa kelas Pengguna abstrak, saya memiliki admin , broker, sub-pemegang saham, tapi sejauh ini, di kelas tes pengguna saya, saya hanya membuat 4 admin untuk diuji, terima kasih dan semoga Anda bisa membantu.

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

/ / Contoh Instansi Pemakai statis pribadi;     // akhir dari james.wyche kode 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;
}

7
2018-04-22 11:59


asal


Jawaban:


Mengapa ini gagal adalah karena Jaxb akan mencoba untuk membuat sebuah instance dari Pengguna. yang abstrak dan karena itu kegagalan.

Di kelas abstrak Anda, tambahkan anotasi

@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

lihat javadoc untuk masing-masing (XmlTransient, XmlSeeAlso)

Apa yang akan dilakukan adalah mencegah jaxb dari mencoba menginisialisasi kelas abstrak Anda.

Satu-satunya downside ke metode ini saya temukan adalah akan ada tambahan informasi namespace ditambahkan ke xml yang dibuat.


9
2018-04-22 12:28



Anda perlu menambahkan XmlSeeAlso anotasi ke kelas Pengguna dengan atribut Admin dan semua kelas konkret lainnya yang meng-subkelas kelas Pengguna.

@XmlSeeAlso({Admin.class})

PS, jangan lupa untuk menambahkan tag Xml @XmlRootElement ke kelas Admin.


7
2018-04-22 12:29



Itu tidak bisa berfungsi, karena JAXB harus membuat instance baru (objek) dari kelas Anda ketika tidak memetakan xml. Dan jika sebuah tag dari xml terikat ke kelas abstrak, itu hanya tidak dapat memberi contoh objek dari kelas itu. Anda juga harus membuat kelas Pengguna tidak abstrak atau mengikat tag xml ke sub-kelas konkret Pengguna.


0
2018-04-22 12:19



Anda harus menentukan concrete jenis masing-masing elemen:

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

0
2018-02-06 14:38