2010-12-08 65 views
28

我開始學習JAXB,所以我的問題可能非常愚蠢。現在我有類並且想要生成XML Schema。 this指令後去我得到異常JAXB和構造函數

IllegalAnnotationExceptions ......沒有一個無參數的默認構造函數 。

是的。我的類沒有默認的無參數構造函數。這太容易了。我有包含可見構造函數/最終方法的類,並且帶有參數的課程。我該做什麼 - 創建一些特定的momemto/builder類或向JAXB指定我的構造函數(以什麼方式?)?謝謝。

回答

42

JAXB可以使用XML適配器來支持這種情況。考慮你有沒有零參數的構造下列對象:

package blog.immutable; 

public class Customer { 

    private final String name; 
    private final Address address; 

    public Customer(String name, Address address) { 
     this.name = name; 
     this.address = address; 
    } 

    public String getName() { 
     return name; 
    } 

    public Address getAddress() { 
     return address; 
    } 

} 

你只需要創建這個類的一個可映射版本:

package blog.immutable.adpater; 

import javax.xml.bind.annotation.XmlAttribute; 
import blog.immutable.Address; 

public class AdaptedCustomer { 

    private String name; 
    private Address address; 

    @XmlAttribute 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public Address getAddress() { 
     return address; 
    } 

    public void setAddress(Address address) { 
     this.address = address; 
    } 

} 

和一個XML適配器,它們之間的轉換:

package blog.immutable.adpater; 

import javax.xml.bind.annotation.adapters.XmlAdapter; 
import blog.immutable.Customer; 

public class CustomerAdapter extends XmlAdapter<AdaptedCustomer, Customer> { 

    @Override 
    public Customer unmarshal(AdaptedCustomer adaptedCustomer) throws Exception { 
     return new Customer(adaptedCustomer.getName(), adaptedCustomer.getAddress()); 
    } 

    @Override 
    public AdaptedCustomer marshal(Customer customer) throws Exception { 
     AdaptedCustomer adaptedCustomer = new AdaptedCustomer(); 
     adaptedCustomer.setName(customer.getName()); 
     adaptedCustomer.setAddress(customer.getAddress()); 
     return adaptedCustomer; 
    } 

} 

然後房產引用Customer類,只需使用@XmlJavaTypeAdapter註釋:

package blog.immutable; 

import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 
import blog.immutable.adpater.CustomerAdapter; 

@XmlRootElement(name="purchase-order") 
public class PurchaseOrder { 

    private Customer customer; 

    @XmlJavaTypeAdapter(CustomerAdapter.class) 
    public Customer getCustomer() { 
     return customer; 
    } 

    public void setCustomer(Customer customer) { 
     this.customer = customer; 
    } 

} 

有關更詳細的例子請參閱:

5

您應該有一個JAXB的默認構造函數來實例化您的類。也許有一種解決辦法我不知道。

JAXB特別適用於bean類,允許通過調用setter來配置對象。

+1

爲所有類創建默認構造函數是一個非常糟糕的想法。必須有一些解決方法。 – 2010-12-08 12:29:38

+0

我也不喜歡這種設計,但這是標準的JAXB方式... – Guillaume 2010-12-08 12:31:42

+0

我坦率地不真正理解無參數的種族主義。您的bean類只能是info的容器,它可以很容易地轉換成XML,而不是複雜初始化的類。 – 2010-12-08 12:32:22

3

JAXB以簡單的方式從XML重新創建bean:創建bean的新實例,然後執行設置屬性所需的所有setXXX。所以,如果你的bean沒有無參數構造函數,那麼JAXB就不能創建它。正如在其他答案中所說的,JAXB對於簡單的「容器」bean更好,因爲無參數構造函數並不是真正的問題。如果您嘗試創建需要特定初始化的bean,則需要在setXXX方法中執行此操作。

13

可以使用註釋@XmlType並使用factoryMethod/factoryClass在各種組合中,如屬性:

@XmlType(factoryMethod="newInstance") 
@XmlRootElement 
public class PurchaseOrder { 
    @XmlElement 
    private final String address; 
    @XmlElement 
    private final Customer customer; 

    public PurchaseOrder(String address, Customer customer){ 
     this.address = address; 
     this.customer = customer; 
    } 

    private PurchaseOrder(){ 
     this.address = null; 
     this.customer = null; 
    } 
    /** Creates a new instance, will only be used by Jaxb. */ 
    public static PurchaseOrder newInstance() { 
     return new PurchaseOrder(); 
    } 

    public String getAddress() { 
     return address; 
    } 

    public Customer getCustomer() { 
     return customer; 
    } 
} 

令人驚訝的是,這個作品d當解組時,你會得到一個初始化的實例。你應該注意不要在你的代碼的任何地方調用newInstance方法,因爲它會返回一個無效的實例。