Contents |
|---|
Why JAX-WS?
- First and foremost, JAX-WS comes with Java 6. That means no extra dependencies.
- JAX-WS is pretty easy to use if you have the WSDL for a given service.
- The tools (e.g.
wsimport) are also bundled with Java 6.
The Basics
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
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!
- The location of the WSDL is hard coded.
- 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:
- 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.
- Sometimes the service 'port' and maybe even the WSDL are protected by HTTP Basic Authentication.
- While
wsimportdoes support HTTP Basic Authentication (via some 'auth file', not via the command line... WTF!), it makes things more complex.
- While
- 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.
Download the official WSDL and put it in the resources directory (we're still using Maven directories). This example uses
wgetwith HTTP Basic Authentication:Run
wsimporton the downloaded WSDL. The generated code will be in the same Java package as the WSDL resource.- The
-wsdllocationparameter 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:
- The
The code that
wsimportgenerates won't work when using the packaged JAR. Change the generated code to retrieve the stored resource:- 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:
|
For example:
- The second argument is the qualified name of the service itself.
http://example.com/exampleserviceis the namespace - thetargetNamespaceattribute in the WSDL's<wsdl:definitions>element.ExampleServiceis the name of the service - thenameattribute 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: