Gartner regularly publishes a graph on the state of software. The latest (at August 2006) is
The site XMethods (www.xmethods.com) is an open site for registering Web services. It includes
Web services are basically RPC across port 80. They require the following environmental support
An RPC system consists of the following pieces
RPC requirement | SOAP |
---|---|
defined data types | defined by SOAP |
wire format for data | defined by SOAP using XML |
wire format for messages | defined by SOAP over HTTP |
an IDL | defined by WSDL |
generation of client stubs | vendor specific |
generation of server stubs | vendor specific |
linking implementation | vendor specific |
Address of service | URL |
Locating service | UDDI |
These are coming (?), but aren't here yet
Converter service:
float inchToMM(float)
float mmToInch(float)
A CORBA IDL specification would look like
interface Converter {
float inchToMM(in float value);
float mmToInch(in float value);
};
A Java RMI specification would look like
public interface Converter implements Remote {
public float inchToMM(float value)
throws RemoteException;
public float mmToInch(float value)
throws RemoteException;
}
The WSDL specification looks like
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="urn:Converter" targetNamespace="urn:Converter" name="ConverterService">
<message name="inchToMMRequest">
<part name="param1" type="xsd:float"/>
</message>
<message name="inchToMMResponse">
<part name="return" type="xsd:float"/>
</message>
<message name="mmToInchRequest">
<part name="param1" type="xsd:float"/>
</message>
<message name="mmToInchResponse">
<part name="return" type="xsd:float"/>
</message>
<message name="java_rmi_RemoteException">
<part type="xsd:string" name="java_rmi_RemoteException"/>
</message>
<message name="com_iona_xmlbus_webservices_ejbserver_ConversionException">
<part type="xsd:string" name="com_iona_xmlbus_webservices_ejbserver_ConversionException"/>
</message>
<portType name="ConverterPortType">
<operation name="inchToMM">
<input message="tns:inchToMMRequest" name="inchToMM"/>
<output message="tns:inchToMMResponse" name="inchToMMResponse"/>
<fault message="tns:java_rmi_RemoteException" name="java_rmi_RemoteException"/>
</operation>
<operation name="mmToInch">
<input message="tns:mmToInchRequest" name="mmToInch"/>
<output message="tns:mmToInchResponse" name="mmToInchResponse"/>
<fault message="tns:java_rmi_RemoteException" name="java_rmi_RemoteException"/>
<fault
message="tns:com_iona_xmlbus_webservices_ejbserver_ConversionException" name="com_iona_xmlbus_webservices_ejbserver_ConversionException"/>
</operation>
</portType>
<binding name="ConverterBinding" type="tns:ConverterPortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http/" style="rpc"/>
<operation name="inchToMM">
<soap:operation soapAction="" style="rpc"/>
<input name="inchToMM">
<soap:body use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output name="inchToMMResponse">
<soap:body use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
<fault name="java_rmi_RemoteException">
<soap:fault name="java_rmi_RemoteException"
use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</fault>
</operation>
<operation name="mmToInch">
<soap:operation soapAction="" style="rpc"/>
<input name="mmToInch">
<soap:body use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output name="mmToInchResponse">
<soap:body use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
<fault name="java_rmi_RemoteException">
<soap:fault name="java_rmi_RemoteException"
use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</fault>
<fault name="com_iona_xmlbus_webservices_ejbserver_ConversionException">
<soap:fault
name="com_iona_xmlbus_webservices_ejbserver_ConversionException"
use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</fault>
</operation>
</binding>
<service name="Converter">
<port name="ConverterPort" binding="tns:ConverterBinding">
<soap:address location="http://www.xmlbus.com:9010/ionasoap/servlet/Converter"/>
</port>
</service>
</definitions>
inchToMMRequest
inchToMMResponse
java_rmi_RemoteException
inchToMM(inchToMMRequest, inchToMMResponse,
java_rmi_RemoteException)
ConverterBinding
operation: inchToMM/rpc
"inchToMM"
"inchToMMResponse"
"java_rmi_RemoteException"
name: Converter
address: http://...
...
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="urn:Converter" targetNamespace="urn:Converter" name="ConverterService">
<message name="inchToMMRequest">
<part name="param1" type="xsd:float"/>
</message>
<message name="inchToMMResponse">
<part name="return" type="xsd:float"/>
</message>
<message name="mmToInchRequest">
<part name="param1" type="xsd:float"/>
</message>
<message name="mmToInchResponse">
<part name="return" type="xsd:float"/>
</message>
<message name="java_rmi_RemoteException">
<part type="xsd:string" name="java_rmi_RemoteException"/>
</message>
<message name="com_iona_xmlbus_webservices_ejbserver_ConversionException">
<part type="xsd:string" name="com_iona_xmlbus_webservices_ejbserver_ConversionException"/>
</message>
<portType name="ConverterPortType">
<operation name="inchToMM">
<input message="tns:inchToMMRequest" name="inchToMM"/>
<output message="tns:inchToMMResponse" name="inchToMMResponse"/>
<fault message="tns:java_rmi_RemoteException" name="java_rmi_RemoteException"/>
</operation>
<operation name="mmToInch">
<input message="tns:mmToInchRequest" name="mmToInch"/>
<output message="tns:mmToInchResponse" name="mmToInchResponse"/>
<fault message="tns:java_rmi_RemoteException" name="java_rmi_RemoteException"/>
<fault
message="tns:com_iona_xmlbus_webservices_ejbserver_ConversionException" name="com_iona_xmlbus_webservices_ejbserver_ConversionException"/>
</operation>
</portType>
<binding name="ConverterBinding" type="tns:ConverterPortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http/" style="rpc"/>
<operation name="inchToMM">
<soap:operation soapAction="" style="rpc"/>
<input name="inchToMM">
<soap:body use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output name="inchToMMResponse">
<soap:body use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
<fault name="java_rmi_RemoteException">
<soap:fault name="java_rmi_RemoteException"
use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</fault>
</operation>
<operation name="mmToInch">
<soap:operation soapAction="" style="rpc"/>
<input name="mmToInch">
<soap:body use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output name="mmToInchResponse">
<soap:body use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
<fault name="java_rmi_RemoteException">
<soap:fault name="java_rmi_RemoteException"
use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</fault>
<fault name="com_iona_xmlbus_webservices_ejbserver_ConversionException">
<soap:fault
name="com_iona_xmlbus_webservices_ejbserver_ConversionException"
use="encoded" namespace="urn:Converter" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</fault>
</operation>
</binding>
<service name="Converter">
<port name="ConverterPort" binding="tns:ConverterBinding">
<soap:address location="http://www.xmlbus.com:9010/ionasoap/servlet/Converter"/>
</port>
</service>
</definitions>
interface ConverterInterface {
float inchToMM(float value);
float mmToInch(float value);
};
AXIS_LIB=/usr/local/axis-1_1/lib # change this for your lib dir
for i in $AXIS_LIB/*.jar
do
CP=$CP:$i
done
java -cp "$CP" org.apache.axis.wsdl.Java2WSDL \
-o ConverterInterface.apache.wsdl \
-l http://localhost/wstk/services/ConverterInterface \
ConverterInterface
java -cp $WSTK_CP org.apache.axis.wsdl.WSDL2Java \
ConverterInterface.ibm.wsdl
interface ConverterInterface {
float inchToMM(float value);
float mmToInch(float value);
};
package DefaultNamespace;
public interface Converter extends java.rmi.Remote {
public float inchToMM(float in0) throws java.rmi.RemoteException;
public float mmToInch(float in0) throws java.rmi.RemoteException;
}
XML DTDs (Document Type Definitions) are good for describing document structure e.g.
<!ELEMENT book (preface?, chapter+, index)>
<!ELEMENT chapter (section+)>
<!ELEMENT section (#PCDATA)>
<age> 45 </age>
<height> 5.9 </height>
<color> blue </color>
<element name="age" type="positiveInteger"/>
<element name="height" type="float"/>
<element name="color">
<simpleType base="xsd:string">
<enumeration value="green">
<enumeration value="blue">
</simpleType>
</element>
<simpleType name='sizes'>
<list itemType='decimal'/>
<simpleType>
with example data
<cerealSizes xsi:type='sizes'> 8 10.5 12 </cerealSizes>
SOAP messages are either
Most XML standard data type are represented by a Java data type
XML | Java |
---|---|
boolean | boolean |
byte | byte |
dateTime | java.util.Calendar |
double | double |
float | float |
int | int |
integer | java.math.BigInteger |
string | String |
Some types can't be represented since they don't exist in Java,
such as unsigned int
. If a type can be "nillable"
(that is, have a nil
value) and it would be a
Java primitive type, then it is wrapped in a Java class such
as Integer
.
A SOAP request consists of
A SOAP response is just like a request, except the body contains the result.
<?xml version="1.0" ?> <env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope"> <env:Header> <p:oneBlock xmlns:p="http://example.com" env:actor="http://example.com/Log"> :::: </p:oneBlock> <q:anotherBlock xmlns:q="http://example.com" env:actor="http://www.w3.org/2001/12/soap-envelope/actor/next"> :::: </q:anotherBlock> <r:aThirdBlock xmlns:r="http://example.com"> :::: </r:aThirdBlock> </env:Header> <env:Body > :::: </env:Body> </env:Envelope>
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope" >
<env:Body>
<m:reserveAndCharge
env:encodingStyle="http://www.w3.org/2001/12/soap-encoding"
xmlns:m="http://travelcompany.example.org/" >
<n:name xmlns:n="http://mycompany.example.com/employees">
John Q. Public
</n:name>
<o:creditCard xmlns:o="http://mycompany.example.com/financial">
<o:number>123456789099999</o:number>
<o:expiration>2005-02</o:expiration>
</o:creditCard>
</m:reserveAndCharge>
</env:Body>
</env:Envelope>
<Request>Response
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope" >
<env:Body>
<m:reserveAndChargeResponse
env:encodingStyle="http://www.w3.org/2001/12/soap-encoding"
xmlns:m="http://travelcompany.example.org/" >
<m:confirmation>
<reference>FT35ZBQ</reference>
<viewAt>
http://travelcompany.example.org/reservations?code=FT35ZBQ
</viewAt>
</m:confirmation>
</m:reserveAndChargeResponse>
</env:Body>
</env:Envelope>
application/soap
POST /Charging HTTP/1.1
Host: travelcompany.example.org
Content-Type: application/soap; charset="utf-8"
Content-Length: nnnn
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope" >
<env:Body>
<m:reserveAndCharge>
::::::
</m:reserveAndCharge>
</env:Body>
</env:Envelope>
HTTP/1.1 200 OK
Content-Type: application/soap; charset="utf-8"
Content-Length: nnnn
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope" >
<env:Body>
<m:reserveAndChargeResponse>
::::::
</m:reserveAndCharge>
</env:Body>
</env:Envelope>
read the SOAP request from a file
open HTTP connection to web service
POST request to service
read response
write response to stdout
Service host: www.soaplite.com
Service name: Demo
Methods:
String hi()
String bye()
use SOAP::Transport::HTTP;
SOAP::Transport::HTTP::CGI
-> dispatch_to('Demo')
-> handle;
package Demo;
sub hi {
return 'hello world';
}
sub bye {
return 'goodbye, world';
}
Make this available as e.g. CGI script hibye.cgi
use SOAP::Lite;
print SOAP::Lite
-> uri('http://www.soaplite.com/Demo') # Demo service
-> proxy('http://services.soaplite.com/hibye.cgi') # script for service
-> hi()
-> result;
.../jakarta-tomcat/webapps/axis
jws
extension to
the toplevel of the Axis directory e.g.
.../jakarta-tomcat/webapps/axis/Converter.jws
http://localhost:8088/axis/Converter.jws
Converter.jws
would contain
public class Converter implements java.rmi.Remote {
public float inchToMM(float float_1) throws
java.rmi.RemoteException {
float _retVal = float_1 * 2.54;
return _retVal;
}
public float mmToInch(float float_1) throws
java.rmi.RemoteException {
float _retVal = float_1 / 2.54;
return _retVal;
}
}
$TOMCAT_HOME/webapps/axis/Converter.jws
#!/usr/bin/perl
use SOAP::Lite;
print SOAP::Lite
-> uri('http://localhost/Converter') # Converter service
-> proxy('http://localhost:8088/axis/Converter.jws') # Axis service
-> inchToMM(1.0)
-> result;
Service
and Call
Call.invoke()
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
public class TestClient {
public static void main(String [] args) {
try {
String endpoint =
"http://nagoya.apache.org:5049/axis/services/echo";
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpoint) );
call.setOperationName(new QName("http://soapinterop.org/", "echoString"));
String ret = (String) call.invoke( new Object[] { "Hello!" } );
System.out.println("Sent 'Hello!', got '" + ret + "'");
} catch (Exception e) {
System.err.println(e.toString());
}
}
}
WSDL2Java
generates client-side stubs
ConverterInterface
service, it generates
ConverterInterface.java
- the Java interface you use
ConverterInterfaceServiceLocator.java
- finds the
service and returns a ConverterInterfaceService.java
ConverterInterfaceService.java
- has a method
to get the client HOPP
ConverterInterfaceSoapBindingStub.java
-
an implementation
of the interface which is the client part of the HOPP
public class Tester
{
public static void main(String [] args) throws Exception {
// Make a service
ConverterInterfaceService service = new ConverterInterfaceServiceLocator();
// Now use the service to get a stub which implements the SDI.
ConverterInterface port = service.getConverterInterface();
// Make the actual call
float mm = port.inchToMM(1.0);
}
}
#!/usr/bin/perl
use CGI;
use SOAP::Lite;
$query = new CGI;
# get CGI query params
$mm = $query->param('mm');
$inch = SOAP::Lite
-> uri('http://localhost/Converter') # Demo service
-> proxy('http://localhost/cgi-bin/converter.pl') # script for service
-> mmToInch($mm)
-> result;
print $query->header();
print $query->start_html(-title=>'Converter result');
print "<p>
$mm millimetres is $inch inches
</p>
</body> </html>";
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Draft//EN">
<html> <head>
<title>Converter Client</title>
</head>
<body>
<h1>Converter Client</h1>
<form action="http://localhost/cgi-bin/converter-bridge.pl" method="post">
Millimetres
<input type="text" width="10" name="mm">
<input type=submit value="mm To Inch">
</form>
</html>
By way of example, consider a database query on persons. A SOAP request might look like (simplified):
POST url HTTP/1.1
HOST: ...
CONTENT-LENGTH: ...
CONTENT-TYPE: ...
SOAP-ACTION: ...
<Envelope>
<Body>
<CUSTOMERS>
</CUSTOMERS>
</Body>
</Envelope>
with response:
HTTP/1.0 200
CONTENT-TYPE: text/xml
CONTENT-LENGTH: ..
<?xml version="1.0"?>
<Envelope>
<Body>
<CUSTOMERS>
<CUSTOMER>
<ID>11</ID>
<FIRSTNAME>Julia</FIRSTNAME>
...
</CUSTOMER>
...
</CUSTOMERS>
</Body>
</Envelope>
The REST version could be to issue a request:
GET http://host/CUSTOMERS
with response consisting of addresses:
<resources
xmlns:xlink="http://www.w3.org/1999/xlink">
<resource
xlink:href="http://host/CUSTOMER/0/">0
</resource>
<resource
xlink:href="http://host/CUSTOMER/1/">1
</resource>
<resource
xlink:href="http://host/CUSTOMER/2/">2
</resource>
<resource
xlink:href="http://host/CUSTOMER/3/">3
</resource>
</resources>
Further requests are then made of addresses such as:
GET http://host/CUSTOMER/1
with response:
<resources xmlns:xlink="http://www.w3.org/1999/xlink">
<ID>11</ID>
<FIRSTNAME>Julia</FIRSTNAME>
...
</resources>
which consists of primitive values.