While web services are supported on many platforms, I like to use Axis2 for a couple of reasons:
The Axis2 server requires a particular file format (Axis archive or aar) for automatic deployment. While it's certainly possible to generate the archive through manual or semi-manual processes, I prefer to use the capabilities provided by Axis2 and documented below. My preferred approach involves first creating a "skeleton" containing the methods I want to expose. Here's an example:
package net.sudsy.AuthenticationService;
public class SimpleClass {
public String authenticate( String ccnum ) {
return( "true" );
}
}
|
Compile the source and generate the class structure relative to the desired destination.
javac -d destinationDirectory SimpleClass.java |
Now we can use the java2wsdl class to generate the corresponding WSDL. I like to use a shell script to invoke java2wsdl since it takes away a lot of the headaches. I should note that, on my system, Axis2 resides in the /opt2/axis2 directory. Here's the script:
#!/bin/bash export AXIS2_HOME=/opt2/axis2 export AXIS2_LIB=$AXIS2_HOME/lib export CLASSPATH for filename in $AXIS2_LIB/*.jar do if [ -z "$CLASSPATH" ] then CLASSPATH=$filename else CLASSPATH=$CLASSPATH:$filename fi done export USER_ARGS= while [ $# -gt 0 ] do if [ x$1 = x-cp ] then shift CLASSPATH=$CLASSPATH:$1 else USER_ARGS="$USER_ARGS $1" fi shift done java org.apache.ws.java2wsdl.Java2WSDL $USER_ARGS |
Here's an invocation using the SampleClass I wrote and compiled earlier:
java2wsdl -cp destinationDirectory -cn net.sudsy.AuthenticationService.SimpleClass -sn AuthenticationService
-tn http://www.sudsy.net/axis2 -stn http://www.sudsy.net/axis2/xsd
|
Without going into details, we specify the class name, service name and some namespaces. You'll need to refer to the documentation in order to fully understand the arguments. Here's the output WSDL file:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://www.sudsy.net/axis2"
xmlns:axis2="http://www.sudsy.net/axis2"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:ns="http://www.sudsy.net/axis2/xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xs:schema attributeFormDefault="qualified"
elementFormDefault="qualified"
targetNamespace="http://www.sudsy.net/axis2/xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="authenticate">
<xs:complexType>
<xs:sequence>
<xs:element name="param0" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="authenticateResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="return" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="authenticateMessage">
<wsdl:part element="ns:authenticate" name="part1"/>
</wsdl:message>
<wsdl:message name="authenticateResponseMessage">
<wsdl:part element="ns:authenticateResponse" name="part1"/>
</wsdl:message>
<wsdl:portType name="SimpleClassPortType">
<wsdl:operation name="authenticate">
<wsdl:input message="axis2:authenticateMessage"/>
<wsdl:output message="axis2:authenticateResponseMessage"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SimpleClassSOAP11Binding" type="axis2:SimpleClassPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="authenticate">
<soap:operation soapAction="urn:authenticate" style="document"/>
<wsdl:input>
<soap:body namespace="http://www.sudsy.net/axis2" use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body namespace="http://www.sudsy.net/axis2" use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="SimpleClassSOAP12Binding" type="axis2:SimpleClassPortType">
<soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="authenticate">
<soap12:operation soapAction="urn:authenticate" style="document"/>
<wsdl:input>
<soap12:body namespace="http://www.sudsy.net/axis2" use="literal"/>
</wsdl:input>
<wsdl:output>
<soap12:body namespace="http://www.sudsy.net/axis2" use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SimpleClass">
<wsdl:port binding="axis2:SimpleClassSOAP11Binding" name="SimpleClassSOAP11port">
<soap:address location="http://localhost:8080/axis2/services/SimpleClass"/>
</wsdl:port>
<wsdl:port binding="axis2:SimpleClassSOAP12Binding" name="SimpleClassSOAP12port">
<soap12:address location="http://localhost:8080/axis2/services/SimpleClass"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
|
I should note that I've run the generated WSDL through a "pretty" processor in order to make it easier to read. While XML is plain text and is supposed to be human-readable, there's no requirement for line breaks.
Next I run the WSDL through wsdl2java. As with java2wsdl, I like to use a shell script to invoke wsdl2java. It's almost exactly the same as the other one:
#!/bin/bash export AXIS2_HOME=/opt2/axis2 export AXIS2_LIB=$AXIS2_HOME/lib export CLASSPATH for filename in $AXIS2_LIB/*.jar do if [ -z "$CLASSPATH" ] then CLASSPATH=$filename else CLASSPATH=$CLASSPATH:$filename fi done export USER_ARGS= while [ $# -gt 0 ] do if [ x$1 = x-cp ] then shift CLASSPATH=$CLASSPATH:$1 else USER_ARGS="$USER_ARGS $1" fi shift done java org.apache.axis2.wsdl.WSDL2Java $USER_ARGS |
Here's the invocation of the command:
wsdl2java -ss -sd -o destinationDirectory -uri pathToWSDLFile |
The outputDir doesn't have to exist; it will be created automatically. In fact, I prefer that the output directory not already exist so that I can have a pristine platform for development. The pathToWSDL should be obvious; it's the path to the file which was generated by java2wsdl.
The output directory will contain two directories (src and resources) and a build.xml file. In this example, the skeleton will be located in the src/net/sudsy/www/axis2 directory and named SimpleClassSkeleton.java. Now it's simply a matter of "fleshing out" the exposed method(s) and invoking ant at the top level of the directory tree. The output archive file will be located in the build/lib subdirectory and, in this case, will be named SimpleClass.aar. Deployment is achieved by copying this file to the ${AXIS2_HOME}/repository/services directory. It will be automagically deployed.
Creating the client is even easier. Hint: remove the -ss (server side) and -sd (service descriptor) flags from the invocation of wsdl2java.