JAXB-Eclipselink: отображение абстрактного «получателя» в XML - PullRequest
2 голосов
/ 04 января 2012

Я использую реализацию EclipseLink (2.3) JAXB для отображения POJO в XML и столкнулся с проблемой следующего сценария использования:

public abstract class A {

    public abstract Set<X> getX();
    // There is no setter
}


public class B extends A {

    // Set via constructor
    private Set<X> x;

    @Override
    public Set<X> getX();

}

Я полностью определяю само отображение во внешнем файле привязок, я устанавливаю класс A так, чтобы он был временным:

<java-type name="foo.A" xml-transient="true"/>

и для класса B:

<java-type name="bar.B" xml-accessor-type="PROPERTY">
    <xml-root-element name="B" />
    <java-attributes>
        <xml-element java-attribute="x" xml-path="..."/>
    </java-attributes>
</java-type>

Теперь при сортировке я получаю исключение: «Дубликат свойства с именем [x] найден в классе [bar.B]» который, по моему мнению, исходит из абстрактного объявления в A, наследуемого B.

Установка типа доступа для B на FIELD избавляет от этой ошибки, к сожалению, это не вариант, потому что у меня есть дополнительное свойство в B для маршала, которое не возвращает поле, но вычисленное значение, поэтому я застрял с PROPERTY (следующие работы: установка accessor-type для B на FIELD и сопоставление дополнительного свойства с аннотацией @XmlPath - но я не хочу аннотации в моем коде).

Застряв в объектах типа B со свойством PROPERTY, моя следующая попытка была:

<java-type name="foo.A" xml-accessor-type="NONE"/>

для предотвращения наследования абстрактного свойства B, что дает мне:

Ignoring attribute [x] on class [bar.B] as no Property was generated for it.

То же самое происходит с использованием этого сопоставления:

<java-type name="foo.A" xml-accessor-type="PROPERTY">
    <java-attributes>
        <xml-transient java-attribute="x"/>
    </java-attributes>
</java-type>

В обоих случаях свойство 'x' игнорируется.

Я действительно потратил довольно много времени на это сейчас - я не могу себе представить, что это невозможно заставить это работать ??

Мой обходной путь на данный момент:

Оставляя foo.A кратковременным, определяя тип поля доступа FIELD для bar.B (который без проблем получает свойство 'x') и отображая дополнительное свойство в B с помощью аннотации в коде. Но, как упоминалось ранее: я хотел бы решить это полностью без аннотаций - кто-нибудь есть идеи? Блейз? :)

С уважением,

- Qu

1 Ответ

1 голос
/ 04 января 2012

Примечание: Я EclipseLink JAXB (MOXy) и являюсь членом JAXB 2 (JSR-222) экспертная группа.

Похоже, вы столкнулись с ошибкой.Вы можете отслеживать наш прогресс в этом вопросе по следующей ссылке.Я предоставил дополнительную информацию по этому вопросу ниже:

Использование аннотаций

Если вы собираетесь отобразить этот вариант использования с аннотациями JAXB / MOXy, вы можете установить @XmlAccessorType(XmlAccessType.NONE) в классе A и сделать что-то вроде:

A

package forum8727402;

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.NONE)
public abstract class A {

    public abstract String getX();

}

B

package forum8727402;

import javax.xml.bind.annotation.*;    
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement
public class B extends A {

    @XmlPath("a/b/c/text()")
    private String x;

    public B() {
        x = "Hello World";
    }

    @Override
    public String getX() {
        return x;
    }

    @XmlElement
    public String getCalculatedValue() {
        return "Calculated Value";
    }

}

Демо

package forum8727402;

import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(B.class);

        B b = new B();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(b, System.out);
    }

}

Выход

<?xml version="1.0" encoding="UTF-8"?>
<b>
   <a>
      <b>
         <c>Hello World</c>
      </b>
   </a>
   <calculatedValue>Calculated Value</calculatedValue>
</b>

Использование внешнего файла сопоставления MOXy

oxm.xml

Ниже приведено внешнее сопоставление MOXyфайл , представляющий эквивалент ранее показанных аннотаций:

<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="forum8727402">
    <java-types>
        <java-type name="A" xml-accessor-type="NONE"/>
        <java-type name="B">
            <xml-root-element/>
            <java-attributes>
                <xml-element java-attribute="x" xml-path="a/b/c/text()"/>
                <xml-element java-attribute="calculatedValue"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Demo

Приведенный ниже код демонстрирует, как ссылаться нафайл сопоставления:

package forum8727402;

import java.util.*;
import javax.xml.bind.*;    
import org.eclipse.persistence.jaxb.JAXBContextFactory;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum8727402/oxm.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {A.class, B.class}, properties);

        B b = new B();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(b, System.out);
    }

}

Выход

[EL Warning]: 2012-01-04 14:45:46.366--Ignoring attribute [x] on class [forum8727402.xml.B] as no Property was generated for it.
<?xml version="1.0" encoding="UTF-8"?>
<b>
   <calculatedValue>Calculated Value</calculatedValue>
</b>
...