私はJAXBの学習を始めているので、私の質問は非常にばかげている可能性があります。現在、クラスがあり、XMLスキーマを生成します。 this 命令の後、例外が発生します
IllegalAnnotationExceptions ...には引数のないデフォルトのコンストラクタはありません。
うん。私のクラスには、デフォルトの引数なしのコンストラクタがありません。簡単すぎる。私は、パッケージの可視コンストラクター/最終メソッドを備えたクラスと、もちろん引数を備えたクラスを持っています。特定のモメト/ビルダークラスを作成するか、コンストラクターをJAXBに指定します(方法は?)ありがとう。
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;
}
}
より詳細な例については、を参照してください。
アノテーション@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. */
private static PurchaseOrder newInstance() {
return new PurchaseOrder();
}
public String getAddress() {
return address;
}
public Customer getCustomer() {
return customer;
}
}
驚くことに、これは機能し、非整列化時に初期化されたインスタンスを取得します。 newInstance
メソッドは、無効なインスタンスを返すため、コードのどこにも呼び出さないように注意してください。
クラスをインスタンス化できるようにするには、JAXBのデフォルトのコンストラクターが必要です。多分私にはわからない回避策があります。
JAXBは特にBeanのようなクラスに適合しており、セッターを呼び出すことでオブジェクトを構成できます。
JAXBはXMLからBeanを単純な方法で再作成します。Beanの新しいインスタンスを作成し、属性の設定に必要なすべてのsetXXX
を実行します。したがって、Beanに引数なしのコンストラクタがない場合、JAXBはそれを作成できません。他の回答で述べたように、JAXBは、引数のないコンストラクターが実際には問題ではない単純な「コンテナー」Beanに適しています。特定の初期化が必要なBeanを作成しようとしている場合は、setXXX
メソッドで作成する必要があります。