2012-04-22 12 views
6

Thưa lập trình viên java, Tôi đã sử dụng một ví dụ từ http://www.vogella.com/articles/JAXB/article.htmlLàm thế nào để tôi làm cho một tác phẩm lớp trừu tượng với JAXB

để sử dụng XML JAXB cho 3 lớp học của tôi, UserStorage, Thành viên, và UserTest

nó hoạt động tốt, nhưng nó chỉ là unmarchialing của

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 

ngoại lệ trong chủ đề javax.xml.bind.UnmarshalException "chính": Không thể để tạo ra một instan ce của platform.User - với ngoại lệ được liên kết: [java.lang.InstantiationException] tại com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent (UnmarshallingContext.java:648) tại com. sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError (Loader.java:236) tại com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance (UnmarshallingContext.java : 615) tại com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader.startElement (StructureLoader.java:170) tại com.sun.xml.internal.bind.v2.runtime.unmarshaller .UnmarshallingContext._startElement (UnmarshallingContext.java:487) tại com.sun .xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement (UnmarshallingContext.java:465) tại com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement (SAXConnector.java: 135) tại com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement (AbstractSAXParser.java WEBC01) tại com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement (XMLNSDocumentScannerImpl.java:400) tại com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $ FragmentContentDriver.next (XMLDocumentFragmentScannerImpl.java:2756) tại com.sun.org.apache.xerces.internal. impl.XMLDocumentScannerImpl.next (XMLDocumentScannerImpl.jav a: 648) tại com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next (XMLNSDocumentScannerImpl.java:140) tại com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl. scanDocument (XMLDocumentFragmentScannerImpl.java WEBC11) tại com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse (XML11Configuration.java:808) tại com.sun.org.apache.xerces.internal. parsers.XML11Configuration.parse (XML11Configuration.java:737) tại com.sun.org.apache.xerces.internal.parsers.XMLParser.parse (XMLParser.java:119) tại com.sun.org.apache. xerces.internal.parsers.AbstractSAXParser.parse (AbstractSAXPars er.java:1205) tại com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $ JAXPSAXParser.parse (SAXParserImpl.java WEBC22) tại com.sun.xml.internal.bind.v2. runtime.unmarshaller.UnmarshallerImpl.unmarshal0 (UnmarshallerImpl.java:200) tại com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal (UnmarshallerImpl.java:173) tại javax.xml. bind.helpers.AbstractUnmarshallerImpl.unmarshal (AbstractUnmarshallerImpl.java:137) tại javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal (AbstractUnmarshallerImpl.java:194) tại platform.UserTest.main (UserTest.java:77) Gây ra bởi: java.lang.InstantiationException tại sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance (InstantiationExceptionConstructorAccessorImpl.java:30) tại java.lang.reflect.Constructor.newInstance (Constructor.java:513) tại com.sun.xml.internal.bind.v2. ClassFactory.create0 (ClassFactory.java:112) tại com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.createInstance (ClassBeanInfoImpl.java:231) tại com.sun.xml.internal.bind.v2 .runtime.unmarshaller.UnmarshallingContext.createInstance (UnmarshallingContext.java:609) ... 20 hơn

có giải pháp nào cho việc này , vì vậy tôi có thể liên kết lớp User với XML, vì tôi có thể lưu tệp XML với chi tiết người dùng, nhưng khi tôi muốn truy xuất nó, nó đồng nghĩa rằng lớp User trừu tượng, tôi có một lớp quản trị viên, môi giới, cổ đông , nhưng cho đến nay, trong lớp người dùng thử nghiệm của tôi, tôi đã tạo chỉ 4 quản trị viên để kiểm tra, cảm ơn và hy vọng bạn có thể trợ giúp.

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 dụ UserStorage; // hết mã 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; 
} 

Trả lời

0

Điều đó không thể hoạt động, vì JAXB phải tạo các cá thể (đối tượng) mới của các lớp học của bạn khi unmarshalling xml. Và nếu một thẻ từ xml bị ràng buộc vào một lớp trừu tượng, nó không thể khởi tạo một đối tượng từ lớp đó. Bạn phải làm cho lớp Người dùng không trừu tượng hoặc gắn thẻ xml vào một lớp con cụ thể của Người dùng.

9

Tại sao điều này không thành công vì Jaxb sẽ cố gắng tạo một phiên bản Người dùng. đó là trừu tượng và do đó thất bại.

Mở lớp trừu tượng của bạn thêm các chú thích

@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 

thấy javadoc cho mỗi (XmlTransient, XmlSeeAlso)

Điều này sẽ làm là ngăn chặn jaxb từ cố gắng để khởi tạo lớp trừu tượng của bạn.

Nhược điểm duy nhất của phương pháp này tôi thấy là sẽ có thêm thông tin không gian tên được thêm vào xml được tạo.

+2

Thêm XmlTransient trên lớp siêu sẽ loại bỏ các mối quan hệ thừa kế mà có thể không được mong muốn, xem: http://blog.bdoughan.com/ tìm kiếm/nhãn/XmlTransient. Bài viết fillowing có thể giúp: http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html –

+0

cảm ơn, sẽ xem xét – Sean

6

Bạn cần thêm chú thích XmlSeeAlso vào lớp Người dùng với Quản trị viên thuộc tính và tất cả các lớp cụ thể khác phân lớp lớp Người dùng.

@XmlSeeAlso({Admin.class}) 

PS, đừng quên thêm thẻ Xml @XmlRootElement vào lớp Quản trị.

+1

Cảm ơn rất nhiều Noam, Jan và Sean, tôi đã khắc phục nó bằng cách sử dụng các giải pháp của bạn :) – wyche5000

0

Bạn cần phải xác định loại concrete của mỗi yếu tố:

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