4

I'm generating Java classes (and then packaging a jar based on them) from wsdl/xsd files, using Maven's cxf-codegen-plugin. I chose this plugin over other options because it allows me to "dynamically" reference all wsdl and xsd files in a folder instead of "statically" writing them down one by one in <wsdl/> tags.

The FurtherExtensionOfBaseObj Java class (defined in the internet.xsd file) is implemented by both MyBarRequest (from bar.wsdl) and MyZedRequest (from zed.wsdl) but in its @XmlSeeAlso annotation only MyBarRequest.class is referenced.

It's as if the plugin only considered what he finds in the first wsdl processed (alphabetically ordered) and nothing else. How I can I get the plugin (or any other plugin, although I like this one) to reference all extending classes in the @XmlSeeAlso annotation?

You can pull a working project reproducing exactly this issue at https://gitlab.com/t.meledina/xmlseealso-issue-poc

EDIT: the issue is now solved, the repository is now a working example of Tomas' solution below.

Alternatively, the following list of files can be used in order to reproduce the issue, the common.xsd should be irrelevant but it's needed in order to compile.

common.xsd file

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema targetNamespace="http://www.somehost.com/common/beans" xmlns:beans="http://www.somehost.com/common/beans" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:complexType name="SomeCommonObj">
        <xsd:sequence>
            <xsd:element name="woop" type="xsd:int"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="ExtensionOfSomeCommonObj">
        <xsd:complexContent>
            <xsd:extension base="beans:SomeCommonObj">
                <xsd:sequence>
                    <xsd:element name="moreWoop" type="xsd:string"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    <xsd:complexType name="BaseRequest">
        <xsd:sequence>
            <xsd:element name="floop" type="xsd:int"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="BaseResponse">
        <xsd:sequence>
            <xsd:element name="scoop" type="xsd:int"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="AnotherCommonObj">
        <xsd:annotation>
            <xsd:documentation>whatever</xsd:documentation>
        </xsd:annotation>
        <xsd:sequence/>
    </xsd:complexType>
    <xsd:complexType name="ExtensionOfAnotherCommonObj">
        <xsd:annotation>
            <xsd:documentation>son of whatever</xsd:documentation>
        </xsd:annotation>
        <xsd:complexContent>
            <xsd:extension base="beans:AnotherCommonObj">
                <xsd:sequence>
                    <xsd:element minOccurs="1" name="goop" type="xsd:int"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    <xsd:complexType name="BarObj">
        <xsd:sequence>
            <xsd:element name="noop" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

internet.xsd file

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema targetNamespace="http://www.somehost.com/internet/beans" xmlns:tns="http://www.somehost.com/internet/beans" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:import namespace="http://www.somehost.com/common/beans" schemaLocation="common.xsd"/>
    <xsd:complexType name="BaseObj">
        <xsd:sequence>
            <xsd:element name="zeep" type="xsd:int"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="ExtensionOfBaseObj">
        <xsd:complexContent>
            <xsd:extension base="tns:BaseObj">
                <xsd:sequence>
                    <xsd:element name="moreZeep" type="xsd:int"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    <xsd:complexType name="SomeOtherObj">
        <xsd:sequence>
            <xsd:element name="neep" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="YetSomeOtherObj">
        <xsd:sequence>
            <xsd:element name="geep" type="xsd:dateTime"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="FurtherExtensionOfBaseObj">
        <xsd:complexContent>
            <xsd:extension base="tns:ExtensionOfBaseObj">
                <xsd:sequence>
                    <xsd:element name="evenMoreZeep" type="xsd:string"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>

bar.wsdl file

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="bar" targetNamespace="http://www.somehost.com/internet/bar/" xmlns:beans="http://www.somehost.com/internet/bar/beans/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://www.somehost.com/internet/bar/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <wsdl:types>
        <xsd:schema jaxb:version="2.0" targetNamespace="http://www.somehost.com/internet/bar/beans/" xmlns:common="http://www.somehost.com/common/beans" xmlns:internet="http://www.somehost.com/internet/beans" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
            <xsd:import namespace="http://www.somehost.com/common/beans" schemaLocation="common.xsd"/>
            <xsd:import namespace="http://www.somehost.com/internet/beans" schemaLocation="internet.xsd"/>
            <xsd:annotation>
                <xsd:appinfo>
                    <jaxb:globalBindings>
                        <jaxb:javaType name="java.util.Calendar" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime" xmlType="xsd:dateTime"/>
                    </jaxb:globalBindings>
                </xsd:appinfo>
            </xsd:annotation>
            <xsd:complexType name="myBarRequest">
                <xsd:complexContent>
                    <xsd:extension base="internet:FurtherExtensionOfBaseObj">
                        <xsd:sequence>
                            <xsd:element minOccurs="0" name="barObjAttuale" type="common:BarObj"/>
                            <xsd:element name="barObjNuovo" type="common:BarObj"/>
                        </xsd:sequence>
                    </xsd:extension>
                </xsd:complexContent>
            </xsd:complexType>
            <xsd:element name="myBarRequestElement" type="beans:myBarRequest"/>
            <xsd:complexType name="myBarResponse">
                <xsd:complexContent>
                    <xsd:extension base="common:BaseResponse">
                        <xsd:sequence minOccurs="0">
                            <xsd:element name="barObj" type="common:BarObj"/>
                        </xsd:sequence>
                    </xsd:extension>
                </xsd:complexContent>
            </xsd:complexType>
            <xsd:element name="myBarResponseElement" type="beans:myBarResponse"/>
        </xsd:schema>
    </wsdl:types>
    <wsdl:message name="myBarRequest">
        <wsdl:part element="beans:myBarRequestElement" name="parameters"/>
    </wsdl:message>
    <wsdl:message name="myBarResponse">
        <wsdl:part element="beans:myBarResponseElement" name="parameters"/>
    </wsdl:message>
    <wsdl:portType name="barPortType">
        <wsdl:operation name="myBar">
            <wsdl:input message="tns:myBarRequest"/>
            <wsdl:output message="tns:myBarResponse"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="barBinding" type="tns:barPortType">
        <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="myBar">
            <wsdl:input>
                <soap12:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap12:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="barService">
        <wsdl:port binding="tns:barBinding" name="barPort">
            <soap12:address location="http://localhost:9080/internet/barService"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

zed.wsdl file

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="zedService" targetNamespace="http://www.somehost.com/internet/zed/" xmlns:beans="http://www.somehost.com/internet/zed/beans/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://www.somehost.com/internet/zed/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <wsdl:types>
        <xsd:schema jaxb:version="2.0" targetNamespace="http://www.somehost.com/internet/zed/beans/" xmlns:common="http://www.somehost.com/common/beans" xmlns:internet="http://www.somehost.com/internet/beans" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
            <xsd:import namespace="http://www.somehost.com/common/beans" schemaLocation="common.xsd"/>
            <xsd:import namespace="http://www.somehost.com/internet/beans" schemaLocation="internet.xsd"/>
            <xsd:annotation>
                <xsd:appinfo>
                    <jaxb:globalBindings>
                        <jaxb:javaType name="java.util.Calendar" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime" xmlType="xsd:dateTime"/>
                    </jaxb:globalBindings>
                </xsd:appinfo>
            </xsd:annotation>
            <xsd:complexType name="myZedRequest">
                <xsd:complexContent>
                    <xsd:extension base="internet:FurtherExtensionOfBaseObj">
                        <xsd:sequence>
                            <xsd:element minOccurs="1" name="blaap" type="xsd:long"/>
                        </xsd:sequence>
                    </xsd:extension>
                </xsd:complexContent>
            </xsd:complexType>
            <xsd:element name="myZedRequestElement" type="beans:myZedRequest"/>
            <xsd:complexType name="myZedResponse">
                <xsd:complexContent>
                    <xsd:extension base="common:BaseResponse">
                        <xsd:sequence minOccurs="0"/>
                    </xsd:extension>
                </xsd:complexContent>
            </xsd:complexType>
            <xsd:element name="myZedResponseElement" type="beans:myZedResponse"/>
        </xsd:schema>
    </wsdl:types>
    <wsdl:message name="myZedRequest">
        <wsdl:part element="beans:myZedRequestElement" name="parameters"/>
    </wsdl:message>
    <wsdl:message name="myZedResponse">
        <wsdl:part element="beans:myZedResponseElement" name="parameters"/>
    </wsdl:message>
    <wsdl:portType name="zedPortType">
        <wsdl:operation name="myZed">
            <wsdl:input message="tns:myZedRequest"/>
            <wsdl:output message="tns:myZedResponse"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="zedBinding" type="tns:zedPortType">
        <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="myZed">
            <wsdl:input>
                <soap12:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap12:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="zedService">
        <wsdl:port binding="tns:zedBinding" name="zedPort">
            <soap12:address location="http://localhost:9080/internet/zedService"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

pom.xml file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mytest.mobile</groupId>
    <artifactId>mytest-jax-ws</artifactId>
    <version>20190707-1950</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>3.1.17</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <wsdlRoot>src/main/resources/wsdl</wsdlRoot>
                            <includes>
                                <include>*.wsdl</include>
                            </includes>
                        </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.4.1</version>
                <executions>
                    <execution>
                        <id>auto-clean</id>
                        <phase>initialize</phase>
                        <goals>
                            <goal>clean</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-codegen-plugin</artifactId>
            <version>3.2.7</version>
        </dependency>
    </dependencies>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
</project>

Thank you in advance for any help.

Tom
  • 92
  • 13

3 Answers3

3

I have explicitly overwritten generated classes from WSDL generation by XSD generation with proper annotations. Please add whole text to pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.test</groupId>
    <artifactId>my-jax-ws</artifactId>
    <version>20190707-1950</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>3.1.17</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <wsdlRoot>src/main/resources/wsdl</wsdlRoot>
                            <includes>
                                <include>*.wsdl</include>
                            </includes>
                         </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-xjc-plugin</artifactId>
                <version>3.3.1</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <sourceRoot>${basedir}/target/generated-sources/cxf</sourceRoot>
                            <xsdOptions>
                                <xsdOption>
                                    <xsd>src/main/resources/wsdl/internet.xsd</xsd>
                                    <bindingFiles>
                                        <bindingFile>src/main/resources/bindings.xjb</bindingFile>
                                    </bindingFiles>
                                    <extension>true</extension>
                                    <extensionArgs>
                                        <extensionArg>-Xannotate</extensionArg>
                                    </extensionArgs>
                                </xsdOption>
                            </xsdOptions>
                        </configuration>
                        <goals>
                            <goal>xsdtojava</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.jvnet.jaxb2_commons</groupId>
                        <artifactId>jaxb2-basics</artifactId>
                        <version>1.11.1</version>
                    </dependency>
                    <dependency>
                        <groupId>org.jvnet.jaxb2_commons</groupId>
                        <artifactId>jaxb2-basics-annotate</artifactId>
                        <version>1.0.2</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.4.1</version>
                <executions>
                    <execution>
                        <id>auto-clean</id>
                        <phase>initialize</phase>
                        <goals>
                            <goal>clean</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-codegen-plugin</artifactId>
            <version>3.2.7</version>
        </dependency>
    </dependencies>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
</project>

And create bindings.xjb file in folder: xmlseealso-issue-poc\src\main\resources with following code:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:annox="http://annox.dev.java.net" 
               xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
               version="2.1">

        <jaxb:bindings schemaLocation="wsdl\internet.xsd" node="/xsd:schema">
        <jaxb:bindings node="xsd:complexType[@name='FurtherExtensionOfBaseObj']">
                <annox:annotate target="class">
                    @javax.xml.bind.annotation.XmlSeeAlso({com.somehost.internet.zed.beans.MyZedRequest.class, com.somehost.internet.bar.beans.MyBarRequest.class})
                </annox:annotate>
        </jaxb:bindings>
    </jaxb:bindings>


</jaxb:bindings>

I hope it helps.

Tomas
  • 46
  • 4
  • This is 100% what I was looking for, works like a charm EXCEPT for the fact that I had to replace the backslash you used in bindings.xjb when giving the schemaLocation ("wsdl\internet.xsd") with a regular slash "wsdl/internet.xsd". – Tom Mar 21 '20 at 13:32
0

In order to be able to use the WSDL-root option of cxf-codegen-plugin, you must provide the JAXB bindings file too (cf. the documentation of the plugin). The bindings XML may be generated too, refer to this SO answer.

D. Kovács
  • 1,232
  • 13
  • 25
  • Thank you for answering. Can you please clarify what you mean by "In order to be able to use the WSDL-root option of cxf-codegen-plugin, you must provide the JAXB bindings file too"? The option kinda works already (i.e. it does build the .java and .class files). I also can't find a way to "generate" the bindings file (I guess you meant through the plugin) from the answer you linked, it looks more like a couple of hints about how to write it down. Perhaps could you sketch out a bindings file complementing the sample files I referenced up here? – Tom Jul 15 '19 at 12:03
0

I have recently faced a problem, I wanted to add annotation @XmlSeeAlso to generated class from WSDL file, below please find example of code. This might help you:

pom.xml

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>3.0.9</version>
    <executions>
        <execution>
            <id>generate-sources-referencedata</id>
            <phase>generate-sources</phase>
            <configuration>
                <sourceRoot>${project.build.directory}/generated-sources/cxf</sourceRoot>
                <defaultOptions>
                    <frontEnd>jaxws21</frontEnd>
                    <faultSerialVersionUID>1</faultSerialVersionUID>
                    <noAddressBinding>true</noAddressBinding>
                </defaultOptions>
                <wsdlOptions>
                    <wsdlOption>
                        <wsdlLocation>classpath:ReferenceDataService.wsdl</wsdlLocation>
                        <wsdl>src/main/resources/ReferenceDataService.wsdl</wsdl>
                        <bindingFiles>
                            <bindingFile>src/main/resources/bindings.xjb</bindingFile> 
                        </bindingFiles>
                        <extraargs>
                            <extraarg>-xjc-Xannotate</extraarg>
                        </extraargs>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>org.jvnet.jaxb2_commons</groupId>
            <artifactId>jaxb2-basics</artifactId>
            <version>1.11.1</version>
        </dependency>
        <dependency>
            <groupId>org.jvnet.jaxb2_commons</groupId>
            <artifactId>jaxb2-basics-annotate</artifactId>
            <version>1.0.2</version>
        </dependency>
    </dependencies>
</plugin>

bindings.xjb [external config file]

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxws:bindings
        xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        xmlns:annox="http://annox.dev.java.net"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        jaxb:extensionBindingPrefixes="annox">

    <jaxws:bindings schemaLocation="ReferenceDataService.wsdl">
        <jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema">
            <jaxb:bindings node="xs:complexType[@name='ReferenceDataRequestCType']">
                <annox:annotate target="class">
                    @javax.xml.bind.annotation.XmlSeeAlso({com.project.BindingClass.class})
                </annox:annotate>
            </jaxb:bindings>
        </jaxws:bindings>
    </jaxws:bindings>
</jaxws:bindings>
Tomas
  • 46
  • 4
  • Thank you very much for the sample. Unfortunately I can't seem to make it work (after changing names na dNS to match my project obviously) i.e. the execution is carried out with no errors but the missing class within the annotation is still missing. Would you perhaps be able to make it work in the sample project I provided? Thank you very much either way. – Tom Mar 08 '20 at 18:10
  • I could not preform push to your project, so I will write another answer here. – Tomas Mar 21 '20 at 13:07