Поиск по этому блогу

пятница, 31 января 2014 г.

Предотвращение маршализации xml элементов в поля, имеющие тип JAXBElement

    Сегодня, при реализации клиента сервиса, столкнулся со следующей проблемой: в сгенерированном коде некоторые поля имели тип JAXBElement<T>. Работать с такими полями не очень удобно, поэтому я решил разобраться почему же так происходит. К счастью, решение было найдено достаточно быстро.

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

  • Существет некая группа ЯПов, куда входит например C#, которая использует класс DataContractSerialize для генерации XML-схем. Некоторые конструкции из этих схем, в свою очередь, могут приводить к появлению полей с типом JAXBElement в сгенерированном java коде. 
  • В XML-схеме содержатся такие элементы, как замещающие группы(substitution groups) или элементы, являющиеся обнуляемыми (nillable="true") и необязательными (minOccurs="0"), одновременно. Они то потом и имеют тип JAXBElement
    Давайте рассмотрим пример элемента с аттрибутами (minOccurs="0") and nillable (nillable="true"): 
<!-- XML schema fragment
<xs:element name="person" type="Person"
<xs:complexType name="Person">
  <xs:sequence>
    <xs:element name="name" type="xs:string"
        nillable="true" minOccurs="0"/>
  </xs:sequence>
</xs:complexType>

    Для этого элемента будет сгенерирован следующий код: 
// Binding
public class Person {
  JAXBElement<String> getName() {...};
  public void setName(JAXBElement<String> value) {...}
}
     Здесь мы видим тип JAXBElement, от которого нам и предстоит избавиться. Для этого создадим файл свойств properties.jaxb и установим в нем свойство generateElementProperty = false. 

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
  xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">

  <jaxb:globalBindings>
      <xjc:generateElementProperty>false</xjc:generateElementProperty>
  </jaxb:globalBindings>
</jaxb:bindings>

   Теперь остается только запустить команду wsimport и скормить ей наш wsdl и properties.jaxb: 

wsimport -keep ~/Desktop/srvCardsExport.wsdl -b properties.jaxb -Xnocompile

    В результате мы увидим что для того же элемента, наш java код будет уже другим:
// set JAXB customization generateElementProperty="false"/>
public class Person {
  String getName() {...}
  public void setName(String value) {...}
}
    Такое связвыние является более привычным для разработчиков, но при этом теряется обратная совместимость.

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

Отправить комментарий