Generating the service stubs from a WSDL

In order to use the Camel CXF Component to either consume from or produce to SOAP web services, you will first need to generate a set of interfaces that define the web service based on a predefined service contract—the WSDL. To do this, we will use a Maven plugin provided by the Apache CXF project.

These generated interfaces take the form of regular Java classes and interfaces marked up with JAX-WS annotations. These classes, used as arguments and return values from the web service methods, are known as models, and they will be generated from the XML schema contained within the WSDL. These classes will be annotated with JAXB bindings to automate the conversion between the Java objects and their XML representation.

Collectively these JAX-WS artifacts make it possible for Camel to call web services or to act as a web service provider.

This recipe will show you the basics of setting up the cxf-codegen-plugin to automate the build-time generation of JAX-WS artifacts from your project's WSDL documents.

Getting ready

The cxf-codegen-plugin is referenced within a Maven project's pom.xml file. This recipe defines a child project, ws-payments-api, within the camel-cookbook-web-services module for the sole purpose of generating JAX-WS artifacts from the WSDL files that define a web service contract. This project's JAR artifact will be used as a dependency by the ws-camel-routes project that includes the Camel routes.

To generate a class representation of a web service, you will require a WSDL file. This chapter makes use of the samples contained within the src/main/resources/wsdl directory.

How to do it...

In the Maven project's pom.xml file, add the following plugin definition:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-codegen-plugin</artifactId>
      <version>${cxf-version}</version>
      <executions>
        <execution>
          <phase>generate-sources</phase>
          <goals>
            <goal>wsdl2java</goal>
          </goals>
          <configuration>
            <sourceRoot>
              ${project.build.directory}/generated-sources/cxf
            </sourceRoot>
            <wsdlRoot>
              ${project.basedir}/src/main/resources/wsdl
            </wsdlRoot>
            <includes>
              <include>*.wsdl</include>
            </includes>
          </configuration>
        </execution>
      </executions>
    </plugin>
    <!-- other plugins -->
  </plugins>
  <!-- other build configurations -->
</build>

The ${cxf-version} used in this example is 2.7.7.

How it works...

The default behavior of the cxf-codegen-plugin, as shown configured in the preceding How to do it... section, is to parse the WSDL files in your project's src/main/resources/wsdl directory (specified in the wsdlRoot option), and generate JAX-WS and JAXB artifacts in your project's target/generated-sources/cxf (sourceRoot) directory.

The code generation happens during the generate-sources phase of the build (see the Maven documentation for a description of the build lifecycle). Maven will automatically compile these Java source files and include the resulting classes in the module being built. You can then start referencing these classes in your code, including within your Camel routes.

It is considered best practice to create a separate Maven project for the sole purpose of generating the JAX-WS annotated web service API from your WSDL files. This project is then used as a dependency by modules that define your Camel routes. Aside from enabling reuse of the API between modules, it makes the generated classes easier to work with from within an IDE. That is, after the first build of the API project, you get code completion around the generated classes in dependent modules without needing to do anything special in the IDE. This is preferable to doing everything in the same project, as your IDE otherwise depends on a source directory that appears only during a Maven build.

The primary benefit of generating JAX-WS source code from a WSDL, and using it in your Camel routes, is that the body and headers of the SOAP messages are accessible to your routing logic as Plain Old Java Objects (POJOs). This makes it very easy to create routes that work with messages coming from multiple frontend technologies, including web services, and operate on them in a consistent fashion.

Code is generated into packages named in the reverse order of their namespace URIs. Two namespaces are of particular interest, the targetNamespace for the service definition and the schema namespace of the payload elements. Consider this fragment from the example WSDL file paymentService.wsdl located in src/main/resources/wsdl/:

<wsdl:definitions name="wsdl-first"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://ws.camelcookbook.org/payment-service"
    xmlns:typens=
      "http://ws.camelcookbook.org/payment-service/types"
    targetNamespace=
      "http://ws.camelcookbook.org/payment-service">

  <wsdl:types>
    <xsd:schema 
        targetNamespace=
          "http://ws.camelcookbook.org/payment-service/types"
        elementFormDefault="qualified">
      <!-- ... -->
    </xsd:schema>
  </wsdl:types>

  <!-- ... -->

  <wsdl:service name="PaymentService">
    <wsdl:port binding="tns:PaymentSOAPBinding"
               name="PaymentPort">
      <soap:address 
          location="http://localhost:9090/paymentService"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

The service interfaces will be generated from the namespace:

http://ws.camelcookbook.org/payment-service

The Java package that they will be placed into is as follows:

org.camelcookbook.ws.payment-service

Likewise, the object representation of the schema will be generated from the following namespace:

http://ws.camelcookbook.org/payment-service/types

The Java package that they will be placed into is as follows:

org.camelcookbook.ws.payment-service.types

There's more...

You do not have to use the cxf-codegen-plugin to generate the required JAX-WS annotated objects; you can instead handcode the JAX-WS classes directly using annotations if you like. Alternatively, the Apache CXF project also includes a java2ws tool that comes with an associated wrapper Maven plugin, which will generate the JAX-WS artifacts from your existing Java interfaces for a service-first approach.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.210.91