7

親愛なる Java コーダーの皆さん、私はhttp://www.vogella.com/articles/JAXB/article.htmlの例を使用しました。

私の 3 つのクラス、UserStorage、User、および UserTest の JAXB XML の使用について

それは正常に動作しますが、それはただの非武装化です

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 

スレッド「メイン」での例外 javax.xml.bind.UnmarshalException: platform.User のインスタンスを作成できません - リンクされた例外: [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) com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.com.sun.org.apache.xerces.internal.parsers の com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:135) の startElement(UnmarshallingContext.java:465)。 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.java:648) com.sun.org.apache.xerces.internal. impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140) com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808) の scanDocument(XMLDocumentFragmentScannerImpl.java:511) com.sun.org.apache.xerces.internal.parsers.XML11Configuration. com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119) の parse(XML11Configuration.java:737) com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser. parse(AbstractSAXParser.java:1205) com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522) com.sun.xml.internal.bind.v2.runtime. unmarshaller.UnmarshallerImpl.unmarshall0(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) platform.UserTest.main(UserTest.java:77) 原因: java.lang.InstantiationException at 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) com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.createInstance(ClassBeanInfoImpl.java:231) で com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext) で.java:609) ... 20 件以上AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194) at platform.UserTest.main(UserTest.java:77) 原因: java.lang.InstantiationException at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30) at java.lang .reflect.Constructor.newInstance(Constructor.java:513) で com.sun.xml.internal.bind.v2.ClassFactory.create0(ClassFactory.java:112) で 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 以上AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194) at platform.UserTest.main(UserTest.java:77) 原因: java.lang.InstantiationException at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30) at java.lang .reflect.Constructor.newInstance(Constructor.java:513) で com.sun.xml.internal.bind.v2.ClassFactory.create0(ClassFactory.java:112) で 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 以上com.sun.xml.internal.bind.v2.ClassFactory.create0(ClassFactory.java:112) の java.lang.reflect.Constructor.newInstance(Constructor.java:513) で InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30) com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.createInstance(ClassBeanInfoImpl.java:231) で com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java: 609) ... 20以上com.sun.xml.internal.bind.v2.ClassFactory.create0(ClassFactory.java:112) の java.lang.reflect.Constructor.newInstance(Constructor.java:513) で InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30) com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.createInstance(ClassBeanInfoImpl.java:231) で com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java: 609) ... 20以上createInstance(ClassBeanInfoImpl.java:231) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:609) ... 20 詳細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;
}
4

4 に答える 4

10

これが失敗する理由は、JaxbがUserのインスタンスを作成しようとするためです。これは抽象的であり、したがって失敗です。

抽象クラスにアノテーションを追加します

@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

each( XmlTransientXmlSeeAlso)のjavadocを参照してください

これにより、jaxbが抽象クラスを初期化しようとするのを防ぐことができます。

私が見つけたこのメソッドの唯一の欠点は、作成されるxmlに追加の名前空間情報が追加されることです。

于 2012-04-22T12:28:59.327 に答える
8

XmlSeeAlsoアノテーションを、属性AdminおよびUserクラスをサブクラス化する他のすべての具象クラスを使用してUserクラスに追加する必要があります。

@XmlSeeAlso({Admin.class})

PS、Xmlタグ@XmlRootElementをAdminクラスに追加することを忘れないでください。

于 2012-04-22T12:29:31.840 に答える
0

XML を非整列化するときに JAXB がクラスの新しいインスタンス (オブジェクト) を作成する必要があるため、これは機能しません。また、xml のタグが抽象クラスにバインドされている場合、そのクラスからオブジェクトをインスタンス化することはできません。User クラスを非抽象にするか、xml タグを User の具体的なサブクラスにバインドする必要があります。

于 2012-04-22T12:19:27.690 に答える