JAXB-Eclipselink: XmlRootElement и наследование

Используя Eclipselink/MOXy 2.3, у меня есть следующий вариант использования при маршаллинге в XML:

abstract class MyAbstract {
}

class MyImpl extends MyAbstract {
}

class A {

    private MyAbstract myAbstract;

    // MyImpl is behind this
    public MyAbstract getMyAbstract() {
        return myAbstract;
    }

}

У меня есть следующее сопоставление, определенное в oxm.xml:

<java-type name="foo.MyAbstract" xml-accessor-type="NONE">
    <xml-see-also>
        foo.MyImpl
    </xml-see-also>
</java-type>

<java-type name="foo.MyImpl">
    <xml-root-element name="MyImpl" />
</java-type>

<java-type name="bar.A" xml-accessor-type="NONE">
    <xml-root-element name="A" />
    <java-attributes>
        <xml-element java-attribute="myAbstract" type="foo.MyAbstract" />
    </java-attributes>
</java-type>

Теперь это приводит к:

<A>
    <myAbstract xsi:type="myImpl">
        <!-- Mapped members of MyImpl + MyAbstract -->
    </myAbstract>
</A>

Поскольку мне не нужно имя свойства в экспортированном xml, я изменил:

<java-type name="bar.A" xml-accessor-type="NONE">
    <xml-root-element name="A" />
    <java-attributes>
        <xml-element java-attribute="myAbstract" type="foo.MyAbstract" xml-path="."/>
    </java-attributes>
</java-type>

что привело к:

<A>
    <!-- Members of MyImpl + MyAbstract marshalled without any wrapping element-->
</A>

Я хочу:

 <A>
    <MyImpl>
        <!-- Members of MyImpl + MyAbstract -->
    </MyImpl>
 </A>

Вопрос: как мне этого добиться? MOXy просто игнорирует мой XmlRootElement на MyImpl...

ИЗМЕНИТЬ:

Попытка того, что предложил Блейз, дает мне следующее исключение:

Exception [EclipseLink-60] (Eclipse Persistence Services - 2.3.2.v20111125-r10461):   
org.eclipse.persistence.exceptions.DescriptorException
The method [] or [getMyAbstract] is not defined in the object [bar.A].

Теперь для этого нужна дополнительная информация, которую я пропустил раньше, потому что я думал, что это не имеет значения:

Класс A — это интерфейс, который определяет: public X getMyAbstract(); MyAbstract реализует X (именно поэтому я добавил атрибут type в отображение для интерфейса A).

Таким образом, использование xml-element-ref MOXy больше не "видит" геттер, а использование xml-element видит.


person quaylar    schedule 13.01.2012    source источник
comment
Класс А - это интерфейс? Какова конкретная реализация A, которую вы отображаете в XML?   -  person bdoughan    schedule 16.01.2012
comment
@BlaiseDoughan: у меня нет сопоставления для конкретного класса - только одно для панели интерфейса. Поскольку я передаю только интерфейс, я подумал, что достаточно просто иметь сопоставление для интерфейса? Я следовал первому примеру в blog.bdoughan.com/ 2011/05/.   -  person quaylar    schedule 16.01.2012
comment
В этом примере предполагается, что интерфейс A соответствует интерфейсу Customer в моем примере, вам все равно нужно будет выполнить загрузку и сопоставить JAXBContext с классом impl, CustomerImpl в моем примере.   -  person bdoughan    schedule 16.01.2012
comment
@BlaiseDoughan - Достаточно ли добавить запись в oxm.xml для моего класса Impl и загрузить JAXBContext с помощью Map, содержащей записи package-name -> oxm.xml? Вот как я загружаю его сейчас - мне просто не хватает записи для класса Impl. И как должна выглядеть эта запись? Я уже сопоставил все для интерфейса..?   -  person quaylar    schedule 16.01.2012
comment
Просто замените сопоставление для интерфейса сопоставлением для класса impl.   -  person bdoughan    schedule 16.01.2012
comment
@BlaiseDoughan - мне все еще не нужно отображение для интерфейса, а также тег xml-see-also? Как иначе MOXy узнает, как маршалировать класс Impl, если я передам интерфейс методу маршала?   -  person quaylar    schedule 16.01.2012
comment
давайте продолжим это обсуждение в чате   -  person quaylar    schedule 16.01.2012
comment
@BlaiseDoughan - ‹xml-element-ref›, очевидно, правильный путь, я обнаружил другие проблемы, которые теперь заставили меня напрямую маршалировать MyAbstract (получать его и маршалировать ()), вместо маршалинга класса A. Тем не менее, ваше решение будет сработало и пригодится в следующий раз, когда мне это понадобится ..   -  person quaylar    schedule 16.01.2012
comment
Я открыл и исправил следующую ошибку на основе нашего чата: bugs.eclipse.org/368746. Вы можете опробовать исправление, загрузив ночную сборку 2.3.3 по следующему адресу: eclipse .org/eclipselink/downloads/nightly.php   -  person bdoughan    schedule 17.01.2012


Ответы (1)


Сопоставление, которое вы ищете, это @XmlElementRef. Это соответствует концепции групп замещения в схеме XML.

bar/oxm.xml

Ниже приведен внешний документ сопоставления для пакета bar. Обратите внимание, как свойство myAbstract сопоставляется с xml-element-ref, которое является XML-представлением @XmlElementRef.

<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="bar">
    <java-types>
        <java-type name="A" xml-accessor-type="NONE">
            <xml-root-element name="A" />
            <java-attributes>
                <xml-element-ref java-attribute="myAbstract"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

foo/oxm.xml

Ниже приведен внешний файл метаданных для пакета foo:

<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="foo">
    <java-types>
        <java-type name="MyAbstract" xml-accessor-type="NONE">
            <xml-see-also>
                foo.MyImpl
            </xml-see-also>
        </java-type>
        <java-type name="MyImpl">
            <xml-root-element name="MyImpl" />
        </java-type>
    </java-types>
</xml-bindings>

Демо

Ниже приведен демонстрационный код для этого примера:

package forum8853855;

import java.util.*;
import javax.xml.bind.*;    
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import bar.A;
import foo.MyImpl;

public class Demo {

    public static void main(String[] args) throws Exception {
        List<String> oxm = new ArrayList<String>(2);
        oxm.add("foo/oxm.xml");
        oxm.add("bar/oxm.xml");

        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, oxm);

        JAXBContext jc = JAXBContext.newInstance(new Class[] {A.class}, properties);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        A a = new A();
        a.setMyAbstract(new MyImpl());
        marshaller.marshal(a, System.out);
    }

}

Вывод

<?xml version="1.0" encoding="UTF-8"?>
<A>
   <MyImpl/>
</A>

Для получения дополнительной информации

person bdoughan    schedule 13.01.2012
comment
Спасибо за поддержку тега MOXy ;) - person dma_k; 14.01.2012
comment
Спасибо, Блейз, за ​​подсказку, на самом деле я уже пробовал это, прежде чем публиковать (согласно вашему сообщению в блоге по этой теме), но во время сортировки произошло исключение. Я отредактирую свой пост выше с некоторой дополнительной информацией. - person quaylar; 16.01.2012
comment
@quaylar - Можете ли вы включить в свое обновление исключение, которое вы видите? - person bdoughan; 16.01.2012