Creating an Apache CXF Web Service Client

So in early blog posts, I discussed how to make an Axis 1.4 client and secure it. Axis 1.4, however, has been end of lifed; no more work is being done on it. Now, if you are thinking about using Axis 2 to make a client in order to stick with a package that is actively being maintained, I would strongly advise against it. Axis 2 is really designed to be used on a Java application server and it is not friendly at all for standalone clients. There are literally 2 dozen jars plus modules that you need to add to your classpath if you want your client to work.

Fortunately, there is another Apache Web Service project, CXF. From what I can see, CXF is really a continuation of where Axis 1.4 left off. Even for Java Web apps, CXF is much friendlier to use than Axis 2. 

Below is an example of how to setup a CXF client

Step 1. Download CXF

Step 2. Download the wsdl that you want to use. For this post, similar to the previous ones, I am going to use the global weather wsdl

Step 3. Use the wsdl2java CXF utility to generate Java code representing the global weather Web Service. The command should look like the following:

wsdl2java globalweather.wsdl

Step 4. Copy the code from step 3 into your source code directory. If you are working in Eclipse, you can drag and drop the code into your src directory

Step 5. Add the following files from the CXF lib directory to your classpath. If you are working in Eclipse, you can drag and drop these files into your own lib directory

  • commons-collections-3.2.1.jar
  • commons-lang-2.4.jar
  • commons-logging-1.1.1.jar
  • cxf-2.2.12.jar
  • geronimo-activation_1.1_spec-1.0.2.jar
  • geronimo-annotation_1.0_spec-1.1.1.jar
  • geronimo-javamail_1.4_spec-1.6.jar
  • geronimo-jaxws_2.1_spec-1.0.jar
  • geronimo-servlet_2.5_spec-1.2.jar
  • geronimo-stax-api_1.0_spec-1.0.1.jar
  • geronimo-ws-metadata_2.0_spec-1.1.2.jar
  • jaxb-api-2.1.jar
  • jaxb-impl-2.1.13.jar
  • neethi-2.0.4.jar
  • saaj-api-1.3.jar
  • saaj-impl-1.3.2.jar
  • wsdl4j-1.6.2.jar
  • wss4j-1.5.10.jar
  • wstx-asl-3.2.9.jar
  • xml-resolver-1.2.jar
  • XmlSchema-1.4.7.jar
  • xmlsec-1.4.3.jar

Step 6. Create a Web Service client. Below is an example of a client that works with the global weather Web Service:

import java.net.MalformedURLException;
import java.net.URL;
import net.webservicex.*;
public class HelloCXF {
   public static void main (String args[]) {
      try {
         GlobalWeather service = new GlobalWeather(new URL("globalweather.wsdl"));
         GlobalWeatherSoap weatherSoap = service.getGlobalWeatherSoap();
         System.out.println("Weather for New York");
         System.out.println(weatherSoap.getWeather("New York", "United States"));
      }
      catch (MalformedURLException mue) {
         System.err.println("problem with the wsdl url");
         System.exit(1);
      }
   }
}

Tomcat 5.5/6.0 SSL Setup

If you want to serve pages from Tomcat over https, you are going to have to setup SSL in Tomcat. This is important if you are going to perform user authentication or serve sensitive data. 

Here are the steps you need to do to get SSL up and running on your Tomcat instance.

Steps 1: Create an certificate keystore. In lieu of buying a certificate, you can create a self signed one. You don’t really need to buy one unless you are going to be serving work related content from your Tomcat server. You can use the keytool utility that comes with the Java SDK in the bin directory. The command should look something like the one below:

keytool -genkey -alias tomcat -keyalg RSA -keystore /path/to/my/keystore

Step 2: Update your server.xml to contain a connector similar to the one below. If you are working with the server.xml that is in the Tomcat tar ball, this tag should be commented out. Uncomment it and update the location of the keystoreFile path to where yours is located.

<Connector
           port="8443" maxThreads="200"
           scheme="https" secure="true" SSLEnabled="true"
           keystoreFile="/path/to/my/keystore" keystorePass="changeit"
           clientAuth="false" sslProtocol="TLS"/>

References:
http://tomcat.apache.org/tomcat-5.5-doc/ssl-howto.html
http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html

Java case insensitive String replaceAll

Here’s a quick handy tip for replacing all occurrences of a substring regardless of case in Java. Put “(?i)” at the beginning of your substring. For example:

String a = "hello HELLO hEllO";
String b = a.replaceAll("(?i)hello", "bye");
System.out.println(a);
System.out.println(b);

The above code will output:

hello HELLO hEllO
bye bye bye

Load and Unload Mac daemons

So I recently upgrade to Postgresql 9.0 from 8.4 on my Mac. I realized after installing that I did not remember how to stop my old Postgresql instance from startup on boot. Basically, both versions were trying to run on the same port whenever I booted up. I did not want to uninstall my old version just yet so I needed to stop it from starting up. You can see the list of daemons on your Mac that will startup on boot using the command below:

ls /Library/LaunchDaemons/

I stopped Postgresql 8.4 from startup on boot using the following command.

sudo launchctl unload -w com.edb.launchd.postgresql-8.4.plist

How to install a jar locally in Maven

This topic is probably trivial to Maven veterans however, to people getting started, it is pretty important. As you probably already know if you got here from Googling, Maven is a neat build tool for Java that goes out and downloads all your jar dependencies for you. For example, if you need to use the apache commons lang package, you specify the dependency in your pom.xml Maven will download it for you. Under the hood, what is happening is that Maven will first check your local package repository, located in a directory called .m2 in your home directory, and if it cannot find the package there, it will check remote repositories.

This approach is great for Maven distributed packages and the most commonly used ones are available. If you happen to need to use a package that is not available though, then you will have to install it locally in order for Maven to build your applications with it. This situation happened to me when my work got a license for a new DBMS that had a closed source driver.

Installing a jar is relevantly painless. Simply use the install:install-file goal. Your command should look similar to the one below.

mvn install:install-file -Dfile=closed-source-driver.jar -DgroupId=com.closed-source -DartifactId=com.closed-source.driver -Dversion=1.0 -Dpackaging=jar

Once you have installed the jar, you can now include it as a dependency in any of your projects. Based on the example above, the dependency tag in your pom.xml should look like the following.

<dependency>
<groupId>com.closed-source</groupId>
<artifactId>com.closed-source.driver</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>

How to build an Axis 1.4 XML-RPC based Web Service client

So Web Services have been around for a while now and one would think that the popular packages out there would support most any service. Well unfortunately, that is a bad assumption to make. That is because of how long Web Services have existed. Some earlier versions employed a variation of the SOAP message that we use today called XML-RPC. Very few contemporary Web Service packages support XML-RPC yet even now, you will run into someone using it, like I did at work.

I found that Axis 1.4 works pretty much out of the box for these older style Web Services. Axis2, like the rest though, does not support XML-RPC. 

To create a client, you will be best served by using the WSDL2Java utility. To use it, you will need to make sure the following jars are in your classpath; they come packaged in the Axis 1.4 download so you don’t have to google for them.

  • axis.jar
  • jaxrpc.jar
  • saaj.jar
  • commons-logging-1.0.4.jar
  • commons-discovery-0.2.jar
  • wsdl4j-1.5.1.jar

Once you have added those jars to your classpath, you can let Axis do most of the work for you in creating a client. For this example, we are going to build a client that gets the weather from the global weather Web Service. This Web Service is pretty basic so it is good for learning how to make a client however, its uptime can be spotty at times.

Here are the steps for creating a clients.

Step 1: Download the globalweather.wsdl. This file contains information describing the Web Service.

Step 2: Run the following command
java org.apache.axis.wsdl.WSDL2Java globalweather.wsdl

This Axis utility will generate a Java package from the wsdl necessary for interacting with the Web Service. This code will be layout out in the directory where you ran the utility and at the time of writing this article should have to following structure
NET/webserviceX/www/

Step 3: Copy the code you generated in Step 2 to your client’s working directory. You might not need to do this step if you are going to write your client in the same directory in which you generated the package. If you are using Eclipse or any IDE though, you will want to copy the NET directory into one of your source code folders. I use Eclipse so I literally dragged and dropped it.

Step 4: Create a client class. The code below is a simple client that gets the weather for New York.

import NET.webserviceX.www.*;
public class HelloWeather {
    public static void main(String[] args) throws Exception {
        GlobalWeatherLocator locator = new GlobalWeatherLocator();
        GlobalWeatherSoap globalWeatherSoap = locator.getGlobalWeatherSoap();
        System.out.println("Weather for New York");
        System.out.println(globalWeatherSoap.getWeather("New York", "United States"));
    }
}

Axis hides a lot of the boiler plate work involved in a Web Service and it is pretty simple to use. The only complexity that you will encounter is when the Web Services you use get complex and generally those ones have some support documentation that explains what all the end points are and how you should use them.

SSH Tunnels - 2 ways

Recently, I have been googling how to make tunnels so I thought I would post what I do. A SSH tunnel allows you to connect to server, A, through server B, from client C.

You generally only want to setup a tunnel when you need to connect to server A but only have access to server B from your client, your laptop in the diagram above. Usually server A is in a protected network and server B is a bastion host that clients can use to access it.

The first tunnel command I will show you will provide you with command line access to your target server, serverA.com
ssh -o ServerAliveInterval=15 -t serverB.com ssh serverA.com

I have included an option to keep the connection alive, -o ServerAliveInterval=15, if you are away from your keyboard for too long. The -t provides you with command line access.

This next tunnel command allows you to forward a port from the target server, again serverA.com, to another port on your client.
ssh -N -L 9999:serverA.com:5432 -o TCPKeepAlive=no -o ServerAliveInterval=15 serverB.com

I am again specifying options to keep idle connections open, -o TCPKeepAlive=no -o ServerAliveInterval=15. The -L allows you to specific which local port you want to have the remote port forwarded to. The above example is really for forwarding the postgresql port on serverA.com (default 5432) to port 9999 on my client going through serverB.com, the bastion server. That allows me use pgAdmin to connect to the database on serverA.com using localhost:9999.

Building Self Contained Executable Jars - 2 ways

Building an executable jar file is generally pretty simple if you do not want to package any library jars files with in it. You simply have to insert a Main-Class entry into the manifest file that specifies which class has the main method that you want to execute. That should be sufficient for small Java applications where you do not need to use a jarred library however once you need to use one, problems arise.

One approach is to simple just put your external jars in your classpath however, that is only really acceptable if you are not really deploying your application anywhere. Plus having to push support jar files and update classpaths is a pain. A much preferable approach is you wrap everything up into a single jar file.

Now the Java class loader does not know how to load classes that are in a jar inside another jar which means just manipulating the manifest file will not be enough. Fortunately, there is a nifty utility called one-jar that helps us build these self contained executable jar files. Here I am going to show you 2 ways to use it, one using Maven and one using Ant.

Way 1: Maven
Using Maven is by far the easiest approach. You need to add the following to your pom.xml

</plugins>
  <plugin>
    <groupId>org.dstovall</groupId>
    <artifactId>onejar-maven-plugin</artifactId>
    <version>1.3.0</version>
    <executions>
      <execution>
      <configuration>
        <mainClass>com.chrisjordan.examples.HelloWorld</mainClass>
      </configuration>
      <goals>
        <goal>one-jar</goal>
      </goals>
      </execution>
    </executions>
  </plugin>
</plugins>

<pluginRepository>
  <id>onejar-maven-plugin.googlecode.com</id>
  <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>

This Maven extension will literally package all the jar dependencies along with your code into a single executable jar file. Simple use the maven goal install or package to generate it.
mvn install
mvn package

Way 2: Ant
Ant is still a really popular build tool but in order to use one-jar, it requires a little more work.

Step 1: Download one-jar

Step 2: Expand it some where that you can reference easily. It is probably the best if you expand it in your project directory since if you are working in a team and are committing your code to a repository, it will need to be there so others can use it without having to think about it.

Step 3: Create a task in your build.xml file similar to the one below

<property name="one-jar.dist.dir" value="one-jar-ant"/>
<import file="${one-jar.dist.dir}/one-jar-ant-task.xml" optional="true" />
<target name="jar" depends="clean, build, tests">
  <!-- Construct the One-JAR file -->
  <one-jar destfile="${target.dir}/hello-world.jar">
    <manifest>
      <attribute name="One-Jar-Main-Class" value="com.chrisjordan.examples.HelloWorld" />
    </manifest>
    <main>
      <fileset dir="${build.main.dir}"/>
    </main>
    <lib>
      <fileset dir="${target.dir}/lib" includes="*.jar"/>
    </lib>
    <fileset dir="${build.main.res}" includes="**"/>
  </one-jar>
</target>

So as you can see from the above task, there are some gotchas with that using one-jar in ant. You are responsible for the downloading the one-jar package and expanding it in a directory that you reference from your build.xml. As well, you have to specify the jars and property files that you want packaged up.

Now to build your executable jar, you simple have to call ant with the one-jar task you created
 

Let’s try blogging again

So since I set this Website up a couple years ago, I haven’t really used it. I’ve decided it is now time to try to blog some of the useful coding tid bits I run into from time to time. Generally I have found blogging to be a royal pain in the butt but I am getting tired of googling for the same stuff or even worse, telling people to google for the same stuff. Hopefully what I blog about will reduce that redundant googling and maybe it will help some people who are googling for the same stuff I was looking for.

A Best Paper Nomination

So I have been busy. Work has been awesome and I will have some interesting updates on different things I have been working on later. I also just got back from my first vacation to Vancouver… well first vacation since I started work. When I got home at the beginning of this month, I was pleasantly surprised to find that my HICSS-42 publication was nominated for a best paper award. It didn’t get it but regardless, it is nice to know that people found it to be good enough to warrant the nod.