REST API

Building a SOAP-Based WebService Client in Nuxeo

Updated: July 17, 2023

To start with we assume that we have access to a remote WebService, from which we can easily download the WSDL file. For example, let's take a simple WebService that provides weather forecast: http://www.restfulwebservices.net/wcf/WeatherForecastService.svc?wsdl.

The code samples used for this example can be found here.

Generating the WebService client Java source files with Maven

The wsimport goal from the Maven plugin jaxws-maven-plugin allows you to generate the WebService client Java source files given a WSDL file. The WSDL file can either be accessed remotely using an URL or locally using a directory. Obviously it is better to point at a local (previously downloaded) WSDL file to ensure reproducibility of the build.

For instance, copy http://www.restfulwebservices.net/wcf/WeatherForecastService.svc?wsdl to src/main/resources/wsdls in a Nuxeo project and use the following code in your pom.xml:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>jaxws-maven-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>wsimport</goal>
      </goals>
      <configuration>
        <wsdlDirectory>src/main/resources/wsdls</wsdlDirectory>
        <sourceDestDir>${project.build.directory}/generated-sources/wsimport</sourceDestDir>
      </configuration>
    </execution>
  </executions>
</plugin>

When you'll build the project, all WSDL files in src/main/resources/wsdls will be parsed and the associated Java source files generated in ${project.build.directory}/generated-sources/wsimport.

The jaxws:wsimport goal is automatically executed within the life cycle phase generate-sources, ie. before the compile phase. This way, running mvn clean install first generates the source files and then compiles them.

Be careful with XSD schema imports!

Often a WSDL file needs to import one or more XSD schemas, using the <xsd:import> directive.

Let's take this example: <xsd:import **schemaLocation="http://www.restfulwebservices.net/wcf/WeatherForecastService.svc?xsd=xsd0"** namespace="http://www.restfulwebservices.net/ServiceContracts/2008/01"/>

If your WSDL file is accessed locally, you also have to download all the XSD schemas referenced by the WSDL and use a relative path for the schemaLocation attribute of the <xsd:import> directives prior to building your project.

Assuming that the XSD schema WeatherForecastService.xsd has been downloaded in src/main/resources/wsdls/xsdschemas, this is what you get: <xsd:import **schemaLocation="xsdschemas/WeatherForecastService.xsd"** namespace="http://www.restfulwebservices.net/ServiceContracts/2008/01"/>.

Documentation about wsimport is available here: http://jax-ws-commons.java.net/jaxws-maven-plugin/wsimport-mojo.html.

Documentation about using JAX-WS with Maven is available here: http://blogs.oracle.com/enterprisetechtips/entry/using_jax_ws_with_maven.

Getting an Instance of the WebService Client

Once the Java source files have been generated and compiled, you can use them as a third-party library:

WeatherForecastService wfs = new WeatherForecastService(
     new URL("http://www.restfulwebservices.net/wcf/WeatherForecastService.svc?wsdl"),
     new QName("http://www.restfulwebservices.net/ServiceContracts/2008/01", "WeatherForecastService"));
IWeatherForecastService iwfs = wfs.getBasicHttpBindingIWeatherForecastService();

The (slightly) tricky part here is to find the actual WebService client in the generated classes and the method it provides to get an instance of the WebService client interface.

  • The actual WebService client is the class with the following annotation: @WebServiceClient(name = "WeatherForecastService",... In our example: WeatherForecastService

    • The URL is the one of the WSDL file.
    • To build the QName, we use the targetNamespace and name attributes of the <wsdl:definitions> element in the WSDL file. In our example: <wsdl:definitions name="WeatherForecastService" targetNamespace="http://www.restfulwebservices.net/ServiceContracts/2008/01"....
  • The WebService client interface is the class with the following annotation: @WebService(name = "IWeatherForecastService",... In our example: IWeatherForecastService

  • The WeatherForecastService class offers the method getBasicHttpBindingIWeatherForecastService() that returns an object of type IWeatherForecastService.

Calling a WebService Method

Finally, you can call any method available in the WebService client interface, for instance IWeatherForecastService#getCitiesByCountry(String country) which returns the cities of a given country.

ArrayOfstring cities = iwfs.getCitiesByCountry("FRANCE");
String message = "Cities of country FRANCE: " + cities.getString();

You can learn here how to build a server-side SOAP based WebService in Nuxeo.

Advanced Client Configuration Using a Configuration XML File

If you are looking how to create some advanced client configuration, since Apache CXF, you'll need some dependencies. The configuration behavior is the same as the server part, and described in the advanced configuration section of the Building a SOAP-Based WebService in the Nuxeo Platform.