Skip to end of metadata
Go to start of metadata

Why JAX-WS?

  1. First and foremost, JAX-WS comes with Java 6. That means no extra dependencies.
  2. JAX-WS is pretty easy to use if you have the WSDL for a given service.
  3. The tools (e.g. wsimport) are also bundled with Java 6.

The Basics

  1. Generate the JAX-WS Java code from the WSDL:

    • We're generating the code into Maven-style directories here, where you'd probably want to commit the sources to version control. The assumption being that the WSDL isn't going to change very often.
    • If you want to use Maven to do it, there is a plugin that runs wsimport
  2. In the client program, instantiate the 'service' object, get the port, and use the port to call methods:

That's all there is to it. However, this is probably not useful in the real world!

  1. The location of the WSDL is hard coded.
  2. Many SOAP services provide the WSDL as a file only, or via secure access.   This generated code will not work even if the actual service is working because it will try to download the WSDL first.

More Realistic Examples

Of course, in real life things are rarely that simple. Here are some issues with using wsimport in the 'vanilla' way:

  1. Most of the time you will probably want to access different instances of the service.
    • For example, a staging/testing instance for development and a production instance for... well... production.
    • Your application may not know the URL for the service up front.
  2. Sometimes the service 'port' and maybe even the WSDL are protected by HTTP Basic Authentication.
    • While wsimport does support HTTP Basic Authentication (via some 'auth file', not via the command line... WTF!), it makes things more complex.
  3. The JAX-WS client code always tries to download the WSDL when it is instantiated.

Storing the WSDL Locally

One way to avoid HTTP Basic Authentication issues with the WSDL and also avoid downloading it every time is to keep the WSDL in the JAR along with the generated JAX-WS client.

  1. Download the official WSDL and put it in the resources directory (we're still using Maven directories). This example uses wgetwith HTTP Basic Authentication:

  2. Run wsimporton the downloaded WSDL. The generated code will be in the same Java package as the WSDL resource.

    • The -wsdllocation parameter does not have the directory on it, this is because the WSDL location in the generated code will be relative to the service class.
    • In the generated service class, you will see something like this:

  3. The code that wsimport generates won't work when using the packaged JAR. Change the generated code to retrieve the stored resource:

  4. The WSDL and the JAX-WS Java code can be committed to version control. The resulting JAR file will be fairly self contained and flexible, provided the WSDL doesn't change.

Ignoring the WSDL Completely

Sometimes the WSDL is not available and you don't want to store it locally (maybe it's too big or it has lots of <ws:import> elements in it).   You can force JAX-WS to ignore the WSDL completely by passing null in the WSDL URL argument.

NOTE:
  • If you do this, you MUST provide the endpoint URL explicitly (see the next section).
  • This works with the built in JAX-WS implementation in Java 6 +, but it does not work in some versions of JBoss WS!

For example:

 

  • The  second argument is the qualified name of the service itself.
  • http://example.com/exampleservice is the namespace - the targetNamespace attribute in the WSDL's <wsdl:definitions> element.
  • ExampleService is the name of the service - the name attribute in the WSDL's <wsdl:definitions> element.

Specifying the Endpoint Address

In the client code, you can create the 'Service' object and set the URL of the service like this:

Specifying the Endpoint Address and HTTP Basic Authorization

Debugging and Troubleshooting

One useful tool is the system property that prints out all the SOAP traffic: