Подтвердить что ты не робот

Ошибка Cxf Wsdl2java в списке исчезает

Я создал клиент webservice с cxf с плагином xew для разворачивания списка

Проблема в том, что null в списке исчезает. Например:.

У меня есть запрос с List<String> со строками и null -entry

Когда запрос теперь поступает на сервер, он содержит только строки, а не запись 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 все еще присутствовала на сервере?

4b9b3361

Ответ 1

Проблема заключается в том, что jaxb-xew-plugin генерирует код, который пропускает nillable = true для XmlElement списка.

Сгенерировано плагином:

@XmlElementWrapper(required = true, nillable = true)
@XmlElement(name = "Role", namespace = "http://www.stackoverflow.com/example")
protected List<String> in1;

Если вы попытаетесь, добавив nillable=true, он будет работать:

@XmlElementWrapper(required = true, nillable = true)
@XmlElement(name = "Role", namespace = "http://www.stackoverflow.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. Эта проблема отслеживает этот случай, здесь - это выпуски.

Ответ 2

Я не уверен в этом, но может ли быть, что generateElementProperty в привязках JAXB может вызвать проблему? Согласно документации, если для этого свойства установлено значение false, JAXB не сможет обойти все XML-документы. Если установлено значение true, вам придется иметь дело с классом JAXBElement, но, как говорится в документации:

Тип JAXBElement обращается к XML-представлению элемента имени во время операции unmarshal/marshal.

Проверьте примеры на этой странице, это может помочь.