Codehaus XFire

Documentation

Quicklinks

Developers

Sponsors

This guide leads you through the steps of creating a client for a service. This process will also generate a server stub as well. The full example can be found in "examples/geoip-client" in the distribution.

Limitations

There are a couple limitations in the generator that you may need to be aware of.

  • The generator Java 5.0 only at this point since it takes advantage of the JSR 181 annotations
  • RPC/Encoding is NOT supported.

Generating Clients/Server stubs

Ant Task

The service we're going to use takes an IP address then supplies us with a country name. Generating a client is relatively easy. Here is an example build file runs the WSGen task from XFire:

<taskdef name="wsgen" classname="org.codehaus.xfire.gen.WsGenTask" 
     classpathref="maven.compile.classpath"/>

<wsgen outputDirectory="${basedir}/target/generated-source"
  wsdl="${basedir}/src/wsdl/geoip.wsdl" package="net.webservicex.geoip.jaxb" overwrite="true"/>



Options:

Command Line

You can also run WsGen from command line ( for jaxb binding, for xmlbeans you need additional jar ) using following  script:

gpath=xfire-all-1.2-SNAPSHOT.jar:ant-1.6.5.jar:jaxb-api-2.0EA3.jar:stax-api-1.0.1.jar:jdom-1.0.jar:jaxb-impl-2.0EA3.jar\
:jaxb-xjc-2.0-ea3.jar:wstx-asl-2.9.3.jar:commons-logging-1.0.4.jar:activation-1.1.jar:wsdl4j-1.5.2.jar:XmlSchema-1.0.3.jar:xfire-jsr181-api-1.0-M1.jar;

java -cp $gpath org.codehaus.xfire.gen.WsGen -wsdl http://localhost:8080/xfire/services/Bookservice?wsdl -o . -p pl.tomeks.client -overwrite true



(Remeber to use jars shipped with xfire distribution to avoid version mismatch)
You can specify following parameters :

-wsdl        : location of wsdl file ( can be any valid url )
-o             : output directory for generated classes
-package   : package where client code will be placed
-binding    : binding to use ( jaxb or xmlbeans )
-overwrite: allows to overwrite previously generated classes  ( without this option, generator will refuse to generate classes if such already exists )

Using the Client

Now using the client is relatively simple:

package net.webservicex.geoip;

import net.webservicex.GetGeoIP;
import net.webservicex.geoip.jaxb.GeoIPServiceClient;
import net.webservicex.geoip.jaxb.GeoIPServiceSoap;
import junit.framework.TestCase;

public class GeoIPClientTest extends TestCase
{
    public void testClient() throws Exception
    {
        GeoIPServiceClient service = new GeoIPServiceClient();
        GeoIPServiceSoap geoIPClient = service.getGeoIPServiceSoap();
        
        System.out.println("The country is: " + 
                           geoIPClient.getGeoIP("216.73.126.120").getCountryName());
    }
}



You'll notice that a GeoIPImpl class is also generated. If you are using the client, you cannot delete this as it has annotations which are used to create the client. The Impl class corresponds to the <binding> in the wsdl so it contains SOAP binding information.
You can add new handlers or set properties on generated client with following code :

Client client = Client.getInstance(geoIPClient);
client.setProperty(Channel.USERNAME, "test");
client.setProperty(Channel.PASSWORD, "test");
client.addInHandler(new DOMOutHandler());



Controlling JAXB Bindings

With JAXB 2 it is possible to control the packages the schema generated beans are placed in.

<jxb:bindings jxb:version="1.0"
	      xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
	      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <jxb:bindings schemaLocation="../wsdl/echoFault.wsdl#types?schema1" node="/xsd:schema">
	<jxb:schemaBindings>
	    <jxb:package name="org.codehaus.xfire.echo.external">
	    </jxb:package>      
	</jxb:schemaBindings>
    </jxb:bindings>
</jxb:bindings>



This will take all the types for the schema and stuff them in the "org.codehaus.xfire.echo.external" package. This is run by specifying the binding parameter on the ant task or command line. For example:
java org.codehaus.xfire.gen.WsGen ... -externalBindings external_binding.xjb



XMLBeans Client/Server Generation

You can also use XMLBeans as the binding instead of JAXB 2.0. Simply set the binding paramter on the task:

<wsgen outputDirectory="target/services"
  wsdl="${basedir}/src/wsdl/echoW.wsdl"
  package="com.acme.echo"
  binding="xmlbeans"  overwrite="true"  />



Please note, that you need to generate your XmlBeans first and include the jar into the classpath of the WsGen-Task. If you forget this step you will see NullPointerExceptions.

Using Server Stubs

To use the service class that is generated, you must use the appropriate service factory.

With JAXB this looks like:

JaxbServiceFactory serviceFactory = new JaxbServiceFactory();
Service service = serviceFactory.create(MyServiceImpl.class);



Or via services.xml:
<service>
<serviceClass>MyServiceImpl</serviceClass>
<serviceFactory>org.codehaus.xfire.jaxb2.JaxbServiceFactory</serviceFactory>
</service>



With XMLBeans this looks like:
XmlBeansServiceFactory serviceFactory = new XmlBeansServiceFactory();
Service service = serviceFactory.create(MyServiceImpl.class);



Or via services.xml:
<service>
<serviceClass>MyServiceImpl</serviceClass>
<serviceFactory>org.codehaus.xfire.xmlbeans.XmlBeansServiceFactory </serviceFactory>
</service>



Generating client over HTTPS

If you need to generate client code from WSDL over HTTPS, you need to specify  these two jvm parameters:

-Djavax.net.ssl.keyStore=<keystore.jks>
-Djavax.net.ssl.keyStorePassword=<password>



 which must points to keystore with server's public key.
If you are using WsGenTask, then you can specify keystore and keystorePass properties of the task instead of jvm params.

Returning an existing WSDL

If you want the service to return the actual WSDL you used to create the stubs instead of generating one from the stubs:

service.setWSDLWriter(new ResourceWSDL("myService.wsdl"));