I have composed this list of questions partly from my own learning process and partly by perusing questions from the SOAP User mailing list. Corrections and suggestions for new questions are always welcome. Please forward new questions - preferably with answers! - or errors to the SOAP Developer mailing list.
See also:
Namespaces
SOAP uses a few different namespaces for different elements and attributes depending on the role that the data item in question plays in the message formatting, handling and/or encoding. Looking at the Envelope element of a typical SOAP message, we see the following namespace declarations:
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
where 1) is the SOAP Envelope namespace, 2) is the SOAP Encoding namespace, 3) is the XML Schema Instance namespace and 4) is the XML Schema Definition namespace. SOAP defines the first two namespaces and refers to the second two. These namespaces reflect how all data type definitions in SOAP are delegated to XML Schema.
The SOAP Envelope
namespace defines the Envelope
, Header
and Body
element names and the encodingStyle
,
actor
and mustUnderstand
attributes.
The SOAP Encoding namespace defines the Array element and the arrayType attribute used to encode Vector and Array java objects. This encoding technique is recommended for any linear list of objects. I.e. Java 2 Collection objects can and probably should use this encoding approach.
The XML Schema Instance namespace defines the type
attribute which identifies the data type of an element.
The XML Schema namespace defines several datatypes used
as values of the xsi:type
attribute. Examples
include: int
, String
, double
,
and ur-type
.
The short answer is yes, but only a little.
The long answer is that the serialization registry is necessarily based on qualified names. Thus, if you are marshalling/unmarshalling Java objects into XML Elements, those element names will have to be namespace qualified.
Although it is technically possible to just use one of the SOAP namespaces, it probably isn't a good idea unless the element name is actually defined in that namespace (i.e. defined by the SOAP specification).
If you already have one or more namespaces, use them. If you
need to generate a new namespace, use something like
urn://acmecorp.com/whatever/
as the URI when you
register an element name. See
Serialization below.
The Apace SOAP library will generate namespace prefixes as needed to make sure that all necessary namespaces are declared. If the same namespace gets declared twice with two different prefixes, the qualified names should still match with any namespace aware software. A qualified name is the combination of the namespace URI plus the local part of the element name (the part after the prefix).
<SOAP-ENV:Envelope
...xmlns:acme="urn://acmecorp.com/namespace"...>
...
<ns3:GetData xmlns:ns3="urn://acmecorp.com/namespace">
</ns3:GetData>
...
In this example, the prefix can be "ns3" or "acme". Either way, it refers to the same namespace and, thus, for any local name, the same element or attribute.
Serialization
You need to map the Java object to a SOAP XML Element name. This is done using an XMLJavaMappingRegistry. Typically, you'll want to use the derived class SOAPMappingRegistry which, among other things, supports primitive types, Array and Vector objects, and the ability to be configured via an XML file (DeploymentDescriptor.xml).
Although not required by the SOAP specification, the Apache library requires that all XML Elements be namespace qualified via the QName utility class. You can use (almost) anything for the QName. You might think of the first piece as a "path", and the second piece as a "SOAP object." You might want to use something like the following:
SOAPMappingRegistry smr = new SOAPMappingRegistry();
MyObjectSerialzier myObjSer = new MyObjectSerialzier();
smr.mapTypes( Constants.NS_URI_SOAP_ENC,
new QName("urn://myown.com/objects/", "MyObject"),
Object.class, myObjSer, myObjSer );
Then, when you deploy the service that you are calling, you must have a mapping entry that looks something like the following:
<isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="urn://myown.com/objects/" qname="x:MyObject"
javaType="com.myown.objects.MyObject"
java2XMLClassName="com.myown.soap.MyObjectSerializer"
xml2JavaClassName="com.myown.soap.MyObjectSerializer"/>
On the server side, all of this (the deployment map) basically says that when you have a com.myown.objects.POBean object to return to the caller, you want the SOAP server to use the bean serializer to translate it into a "urn://myown.com/objects/MyObject" SOAP object and send it to the client.
One the client side, all of this (the mapTypes() method) says that when you get a SOAP "urn://myown.com/objects/MyObject" object from the SOAP server, you would like to use the serializer called myObjSer to translate the SOAP object into a Java MyObject object.
The main thing you have to do is make sure that the xmlns and qname values in your deployment descriptor file (or their equivalents in the GUI) match the values you use in your QName object.
Note, that it is often not necessary to write your own Serializer or Deserializer. If your class has a get and a set for each attribute that needs to be marshalled, you can just use the Apache SOAP BeanSerializer class.
The Apache SOAP library uses the SOAP-ENV:encodingStyle
attribute as a lookup qualifier when locating a Serializer
for a Java object or a Deserialzier
for an XML element.
The SOAP specification allows the encodingStyle
attribute to hold
multiple URIs which denote increasingly general encoding rules.
What isn't defined, however, is how a SOAP processor is to determine
which encoding style to apply. Consequently, the Apache SOAP library
does not support this syntax and will always treat the encodingStyle
attribute value as a single URI reference.
This encoding style is identified by the SOAP Encoding URI
http://schemas.xmlsoap.org/soap/encoding/
and is
described fully in section 5
of the SOAP specification.
Use BeanSerializer. Either add a mapping for date in the deployment xml file or call SOAPMappingRegistry.mapTypes() in your application. A more "correct" DateSerializer is planned that serializes using the ISO date format.
Date objects should be converted to xsd:date
or
xsd:timeInstant
to be SOAP compliant. The SOAP spec says, "For simple types, SOAP adopts all the types
found in the section
Built-in datatypes
of the XML Schema Part 2: Datatypes", but not all have been implemented.
The encoding style of a Call return is determined by the encoding style of the Request. DOM Elements use Literal XML encoding. For example, if a service accepts one String Parameter and returns an Element, just set the encoding style for the call to "http://xml.apache.org/xml-soap/literalxml" and the encoding style for the parameter to "http://schemas.xmlsoap.org/soap/encoding". Thus, part of your client code would look like:
...
Call call = new Call();
call.setTargetObjectURI("urn:someservice");
call.setMethodName("callmethod");
call.setEncodingStyleURI( Constants.NS_URI_LITERAL_XML );
String strparam = "joebob";
Vector params = new Vector();
params.addElement( new Parameter( "strparam", String.class,
strparam, Constants.NS_URI_SOAP_ENC ) );
...
Service Handlers
Every SOAP message has primary intended recipient. An actor is a different message recipient that may recieve the message, and possibly modify it, before forwarding it on to either the next actor or the final, intended recipient.
SOAP allows Header
entries to be addressed to specific
actors with the SOAP-ENV:actor
attribute. This attribute
contains the URI that uniquely identifies the actor.
Brought to you by the same folks that brought you UDDI, is the Web Services Definition Language. WSDL is an XML schema that defines documents, in XML format, that describe SOAP services. There is an IBM alphaWorks toolkit that generates Java service client libraries and service handler skeletons from a WSDL document. See the WSDL specification and the IBM toolkit.
For Tomcat: put the soap.jar and samples classes on the system classpath (i.e, in $TOMCAT_HOME/classes,lib) rather than in webapps/soap/WEB-INF
Apache SOAP has worked under every version of WebSphere from 1.1 to 3.02. It will, however, work out of the box on WebSphere 3.5 with fixpak 2 applied. The WebSphere install instructions for that level are part of the current SOAP kit. You can browse them online. Be sure to check the following items:
http://aaa.bbb.ccc.ddd:port/soap/servlet/rpcrouter
.
Yes, but you need to install a patch to the MS SOAP package. One of the well-known interoperability problems between Apache 2.0 and MS Soap is that MS clients do not send type information with each parameter, and the Apache soap server will reject such requests.
James Snell has provided a patch adding the typing. It can be found at SOAP-WRC web site.