JAXB и конструкторы - PullRequest
       33

JAXB и конструкторы

28 голосов
/ 08 декабря 2010

Я начинаю изучать JAXB, поэтому мой вопрос может быть очень глупым.Теперь у меня есть классы и я хочу сгенерировать XML-схему.После этой инструкции я получаю исключение

IllegalAnnotationExceptions ... не имеет конструктора по умолчанию без аргументов.

Да.Мои классы не имеют конструкторов по умолчанию без аргументов.Это слишком просто.У меня есть классы с видимыми конструкторами / финальными методами и, конечно же, с аргументами.Что мне делать - создавать какие-то определенные классы momemto / builder или указывать мои конструкторы для JAXB (каким образом?)?Спасибо.

Ответы [ 4 ]

42 голосов
/ 08 декабря 2010

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;
    }

} 

Более подробный пример см.

14 голосов
/ 15 июля 2011

Вы можете использовать аннотацию @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, так как он вернет недопустимый экземпляр.

5 голосов
/ 08 декабря 2010

У вас должен быть конструктор по умолчанию для JAXB, чтобы иметь возможность создавать экземпляры ваших классов. Может быть, есть обходной путь, которого я не знаю.

JAXB специально приспособлен для классов, подобных бобам, позволяя конфигурировать объекты, вызывая для них сеттеры.

3 голосов
/ 08 декабря 2010

JAXB воссоздает bean-компоненты из XML простым способом: он создает новый экземпляр bean-компонента, а затем выполняет все setXXX, необходимые для установки атрибутов.Итак, если у вашего компонента нет конструктора без аргументов, JAXB не сможет его создать.Как сказано в других ответах, JAXB лучше работает для простых «контейнерных» bean-компонентов, для которых конструктор без аргументов на самом деле не является проблемой.Если вы пытаетесь создать bean-компоненты, которые нуждаются в особой инициализации, вам нужно сделать это с помощью методов setXXX.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...