Using XML catalogs for your JAX-WS generated code

Table of Contents

The latest JAX-WS standards make the implementation of a webservice a breeze. lately i needed to implement a client from which a WSDL is available. That proces is simple, but the client has issues when starting, the WSDL defined in the generated code is not available. In this post i describe a (the) solution to overcome this.

By means of the maven jax-ws plugin it is simple to generate all the required code for the client implementation. Just add the following to your pom file and you are done.

<plugin>
 <groupId>org.jvnet.jax-ws-commons</groupId>
 <artifactId>jaxws-maven-plugin</artifactId>
 <version>2.3</version>
 <executions>
  <execution>
   <goals>
    <goal>wsimport</goal>
   </goals>
   <!-- 
    Following configuration will invoke wsimport
    once for each wsdl. 
   -->
   <configuration>
    <wsdlLocation>
     http://example.com/mywebservices/*
    </wsdlLocation>
    <wsdlDirectory>src/mywsdls</wsdlDirectory>
    <wsdlFiles>
     <wsdlFile>a.wsdl</wsdlFile>                         
      <!-- 
       produces wsdlLocation = 
       http://example.com/mywebservices/a.wsdl 
      -->
    </wsdlFiles>
   </configuration>
  </execution>
 </executions>
</plugin>

the resulting source for the initialization will look like this:

public final static URL WSDL_LOCATION;
static {
 URL url = null;
 try {
  url = new 
   URL("http://example.com/mywebservices/a.wsdl");
 } catch (MalformedURLException e) {
 
 java.util.logging.Logger.getLogger(
  WebServiceTestClient.class.getName())
   .log(java.util.logging.Level.INFO,
     "Can not initialize the default wsdl from {0}", 
     "http://example.com/mywebservices/a.wsdl");
 }
 WSDL_LOCATION = url;
}

This all looks good when the WSDL is present at URI defined. The location specified in the location is loaded when the client is used for the first time. Not so bad right, wel yes it is. I do not want to depend on the availablity of the WSDL at the location. It might even be that it is not available. But when its not available my client will fail to start.

The solution to this problem is a XML Catalog. The previous link is a latest documentation for it, but i find that the description provided in a old version explains it a lot better.

After reading this the following XML makes sense:

<catalog 
 xmlns=
  "urn\:oasis\:names\:tc\:entity\:xmlns\:xml\:catalog"
 prefer="system">
<system 
 systemId=
  "http://localhost/wsdl/a.wsdl" 
  uri="/wsdl/a.wsdl"/>
</catalog>

The xml must be placed in a file called jax-ws-catalog.xml. Place this file in the META-INF when the generated client is in jar file and in WEB-INF if its a war.

JAX-WS uses the catalog file to resolve the URL to the specified uri. Naturally you need to include the WSDL file in your jar/war file so that is is on the classpath.

With this your client will initialize correctly when loaded by the container and no external (outside jar) files are used anymore.

Related Posts

Using Spring @Cacheable annotations

Today I needed some performance improvements on a application that makes quite a few calls to a database. My default statement is not to implement performance improvements unless there is a issue. Well it just happened.

Read More

How to shoot yourself in the foot!

For Java: After importing java.awt.right.foot.* import java.awt.gun.right.hand.* And writing the classes and methods of those classes needed, you’ve forgotten what the hell you’re doing.

Read More

Adding your artifacts to the public maven repo

Ever had a project that you want to share with every body and not want them to get your source code, build and install it public repository?

Read More