Cxf Wsdl2java пустая запись в списке исчезнет
Я создал клиент веб- сервиса с cxf с плагином xew для распаковки списка
Проблема в том, что null
в списке исчезают. Например:
У меня есть запрос с List<String>
со строками и null
-Посещение
Когда запрос теперь поступает на сервер, он содержит только строки, а не null
запись. Таким образом, в списке примеров только 2 записи.
Вот пример wsdl:
[..]
<!-- the request -->
<xsd:element name="createGroup">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="in0" nillable="true" type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="in1" nillable="true" type="ns2:ArrayOfRole"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
[..]
<!-- the list which will be unwrapped -->
<xsd:complexType name="ArrayOfRole">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="Role" nillable="true" type="xsd:String"/>
</xsd:sequence>
</xsd:complexType>
Я использую Maven для создания клиента WS
<properties>
<cxf.version>3.0.5</cxf.version>
<jaxbBasic.version>0.6.5</jaxbBasic.version>
</properties>
[..]
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>src/main/java</sourceRoot>
<defaultOptions>
<bindingFiles>
<bindingFile>${basedir}/jaxbBindings.xml</bindingFile>
<bindingFile>${basedir}/jaxwsBindings.xml</bindingFile>
</bindingFiles>
<extraargs>
<!-- xew plugin for unwrapping list wrappers types NOTE: the args need to be over the others otherwise there are compilation errors -->
<extraarg>-xjc-Xxew</extraarg>
<extraarg>-xjc-Xxew:instantiate lazy</extraarg>
<!-- Generate toString, equals, hashcode methods -->
<extraarg>-xjc-Xts:style:de.company.tostring.CustomToStringStyle.DEFAULT</extraarg>
<extraarg>-xjc-Xequals</extraarg>
<extraarg>-xjc-XhashCode</extraarg>
</extraargs>
</defaultOptions>
<wsdlRoot>${ws.dirAbsolute}</wsdlRoot>
<includes>
<include>*.wsdl</include>
</includes>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.cxf.xjcplugins</groupId>
<artifactId>cxf-xjc-ts</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>${jaxbBasic.version}</version>
</dependency>
<dependency>
<groupId>com.github.jaxb-xew-plugin</groupId>
<artifactId>jaxb-xew-plugin-fixed</artifactId> <!-- this is a custom version with a small modification see https://github.com/dmak/jaxb-xew-plugin/issues/44 -->
<version>1.7-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-xjc</artifactId>
<version>2.2.11</version>
</dependency>
</dependencies>
</plugin>
jaxbBindings.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings version="2.1" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
<jaxb:globalBindings generateElementProperty="false"/>
</jaxb:bindings>
jaxwsBindings.xml
<jaxws:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
<jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
</jaxws:bindings>
Пример запроса:
final CreateGroup create = new CreateGroup();
create.setIn0("newgroup");
final List<String> roles = new ArrayList<String>();
roles.add("testrole");
roles.add(null);
roles.add("testrole2");
create.setIn1(roles);
final SamplePortType proxy = ..;
proxy.createGroup(create);
Есть ли способ, которым null
запись все еще будет присутствовать на стороне сервера?
2 ответа
Проблема в том, что jaxb-xew-plugin
генерирует код, который пропускает nillable = true
для XmlElement
списка.
Генерируется плагином:
@XmlElementWrapper(required = true, nillable = true)
@XmlElement(name = "Role", namespace = "http://www.stackru.com/example")
protected List<String> in1;
Если вы попробуете, с добавленным nillable=true
, это будет работать:
@XmlElementWrapper(required = true, nillable = true)
@XmlElement(name = "Role", namespace = "http://www.stackru.com/example", nillable = true)
protected List<String> in1;
Так что, похоже, плагин не хватает nillable
атрибут для обернутых значений.
Я думаю, что проблема заключается в этой части кода, где XmlElement "поднимается" к внешнему элементу и nillable
атрибут не указан
Добавление следующего фрагмента кода в упомянутую часть кода решит вашу проблему и создаст рабочий код:
JExpression nillable = getAnnotationMemberExpression(xmlElementOriginalAnnotation, "nillable");
if (nillable != null) {
xmlElementAnnotation.param("nillable", nillable);
}
Проблема, обсуждаемая в этом вопросе, решена начиная с версии 1.7 jaxb-xew-plugin. Эта проблема отслеживает этот случай, вот релизы.
Я не уверен в этом, но может ли быть так, что generateElementProperty
в привязках JAXB может быть причиной проблемы? Согласно документации, если для этого свойства установлено значение false, JAXB не сможет обойти все XML-документы. Если установлено значение true, вам придется иметь дело с JAXBElement
класс, но, как говорится в документации:
Тип JAXBElement обходит XML-представление элемента name по операции unmarshal/marshal.
Проверьте примеры на этой странице, это может помочь.