Using jaxws-maven-plugin with -clientjar option

2020-04-16 18:57发布

问题:

I'm using jaxws-maven-plugin to execute wsimport for a web service consumer app. I'm using the -clientjar option on wsimport which was introduced with JAX-WS 2.2.2 RI in 2010. I do this because I want to bundle the WSDL within the jar.

I don't have a problem crafting the pom. For plugin configuration I do something like:

<configuration>
    ...
    <args>
        <arg>-clientjar</arg>
        <arg>bundled-wsdl.jar</arg>
    </args>
</configuration>

When I execute a build my created jar, lets call it myapp.jar, has file bundled-wsdl.jar within it. Inside the bundled-wsdl.jar's META-INF directory I find the wsdl and xsd just as I like them. I'm also quite happy with the generated java code that come as a result of using the -clientjar option. So far so good.

But this stuff should be in myapp.jar's META-INF, right? The fact that it sits within bundled-wsdl.jar's META-INF doesn't help me a lot.

The funny thing is that I do in fact get a wsdl file in myapp.jar's META-INF which makes the application actually work. How it gets there I don't know. Also the xsd file isn't there, only in bundled-wsdl.jar's META-INF.

The basic question is how to correctly use wsimport -clientjar option in a Maven project ?

Java 1.7.0_45.

回答1:

The -clientjar option is really poorly documented, IMHO. Here's how I believe it works:

When the -clientjar <jarfile> option is used three things are happening:

  1. You'll get a <jarfile> generated in the directory pointed to by the -d argument to the wsimport tool. This will contain within it both WSDL and any relevant XSD files as well. This little bundle will not be used for anything at all. If you want to make use of it it would be entirely up to you. But before you do see (2) below. I'm not sure what to use this jarfile for other than as a form of documentation.
  2. You'll get a copy of the WSDL put into a file called META-INF/wsdl/<svcname>.wsdl. The generated classes will use this file in the no-arg proxy constructor. So this is what will actually be used if you request a bundled WSDL file with the -clientjar option.
  3. The generated code will change so that wsdlLocation, if you are using the default no-arg constructor on the @WebServiceClient class, will be that of the bundled WSDL (from (2)), rather than the remote WSDL. Indeed if you use -wsdllocation on your command line together with -clientjar then whatever you specify with -wsdllocation will have no effect as -clientjar will take precedence.

So we must focus on (2) and (3) because that's the only one being actually used ... at least if you use the generated code as-is.

It is interesting to note that the result of (2) is only a WSDL file. This file may have embedded links to XSD files but as far as I can tell such link will never be followed. The reason is that when we say a web service consumer needs the WSDL at runtime it really only needs the WSDL itself, at not the schema. The schema is "hardcoded" into the consumer and there's no way of changing it at runtime. Hence there's no reason to read schema information at runtime. (THIS IS FROM MY UNDERSTANDING)

Second thing to note about the WSDL that's included with (2): It is really just a copy of the original WSDL so it may not have endpoint you want. Actually in most cases it won't. This means that in this situation you'll need to set the endpoint yourself :

// Use no-arg constructor. Means it uses the WSDL bundled into the 
// META-INF/wsdl directory rather than trying to retrieve WSDL over the
// network.
service = new HelloSvc_Service();
hello = service.getHelloSvcPort();

// Since we're using a bundled WSDL the web service URL cannot 
// be derived from that (it would be wrong!). So we have to set
// it explicitly.
((BindingProvider) hello).getRequestContext().put(
                BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                "http://myhellowebservice-address");


回答2:

The documentation for this plugin is a joke. A workaround is to manually extract the contents from the client jar after it is created like follows:

<build>
    <plugins>
        <plugin>
            <!--
                Generates JAXWS classes for all of the WSDL files in $[project.base.dir}/src/wsdl.
            -->
            <groupId>org.jvnet.jax-ws-commons</groupId>
            <artifactId>jaxws-maven-plugin</artifactId>
            <version>2.3</version>
            <executions>
                <execution>
                    <goals>
                        <goal>wsimport</goal>
                    </goals>
                    <configuration>
                        <args>
                            <arg>-clientjar</arg>
                            <arg>${project.build.directory}/wsimport-client.jar</arg>
                        </args>
                        <wsdlUrls>
                            <wsdlUrl>https://webservice.com/service.wsdl</wsdlUrl>
                        </wsdlUrls>
                    </configuration>
                </execution>
            </executions>
            <configuration>
                <target>2.1</target>
                <verbose>true</verbose>
            </configuration>
        </plugin>
        <plugin>
            <!--
                Unjar the wsimport-client.jar created in the jaxws-maven-plugin to the WAR's classes folder
            -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <phase>process-resources</phase>
                    <configuration>
                        <target>
                            <unzip src="${project.build.directory}/wsimport-client.jar" dest="${project.build.directory}/classes" />
                        </target>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

taken from here: https://gist.github.com/mpellegrini/5439304