Не удается маршалировать java.lang.Строка

#java #xml #marshalling #cxf #unmarshalling

#java #xml #маршалирование #cxf #отмена маршалирования

Вопрос:

Вот моя дилемма:

У меня есть класс dto для маршалинга туда и обратно из / в XML.

Вот в чем хитрость: из-за большого количества классов dto, с которыми имеет дело наш проект, которые представляют собой коллекции с тегом outter во множественном числе, я решил создать коллекцию делегатов, которая позволяет мне взять один из этих классов и без особых усилий превратить их в коллекцию и получить удобство, которое с ним связано (итерация, добавлениеи т.д.).

В нашем проекте у нас есть маршалинг-тесты для устранения ошибок аннотаций и тому подобного. Ниже приведен мой код проблемы.

Проблема: в зависимости от маршалера, если я расширяю этот QuickCollection, я получаю приведенную ниже ошибку. Когда объект разархивируется в xml с использованием CXF в качестве ответа на запрос веб-сервиса, он завершается с ошибкой. Точная ошибка: com.sun.istack.SAXException2: невозможно маршалировать тип «java.lang.Строка» как элемент, потому что в нем отсутствует аннотация @XmlRootElement

Когда он маршалируется / не маршалируется с помощью JAXB в тесте, все в порядке. Когда этот же QuickCollection используется для маршалирования результатов от сторонних разработчиков с использованием spring RestOperations и работает нормально

винт разума: когда я удаляю наследование и управляю коллекцией как частным членом, все просто работает!

Для меня это не имеет смысла, поскольку я буквально возвращаю точный тип данных в обеих ситуациях.

Ниже приведен весь соответствующий код.

Это унаследованный класс делегата.

     public class QuickCollection<T> implements Collection<T> {
    // to be set if needed after instantiation. To behave like a normal collection, we set it to something safe
    protected Collection<T> delegate = Collections.emptySet();

    public QuickCollection() {
    }

    public QuickCollection(Collection<T> delegate) {
        this.delegate = delegate;
    }

    @Override
    public int size() {
        return delegate.size();
    }

    @Override
    public boolean isEmpty() {
        return delegate.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return delegate.contains(o);
    }

    @Override
    public Iterator<T> iterator() {
        return delegate.iterator();
    }

    @Override
    public Object[] toArray() {
        return delegate.toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return delegate.toArray(a);
    }

    @Override
    public boolean add(T t) {
        return delegate.add(t);
    }

    @Override
    public boolean remove(Object o) {
        return delegate.remove(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return delegate.containsAll(c);
    }

    @Override
    public boolean addAll(Collection<? extends T> c) {
        return delegate.addAll(c);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return delegate.removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return delegate.retainAll(c);
    }

    @Override
    public void clear() {
        delegate.clear();
    }

    @Override
    public String toString() {
        return ""   delegate.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        QuickCollection that = (QuickCollection) o;

        if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return delegate != null ? delegate.hashCode() : 0;
    }
}
  

Вот дочерний класс DTO

 @XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "BuddyCodes")
@XmlRootElement(name = "BuddyCodes")
public class BuddyCodes extends QuickCollection<String> implements Xml {

    private Long accountId;

    private Date expirationDate;

    public BuddyCodes() {
        super.delegate = new HashSet<String>();
    }

    public BuddyCodes(Long accountId, Set<String> codes, Date expirationDate) {
        super(codes);
        this.accountId = accountId;
        this.expirationDate = expirationDate;
        super.delegate = new HashSet<String>();

    }

    public BuddyCodes(Long accountId, Date expirationDate) {
        this.accountId = accountId;
        this.expirationDate = expirationDate;
        super.delegate = new HashSet<String>();
    }

    @Override
    public String toXml() {
        String retVal;
        try {
            retVal = StringUtils.toXml(this);
        }
        catch (JAXBException e) {
            retVal = e.toString();
        }
        return retVal;

    }

    public Long getAccountId() {
        return accountId;
    }

    public void setAccountId(Long accountId) {
        this.accountId = accountId;
    }

    public Set<String> getCodes() {
        return (Set<String>) super.delegate;
    }

    @XmlElement(name = "code")
    public void setCodes(Set<String> codes) {
        super.delegate = codes;
    }

    public Date getExpirationDate() {
        return expirationDate;
    }

    public void setExpirationDate(Date expirationDate) {
        this.expirationDate = expirationDate;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        BuddyCodes that = (BuddyCodes) o;

        if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) return false;
        if (delegate != null ? !super.delegate.equals(that.delegate) : that.delegate != null) return false;
        if (expirationDate != null ? !expirationDate.equals(that.expirationDate) : that.expirationDate != null)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = accountId != null ? accountId.hashCode() : 0;
        result = 31 * result   (expirationDate != null ? expirationDate.hashCode() : 0);
        result = 31 * result   (super.delegate != null ? super.delegate.hashCode() : 0);
        return resu<
    }

    @Override
    public String toString() {
        return "BuddyCodes{"  
                "accountId="   accountId  
                "codes="   super.delegate  
                ", expirationDate="   expirationDate  
                '}';
    }
}
  

И это не работает. Я получаю сообщение об ошибке.

Теперь, вот дочерний класс после удаления наследования, и он работает!!!

 import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.*;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * @author christian.bongiorno
 *         Date: 10/3/11
 *         Time: 6:11 PM
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "BuddyCodes")
@XmlRootElement(name = "BuddyCodes")
public class BuddyCodes implements Xml {

    private Long accountId;

    private Date expirationDate;
    private Set<String> delegate;
    public BuddyCodes() {
        delegate = new HashSet<String>();
    }

    public BuddyCodes(Long accountId, Set<String> codes, Date expirationDate) {
        this.accountId = accountId;
        this.expirationDate = expirationDate;
        delegate = new HashSet<String>();

    }

    public BuddyCodes(Long accountId, Date expirationDate) {
        this.accountId = accountId;
        this.expirationDate = expirationDate;
        delegate = new HashSet<String>();
    }

    @Override
    public String toXml() {
        String retVal;
        try {
            retVal = StringUtils.toXml(this);
        }
        catch (JAXBException e) {
            retVal = e.toString();
        }
        return retVal;

    }

    public Long getAccountId() {
        return accountId;
    }

    public void setAccountId(Long accountId) {
        this.accountId = accountId;
    }

    public Set<String> getCodes() {
        return delegate;
    }

    @XmlElement(name = "code")
    public void setCodes(Set<String> codes) {
        delegate = codes;
    }

    public Date getExpirationDate() {
        return expirationDate;
    }

    public void setExpirationDate(Date expirationDate) {
        this.expirationDate = expirationDate;
    }

    public boolean add(String s) {
        return delegate.add(s);
    }

    public int size() {
        return delegate.size();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        BuddyCodes that = (BuddyCodes) o;

        if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) return false;
        if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) return false;
        if (expirationDate != null ? !expirationDate.equals(that.expirationDate) : that.expirationDate != null)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = accountId != null ? accountId.hashCode() : 0;
        result = 31 * result   (expirationDate != null ? expirationDate.hashCode() : 0);
        result = 31 * result   (delegate != null ? delegate.hashCode() : 0);
        return resu<
    }


}
  

Почему наследование вообще имеет значение???

Я не понял этого, но у меня есть другой DTO в аналогичном макете (BuddyTypes BuddyType). BuddyType имеет 2 члена: Long и String . Оба помечены как XmlElement . Это работает просто отлично.

Кажется, проблема в том, что члены набора, составляющие делегат, не аннотируются в моем проблемном случае, и я не знаю, как аннотировать родительский элемент. В качестве унаследованного класса не имело бы смысла иметь какое-то имя / аннотацию по умолчанию. Но я попробовал это безумие, и аннотация игнорируется — я видел, что аннотации родительских членов игнорировались раньше, так что это не ново.

Я не знаю, возможно ли это, но мне нужно аннотировать родительский элемент.

Комментарии:

1. Вы видели XmlElementWrapper аннотацию? Если я правильно понимаю ваши требования, это был бы гораздо более простой способ добавить элемент множественной оболочки.

2. Я видел это, но все, что я когда-либо видел, это «BlahBlahWrapper», когда он используется. Что это мне дает? Я изучу это

Ответ №1:

Немного нестандартно: попробуйте простую библиотеку XML вместо JAXB. Мой опыт работы с этим — самый лучший.