JAXB-Eclipselink: отображение абстрактного "получателя" в XML
Я использую реализацию 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 - но я не хочу аннотации в моем коде).
Застряв в свойствах типа PROPERTY для класса B, моя следующая попытка была:
<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 ответ
Примечание. Я являюсь лидером EclipseLink JAXB (MOXy) и являюсь членом группы экспертов JAXB 2 (JSR-222).
Вы, кажется, попали в ошибку. Вы можете отслеживать наши успехи в этом вопросе по следующей ссылке. Я предоставил дополнительную информацию по этому вопросу ниже:
Использование аннотаций
Если вы собираетесь отобразить этот вариант использования с аннотациями JAXB/MOXy, вы можете установить@XmlAccessorType(XmlAccessType.NONE)
наA
класс и сделать что-то вроде:
package forum8727402;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.NONE)
public abstract class A {
public abstract String getX();
}
В
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>
демонстрация
Код ниже демонстрирует, как ссылаться на файл сопоставления:
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>