JAXB всегда расширение маршала - невозможно получить элементы только супертипа
Я застрял в проблеме с JAXB / Spring Web Services. Ниже приведено подробное описание. Я ценю любое предложение, которое может помочь мне решить его. Я могу предоставить больше, если детали, если это необходимо.
Я пишу веб-сервис, который возвращает список некоторых объектов. Spring WS - это среда контракта, поэтому я начал с XSD, подобного следующему:
<element name="GetEntitiesRequest" type="Something"/>
<element name="GetEntitiesResponse" type="Entities"/>
<complexType name="Entities">
<sequence>
<element name="Entity" type="Entity" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="Entity">
<sequence>
(...)
</sequence>
</complexType>
Это работало хорошо. Однако тип "сущность" начинает расти (там много элементов), что вызывает проблемы с производительностью (в ответе много сущностей). Поэтому я решил разделить "сущность" на две части
- Некоторая общая информация, которая будет возвращена в ответе группы - Entity
- Более подробная информация, которая будет возвращена в другой операции веб-службы, специфичной для объекта - EntityDetails
Поэтому после изменения схема выглядит следующим образом (EntityDetails наследуется от Entity):
<element name="GetEntitiesRequest" type="Something"/>
<element name="GetEntitiesResponse" type="Entities"/>
<complexType name="Entities">
<sequence>
<element name="Entity" type="Entity" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="Entity">
<sequence>
(...)
</sequence>
</complexType>
<element name="GetEntityDetailsRequest" type="SomethingMore"/>
<element name="GetEntityDetailsResponse" type="EntityDetails"/>
<complexType name="EntityDetails">
<complexContent>
<extension base="Entity">
<sequence>
(...)
</sequence>
</extension>
</complexContent>
</complexType>
JAXB (точнее: hyperjaxb3) генерирует классы для Entity (стратегия наследования = JOINED), EntityDetails и Entities. Кроме того, он создает ObjectFactory с методом "createGetEntitiesResponse". Я использую этот метод для сортировки списка, полученного с помощью Hibernate из таблицы Entity.
Теоретически, я должен получить список "Entity" при отправке "GetEntitiesRequest". Однако вместо этого я получаю список "EntityDetails".
Если вы прочитаете эту форму в начале, вы можете представить, что это то, чего я хотел избежать.
Если вам нужно больше деталей, persistence.xml выглядит следующим образом:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence (...)>
<persistence-unit name="org.package">
<class>org.package.Entity</class>
<class>org.package.EntityDetails</class>
<class>org.package.Entities</class>
</persistence-unit>
</persistence>
Я использую Gradle для автоматизации сборки и его плагин jaxb для генерации классов:
jaxb
{
xsdDir = "src/main/webapp/schemas/messages"
bindingsDir = "src/main/webapp/schemas/bindings"
bindings = ["bindings.xjb"]
xjc
{
extension = true
taskClassname = "com.sun.tools.xjc.XJC2Task"
generatePackage = "org.package"
args = ["-Xannotate", "-Xhyperjaxb3-jpa2", "-Xequals", "-XhashCode", "-XtoString"]
}
}
в настоящее время, bindings.xjb, за пределами заголовка, содержит только:
<jaxb:globalBindings localScoping="toplevel">
<xjc:serializable/>
</jaxb:globalBindings>
1 ответ
Прежде всего, убедитесь, что вы получаете экземпляры Entity
из базы данных, НЕ EntityDetails
,
Попробуйте создать изолированный сценарий без базы данных. Просто создай свой экземпляр Entity
, заполните это чем-нибудь, создайте ответ и соберите это. Посмотри что получится. Вы изолируете проблему - либо вы получаете неправильные экземпляры из базы данных, либо сортировка не работает должным образом. И то, и другое сложно диагностировать, не видя ваш код. Попробуйте свести свою проблему к одной из двух, упомянутых мной выше.
Diclaimer: я автор Hyperjaxb3.