Getting started with Middleware Web Services
Background and Basic Requirements
The general idea is that a web service is a client/server application
which exchanges data in the form of XML documents. The protocol for
doing this is called "SOAP" and all data is transported with HTTP. Other
transport protocols can be used, but HTTP seems to be the most prevalent.
The client and server need not be of the same architecture, operating
system or programming language or even on the same network.
Web Services provide methods to applications as if those methods were
from libraries installed locally.
In most programming environments, a "SOAP" object is instantiated and
methods are called upon it using XML documents as inputs and outputs.
Consider a fictional identifier translation web service:
There is a method which accepts as input an XML document which represents a list
of PeopleSoft "emplids." That method will do some processing and return an
XML document which represents a list of Internet email addresses
associated with those emplids. The application developer does need not to be
concerned with the backend database operations which would most likely involve
both Oracle (PeopleSoft) and LDAP (Sun One Directory Server 5.2).
All the developer has to do is first format the input XML correctly, pass it
to the SOAP client then extract and process the response XML. It is difficult
to learn how to do this at first in most languages since the XML is abstracted
by object orientation, however in the long run it is easier then attempting
to manage Oracle and LDAP connections and the structure of data in those stores.Middleware would write and maintain the method that does the translation from emplids
to email and formats the output XML appropriately. Application developers are
left to focus on what their business rules are and the proper format of the
input XML.
Learning web services is a two step process of first figuring how the environment
makes and configures SOAP objects and connections and then learning how to
extract data from returned objects which represent XML documents.
Middleware has worked with SOAP clients in Perl,PHP,Java,Visual Basic 6.0
and VBScript(Microsoft Soap Toolkit 2.0). Middleware is most familiar
with Perl based web services clients and can offer the most assistance
if Perl is used as the client.There are a few technical requirements of the SOAP client software and
these are:
- The client must be able to support the use of SSL Client certificates.
(The security model of our server environment requires this.) If the client
tool kit does not support client certificate exchange, HTTP Basic
Authentication can be used if supported.
- The client must be able to connect to services utilizing a WSDL file.
At this point of time, support for UDDI discovery services is not necessary.
- The client must support the document/literal wrapped style of SOAP.
This is essentially the way Microsoft .NET works and is now a standard.
- The client must have some sort of XML processing capability.
With this in mind, some SOAP clients will work whereas others will not,
even though they advertise "SOAP/web services" compatibility.
Our services operate as a shared infrastructure, so we try to avoid
writing services that are specific to one particular project or
application. We aim to write libraries of reusable code that can fit
multiple sets of UW business models and rules.
WSDL Files, Toolkits and Web Services:
Okay, here's how you find out the information you need to know.
First go to a regular web browser and load in the WSDL file.
The WSDL file describes which methods and XML documents a web service provides.
http://rpctest.services.wisc.edu/Test.wsdl
It is important that you understand the components of a
WSDL file, there are many resources on the Internet. (Google it.)
But here's a quick HOWTO on extracting variables from
WSDL files which you will need to specify when configuring
your client's toolkit.
Go all the way to the bottom of the NetID.wsdl until you find the <wsdl:service>
element. There you will find the service name and port names.
Write these down, they are usually specified in most
toolkits at the same time the url of the WSDL is specified.
Go back up a bit to the <wsdl:binding> element. There you
will find all of the operations. These are the methods
or operations (library functions) that can be called.
The notion of a class (e.g. a collection of methods) is called
a portType in wsdl. You can find that by looking for the
<wsdl:portType> element. Note that the method names are here
as well. This is usually only important for .NET and
Java clients as classes are built from the port types.
Check out the <wsdl:types> section for the format of XML input
and output messages. Each method will have it's own format
depending on the information it accepts or returns. This
is expressed in XML Schema, which is something useful to
be familiar with.
Some toolkits do all of this for you without needing to generate
stub classes, shims or any other go-between and it works like
this:
- Instantiate toolkit object with WSDL file, service name and desired port.
- Use XML libraries to make objects which represent XML
- Call web service methods on the toolkit object, pass XML object.
- Process the response using XML libraries.
Toolkits which do this:
- Microsoft Soap ToolKit 3.0/2.0 (for VB6, VC++ 6)
- PHP PEAR
- Perl SOAP::Lite
Toolkits that generate proxy/stub classes which require
more programming effort:
- Microsoft .NET (!)
- Apache Axis
Technical Details about our Web Services and WSDL files:
- There is only one portType (class) per WSDL file.
It's name is "<service>PortType" eg NetIDPortType
- There is only one service and it's name is
"<service>Service" eg NetIDService
There are usually two publicly accessible ports defined for the service.
One port describes a service endpoint/proxy for webservices which talk to each other. (eg via localhost)
The other port describes the 'public' interface by which clients use the service over SSL.
You will have to specify that you want to use the https port. It's usually named "<service>ServicePort" eg
NetIDServicePort. You can't use the local port.
If you have a toolkit that builds static code/classes from the WSDL in the ITE, then you move that code to
production, it will still talk to the ITE (or try to) unless you rebuild the code from the production WSDL.
The WSDL file locations are the same in production as in the ITE, however the service endpoints are different.
NOTE: In production, endpoint is "https://rpc.services.wisc.edu/cert"
The namespace / uri is http://rpc.services.wisc.edu/UWDS/WebService/<service>
These uri's are used for defining namespaces and aren't actual
web addresses where you can be expected to find things.,/p>
The style of SOAP we do is not XML RPC.
We do "Document Literal Wrapped" aka .NET style.
This means that our responses are XML documents
with no RPC style encoding. (eg 'literal') The
documents are wrapped in an element called
<operation>Response eg
<getQuestionsResponse>...</getQuestionsResponse>
The document elements may or may not have a
namespace prefix depending on the type of
document returned.
- We require the use of SSL.
Client Certificates are used for authentication.
- MST's Certificate Authority will issue your client certificate.(Click here for instructions.)
Debugging
One of the best debugging aids is to actually look at the XML and HTTP
headers on the wire as they go out. It's often easier to build a
client looking at an example capture that works, then tweaking your
code to produce the same result. Perl's SOAP::Lite client has a great
debug switch that'll do just that.
Sample Code
#!perl
use UWDS::WebService;
use SOAP::Lite on_debug => sub { print @_; };
my $service = "NetID";
my $wsdl = "http://localhost/" . $service . ".wsdl";
my $servicename = $service . "Service";
my $port = $service . "LocalServicePort";
my $soap = SOAP::Lite->service($wsdl,$servicename,$port);
my %hash = ( uid=>"jeremyscott");
my @result = $soap->getQuestions(UWDS::WebService->format_soapdata(\%hash));
foreach my $question (@result) {
print $question . "\n";
}
POST http://localhost/services
Accept: text/xml
Accept: multipart/*
Content-Length: 497
Content-Type: text/xml; charset=utf-8
SOAPAction: "UWDS/WebService/NetID#getQuestions"
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<getQuestions xmlns="http://rpc.services.wisc.edu/UWDS/WebService/NetID">
<uid>jeremyscott</uid>
</getQuestions>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
HTTP/1.1 200 OK
Connection: close
Date: Fri, 05 Mar 2004 07:03:37 GMT
Server: Apache/1.3.29 (Unix) mod_perl/1.29
Content-Length: 638
Content-Type: text/xml; charset=utf-8
Client-Date: Fri, 05 Mar 2004 07:03:37 GMT
Client-Peer: 127.0.0.1:80
SOAPServer: SOAP::Lite/Perl/0.55
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<getQuestionsResponse xmlns="http://rpc.services.wisc.edu/UWDS/WebService/NetID">
<result>What is your quest?</result>
<result>What is your favorite colour?</result>
<result>What is the airspeed of a coconut-laden swallow?</result>
</getQuestionsResponse>
</SOAP-ENV:Body>
What is your question?
What is your favorite colour?
What is the airspeed of a coconut-laden swallow?
|