I needed web services up and running, and after a short look at what looks like the best framework for implementing web services, I ended up choosing CXF.
Now though the standalone demo is pretty simple (as explained on the site), deploying this in JBoss is somewhat more difficult. This is partly caused by difficult to find documentation, and partly by possible clashes caused by the classloader (some libraries you really don’t want to have in your classpath twice).
Let’s start by running the demo, then explain what I did and why I made some of the choices I made.
I have a small project which implements this little demo that you can download. You have to fix some of the settings in the main pom.xml file. Specifically the details of your JBoss installation which can be found in the properties in the dev-example profile.
You also need a working JBoss instance, with cargocpc in it. One option is downloading this tuned configuration. I would recommend you to remove the “jbossws.sar” directory from deploy. This contains a different web services stack. However, the demo does not include the CXF libraries, so these need to be added in your deploy directory. The easiest way is to download and extract cxf-2.0.5.sar.tgz.
When these changes are done, thanks to maven, you can run and test the simple “ping” web service by typing
mvn -Dfulltest -Ddev=example install
The actual service and implementation are very simple
public interface PingService
public class PingServiceImpl
public String getPing()
return "Ping back @" + new Date( System.currentTimeMillis() );
To assure this works, the following web.xml is provided
<?xml version="1.0" encoding="ISO-8859-1"?>
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
<display-name>Prolix Web Services 1.0</display-name>
This in turn refers to the following cxf.xml configuration file
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
Running and testing this bean can be done using this simple program.
public class PingTest
public void testPingService()
ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
factory.setServiceClass( PingService.class );
factory.setAddress( "http://localhost:8080/cxfdemo/ws/1.0/ping" );
factory.getServiceFactory().setDataBinding( new AegisDatabinding() );
PingService client = (PingService) factory.create();
String res = client.getPing();
assertTrue( res.startsWith( "Ping back @" ) );
This all is very short and compact.
Why the projects is built like this.
The project does not include the libraries as JBoss can cause problems when a library is in the classpath more than once. “commons-logging” is a typical example of this.
This also has the advantage that the deployments don’t need to include the libraries again.
- The service interface is put in a separate module than the implementation. This allows easy distribution of the interfaces in java form (which for many people is more readable than wsdl files).
The project is built to allow compiling and installing to work without running the full tests. However, you can run them if you want to (using the fulltest profile).
- There is a jboss web services implementation which uses CXF. However, this was not used here as this does not include the “simple” CXF interface, only the JAX-WS interface.
- The web services module names, interface packages and URL includes a version identifier. This is part of the the way the project is built. When all the interfaces are in one module, then it should be possible to keep the services stable (same WSDL) even when the actual backend code changes. When incompatible changes are required, you can just create anoth set of modules (one interface, one implementation, and provide the changes there.