I described WSDL in Part 1 of this series of articles. WSDL describes the interface of web services. Web service owners will implement their interfaces using SOAP. Therefore WSDL services will actually exist as SOAP services. Once the web service user has the WSDL file, he or she knows the interface details. He or she will now use SOAP to communicate with the web services.
Think of web services as objects that you can expose through WSDL interfaces and access remotely across the Internet using SOAP. Since services are objects, there must be some properties related to each service and behaviors for invocation of each service. SOAP messages are XML documents that may work over HTTP.
Business-to-business (B2B) and application-to-application (A2A) requirements dictate that enterprises communicate with each other in order to exchange information. This concept is used in B2B, workflow, and across the enterprise integration. For example, consider a vertical supply chain where an enterprise will need to invoke the services of its suppliers in order to fulfill the requirements of its customers. Some suppliers will need to go further down the supply chain and invoke services of other enterprises.
It is evident that interoperability is of paramount importance in such applications. Any single enterprise will implement only one end of the SOAP communication channel. The other end will be somebody from anywhere on the Internet.
Integration and interoperability between enterprises has been a challenging task for both software engineers and enterprises in last few years. Platform dependency was also a big problem in achieving integration and interoperability. SOAP is the simplest mechanism yet to achieve integration and interoperability between enterprises.
With a basic understanding of SOAP and its purpose, I will now extend the discussion toward its architecture to help you learn the inside story. Refer to Figure 1
where you can identify the following components of a typical SOAP communications
architecture:
- SOAP client
- SOAP server
- actual service
Figure 1. Components of a typical SOAP communication architecture

Let me try to explain the architectural role of each of above mentioned entities.
The following discussion refers to Figure 1.
The SOAP client is a SOAP-aware machine and is capable of generating and sending SOAP requests to a SOAP server over HTTP. A SOAP request is a type of SOAP message; normally there are only two types of SOAP messages: a SOAP request is what a SOAP client sends to a SOAP server and a SOAP response is what a SOAP server sends to a SOAP client in response. Listing 1 is typical SOAP request, see Listing 2 to review a SOAP response.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" >
<SOAP-ENV:Body>
<m:getListOfModels xmlns:m = "uri reference" >
</m:getListOfModels>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
|
The SOAP server is also a SOAP-aware machine and has the capability to accept requests from SOAP clients and author appropriate responses. These encoded responses go back to the requesting SOAP client. Inside the SOAP server there are three entities:
- service manager
- deployed services list
- XML translator
The service manager is responsible for managing services against requests. Refer to the SOAP request
from Listing 1, where the element <m:getListOfModels xmlns:m="urn:MobilePhoneservice" > contains the name of the service. The service manager will read name of the SOAP service that the SOAP client wants to invoke and check whether the required service actually resides on this SOAP server. To that end, it will consult the deployed services list, a list of all services that the SOAP server hosts. If yes, the server
manager will pass on the SOAP request to the XML translator. The XML translator is then responsible for converting the XML structure of the SOAP request to that of a programming language (for example, Java programming language) that programmers used to implement the actual service. It is also responsible for converting the response from the actual service back to the XML Structure of the SOAP response. Refer to Listing 2 for an illustration of the SOAP response.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<m:getListOfModelsResponse xmlns:m="urn:MobilePhoneservice">
<Model>M1</Model>
<Model>M2</Model>
<Model>M3</Model>
</m:getListOfModelsResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
|
The box labeled actual service in Figure 1 is the location where actual service resides. The service implementation may be in the form of COM components or JavaBeans components, for example. The XML translator is responsible for translating XML structures into proper method invocation calls. When the XML translator invokes some method of actual service implementation, the method will perform its job and return the resulting information back to the XML translator.
Have a look at the arrow in Figure 1, which connects XML translator to the actual service. Both ends of this arrow are within the same enterprise, which means the same organization has the control over interfaces at both ends of communication. Compare this to arrow between SOAP client and SOAP server, which crosses the boundary of an enterprise. This is exactly the purpose of SOAP.
SOAP request response mechanism
When SOAP client sends SOAP message to a SOAP server it uses HTTP protocol for transportation. This is called SOAP Binding with HTTP. When SOAP server receives the message, it hands it over to service manager. It checks the deployed services list for the required service in SOAP message. If it cannot locate the requested service, it responds back to SOAP client with request failure. But if the service is available, control is transferred from service manager to XML translator, which performs
appropriate language conversion and accesses the actual service implementation. Service Implementation will process the request and sends results back to XML translator. XML translator converts it to SOAP response (XML Document) that is understandable by SOAP client. Again HTTP binding is used for transportation of SOAP response.
It is time to look at SOAP binding with HTTP in detail.
When you bind SOAP with HTTP or operate SOAP over HTTP, you actually add HTTP headers to the SOAP requests and responses. Listing 1 is the structure of a typical SOAP request, while Listings 3, 4, 5 and 6 are complete HTTP requests to demonstrate the addition of HTTP headers to Listing 1. Similarly, Listing 7 is a complete HTTP response corresponding to the SOAP response from Listing 2.
Whenever you use SOAP over HTTP, Content-Type field must be text/xml. You'll now see the details of Listing 3 through Listing 7.
You can use SOAP in combination with the HTTP request method POST. In order to send a SOAP HTTP request, you need to supply a SOAPAction header field in HTTP.
SOAPAction specifies the intent of SOAP request. Servers (such as firewalls that filter SOAP request messages in HTTP) can use the value of the SOAPAction to make decisions.
HTTP client must use this header field when issuing a SOAP HTTP request. SOAPAction can have one of the following values:
SOAPAction: "URI-Reference"
SOAPAction: "filename"
SOAPAction: ""
SOAPAction:
POST /Vendors HTTP/1.1 Host: www.mobilephoneservice.com Content-Type:"text/xml";Charset="utf-8" Content-Length: nnnn SOAPACtion:"www.mobilephoneservice.com/Vendors/MobilePhoneservice#getListOfModels" <?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <m:getListOfModels xmlns:m="urn:MobilePhoneservice" > </m:getListOfModels> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
Listing 3 contains following URI Reference in SOAPAction:
www.mobilephoneservice.com/Vendors/MobilePhoneservice#getListOfModels
This SOAPAction represents two things. First is the address of a particular SOAP deployment: www.mobilephoneservice.com/Vendors/MobilePhoneservice
Second is a fragment identifier that gives the name of the method of our interest ( #getListOfModels ).
POST /Vendors HTTP/1.1 Host: www.mobilephoneservice.com Content-Type:"text/xml";Charset="utf-8" Content-Length: nnnn SOAPAction:"MobilePhoneservice#getListOfModels" <?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <m:getListOfModels xmlns:m="urn:MobilePhoneservice" > </m:getListOfModels> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
Listing 4 contains a filename ( MobilePhoneservice#getListOfModels ) in SOAPAction.
The MobilePhoneservice file must be present at the host URI ( www.mobilephoneservice.com/Vendors ).
This host URI is a combination of the host field in the HTTP header ( www.mobilephoneservice.com ) and the folder name, /Vendors .
POST /Vendors HTTP/1.1 Host: www.mobilephoneservice.com Content-Type:"text/xml";Charset="utf-8" Content-Length: nnnn SOAPAction:"" <?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <m:getListOfModels xmlns:m="urn:MobilePhoneservice" > </m:getListOfModels> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
Listing 5 contains an empty string ("") in the SOAPAction. The empty string value represents that intent of SOAP is the same as Host URI (www.mobilephoneservice.com/Vendors).
POST /Vendors HTTP/1.1 Host: www.mobilephoneservice.com Content-Type:"text/xml";Charset="utf-8" Content-Length: nnnn SOAPAction: <?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <m:getListOfModels xmlns:m ="urn:MobilePhoneservice" > </m:getListOfModels> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
Listing 6 contains no value for SOAPAction. This indicates that there is no information about the intent of the message.
There can be one of the two possible types of SOAP responses:
- A successful SOAP operation producing SOAP results
- An unsuccessful SOAP operation resulting in a SOAP fault message
HTTP/1.1 Content-Type:"text/xml"; Charset="utf-8" Content-Length: nnnn <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <m:getListOfModelsResponse xmlns:m = "URI-Reference"> <model>m1</model> <model>m2</model> </m:getListOfModels> </SOAP-ENV:Body> |
Listing 7 is the first case where you get a meaningful result from the SOAP server.
Listing 8 is a typical SOAP fault message. SOAP HTTP responses follow the semantics of the HTTP status codes for communicating status information in HTTP. In the case of a SOAP error while processing a request, the SOAP HTTP server must issue an HTTP 500 "Internal Server Error" response including a SOAP message in the response with the SOAP fault element.
HTTP/1.1 500 Internal Server Error Content-Type: "text/xml"; Charset="utf-8" Content-Length: nnnn <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <SOAP-ENV:Fault> <faultstring>Failed to process the request</faultstring> </SOAP-ENV:Fault> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
HTTP is not the only solution for binding SOAP messages. You can use other mechanisms like SMTP for SOAP binding where HTTP is not suitable. Binding SOAP to SMTP, you can establish a one-way transport route. Two one-way messages can be used to establish request/response communications. To send a SOAP message with SMTP, you will need to perform the following steps:
- Use of the MIME-Version header field
The MIME-Version uses a version number to differentiate between different MIME versions. It allows mail-processing agents (such as a POP server) to distinguish between mail messages that are generated by older versions and new versions. Refer to Listing 9 which uses a MIME-Version header field.TO: <info@waxsys.com> From: <abc@punjab.com> Reply-To: <abc@punjab.com> Date: SAT, 2 Feb 2002 16:00:00 Message-Id: <4FAB345C8D93E93B7A6E9@punjab.com> MIME-Version: 1.0 Content-Type: text/xml; charset=utf-8 Content-Transfer-Encoding: QUOTED-PRINTABLE <?xml version ="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <prnt:echoString xmlns:prnt="http://waxsys.com"> <msgString>Put your mail Message</msgString> </prnt:echoString> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
- Use of the Content-Type header field:
The Content-Type is used to identify the type of data in the message body. In case of SOAP message Content-Type should have a value "text/xml". Refer to Listing 9 , which uses Content-Type. - Use of Content-Transfer-Encoding field:
Content-Transfer-Encoding is used to specify the type of transfer encoding, that is, whether data that you want to transfer is in character or binary format. Listing 9 uses Quoted-Printable encoding that corresponds to printable characters according to the ASCII character set. It encodes the data in such a way that the mail transport agent is unlikely to modify the resulting octets. Refer to Listing 9, which uses Content-Transfer-Encoding.
A SOAP message is nothing but an XML document that consists of a mandatory SOAP Envelope having an optional SOAP Header and a mandatory SOAP Body.
Elements of a SOAP Schema:
- Envelope
- Header
- Body
- Fault
Envelope:
The Envelope is the top element that represents a SOAP message. This element must be present in order to send SOAP message. The Envelope uses SOAP namespace identifier
http://schemas.xmlsoap.org/soap/envelope/
that is essential. If the Envelope contains the wrong namespace, an error will be generated regarding the version of Envelope namespace.
Listing 10 is an empty Envelope. You call it an "empty envelope" to emphasize that it should eventually contain a "letter"
(perhaps a business letter) before you can send it by "post". The "letter" in SOAP schema is referred to as a "SOAP Body" and HTTP POST
(as discussed in the section on HTTP binding with SOAP) is the transport mechanism.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> </SOAP-ENV:Envelope> |
Header:
The SOAP Header is optional. You can directly wrap a SOAP Body inside a SOAP Envelope and skip the header altogether.
Headers provide a mechanism to extend functionality of SOAP message. For example, authentication is a typical extension provided with
SOAP Header entries. In this case there will be an authentication framework, which will use SOAP
as a lower level transport. Refer to Listing 11 to see header implementation in SOAP.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> <m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1"> </m:Order> </SOAP-ENV:Header> </SOAP-ENV:Envelope> |
Body:
The Body element will contain the actual message that you want to send. It is a mandatory element and its child elements normally belong to a user-defined namespace.
Listing 12 shows a SOAP message that refers to a user-defined namespace "u".
The Body element is a container for mandatory information. This element must be present in the SOAP message and must be an immediate
child element of the SOAP Envelope element. It must follow the SOAP header element directly. If the Header element is not present then
it should follow the Envelope element directly. The body may contain child elements and they may be namespace-qualified.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> <m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1"> </m:Order> </SOAP-ENV:Header> <SOAP-ENV:Body> <u:GetPrice xmlns:u="some URI" > <model>m1</model> </u:GetPrice> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
Fault:
This element indicates an error message. It should appear as a body entry and must
not appear more than once within a Body element. Normally, the Fault element will appear in
a SOAP response message to indicate that there was something wrong with the SOAP request.
Sub elements of Fault:
faultcode(identification of fault)faultstring(description of fault)faultactor(identifies who caused this fault)detail(detail of the error. It is normally an application specific error, that is, it corresponds to user-defined namespace that was used in the body of a SOAP request)
Listing 13 is a typical fault message.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> <m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1"> </m:Order> </SOAP-ENV:Header> <SOAP-ENV:Body> <SOAP-ENV:Fault> <faultcode>SOAP-ENV:Server</faultcode> <faultstring>Not necessary information</faultstring> <detail> <d:faultdetail xmlns:d = "uri-referrence"> <msg> application is not responding properly. </msg> <errorcode>12</errorcode> </d:faultdetail> </detail> </SOAP-ENV:Fault> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
A SOAP request for the WSDL file from Part 1
Having explained the general syntax of a SOAP message (request and response),
I'll show how to develop a SOAP request for your MobilePhoneservice of Part 1 of this series
of articles. You designed a complete WSDL interface explaining MobilPhoneservice in Part 1.
Mobile Company offers two methods in MobilePhoneservice, one is getListOfModels() and the
other is getPrice(modelNumber). GetListOfModels() takes no parameter but returns a list
of Mobile models while getPrice(modelNumber) takes a parameter modelNumber and returns price
of requested model. You'll document it in the form of a SOAP request but first I'll show you the generic form of SOAP request and response.
<SOAP-ENV:Envelope xmlns:SOAP-ENV ="SOAP schema's URI" <SOAP-ENV:Body> <Instance:"Method Name" xmlns:Instance= "URI where method is located"> <parameter1>value</parameter1> <parametern>value</parametern> </Instance:"Method Name"> </SOAP_Envelop:Body> </SOAP-ENV:Envelope> |
A single SOAP request or response can only specify one method of a service. The generic form of your envelope containing
a SOAP request takes the form of Listing 14. Compare this generic form to the getListOfModels() method invocation
request in Listing 16. In Listing 16, I have provided names for the method and URI.
As there were no parameters required with getListOfModels() , so
<m:getListOfModels> is an empty element in Listing 16.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <Instance:"Method Name"+"Response" xmlns:Instance="URI where method is located"> <return> <responseparameter1>value</responseparameter1> <responseparametern>value</responseparametern> </return> </Instance: "Method Name"+"Response"> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
Listing 15 is a generic SOAP response. The Apache SOAP server adds the "Response" keyword at the
end of a method name and encloses the return value in the <return> element as an immediate child method element.
If the return value is a complex structure then the <return> element contains one or more <item> elements. Compare
Listing 15 with Listing 17, which is the actual response from the getListOfModels() method.
Listing 17 contains a list of items as a Vector data type, which is the return parameter.
Similarly Listings 18 and 19 shows SOAP request and response against getPrice()
method of MobilePhoneservice.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <m:getListOfModels xmlns:m = "www.mobilphoneservice.com" > </m:getListOfModels> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope 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> <ns1:getListOfModelsResponse xmlns:ns1="urn:MobilePhoneservice" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <return xmlns:ns2="http://xml.apache.org/xml-soap" xsi:type="ns2:Vector"> <item xsi:type="xsd:string">M1</item> <item xsi:type="xsd:string">M2</item> <item xsi:type="xsd:string">M3</item> <item xsi:type="xsd:string">M4</item> <item xsi:type="xsd:string">M5</item> </return> </ns1:getListOfModelsResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
<SOAP-ENV:Envelope 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> <m:getPrice xmlns:m ="www.mobilphoneservice.com"> <modelNumber xsi:type ="xsd:String">M1</modelNumber> </m:getPrice> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope 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> <ns1:getPriceResponse xmlns:ns1="urn:MobilePhoneservice" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <return xsi:type="xsd:string"> 5000 </return> </ns1:getPriceResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
Deployment of WSDL-based services on a SOAP server
In this section you will deploy the WSDL service from Part 1 on an Apache SOAP server. The Apache SOAP toolkit keeps the WSDL service information in a deployment descriptor file. The deployment descriptor contains names of the WSDL service and all methods that it contains. The deployment descriptor will provide these names to SOAP server at runtime. The same deployment descriptor file also contains the address of the JavaBean component that implements the interface.
<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="URN:SERVICE-URN"> <isd:provider type="java" scope="Request" methods="EXPOSED-METHODS"> <isd:java class="IMPLEMENTING-CLASS"/> </isd:provider> <isd:faultListener>org.apache.soap.server.DOMFaultListener </isd:faultListener> </isd:service> |
Listing 20 is a skeleton deployment descriptor which needs three bits of information
(URN:SERVICE-URN, EXPOSED-METHODS and IMPLEMENTING-CLASS)
in order to be used as a WSDL-based service deployment descriptor.
URN:SERVICE-URN is the name of the service deployed. In this case it will be "urn:MobilePhoneservice".
EXPOSED-METHODS is a single-space separated list of methods offered by the service.
In this deployment it will be getListOfModels getPrice.
IMPLEMENTING-CLASS is the name of a Java class with a complete path. For example, samples.phonequote.MobilePhoneservice.
In this case while testing this application you had the following directory structure:
Apache SOAP server: C:\foo\SOAP-2_2
Mobile phone service implementation: C:\foo\SOAP-2_2\samples\phonequote\MobilePhoneservice
So the IMPLEMENTING-CLASS path refers to the directory where you installed SOAP toolkit. I have not provided the actual implementation of the Java classes. It depends on the business logic and can be anything.
<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="urn:MobilePhoneservice"> <isd:provider type="java" scope="Request" methods="getListOfModels getPrice"> <isd:java class="samples.phonequote.MobilePhoneservice"/> </isd:provider> <isd:faultListener> org.apache.soap.server.DOMFaultListener </isd:faultListener> </isd:service> |
Listing 21 is the completed deployment descriptor for the WSDL file from Part 1.
A SOAP client communicating with a SOAP server
I have provided a sample application to demonstrate the communication of a SOAP client with a SOAP server. For this purpose I have given three listings: Startup.html (Listing 22), Operation.html (Listing 23), and Execute.jsp (Listing 24).
StartUp.html (Listing 22) is a simple HTML file that presents a GUI to the user and asks which SOAP method he or she wants to invoke. The user will select a method of his choice.
<HTML> <BODY bgcolor="Teal"> <br/> <p align="center"> <font size="5" face="Arial" color="white"><b> SOAP method invocation demo </b></font> </p> <hr/> <font face="Arial" color="whitesmoke" size="3"> <br/><b> Click any of the method name to execute.<br/> 1. Get the List of all Models that we manufacture.... <a href="execute.jsp?index=1"> <font color="orange"> GetListOfModels </font></a> <br/> 2. Get the Price of any particular model...................... <a href="operation.html"> <font color="orange"> GetPrice </font></a> </b> </BODY> </HTML> |
Operation.html (Listing 23)will ask the user to provide parameters that go with the method invocation call.
<HTML> <BODY bgcolor="Teal"> <br/> <p align="center"> <font size="5" face="Arial" color="white"><b> GetPrice Operation input Form </b> </font></p> <hr/> <p align="center"> <form action="execute.jsp" method="POST"> <input type="hidden" name="index" value="0"> <table textColor="white"> <tr><td> <font color="whitesmoke"><b>Description :</b></font> </td><td><font color="whitesmoke"> Method GetPrice is used to Get Price of given Model Number</font> </td></tr> <tr><td> <font color="whitesmoke"><b>Parameter(s)</b></font></td><td> </td></tr> <tr><td><font color="whitesmoke">Model Number </td></font> <td><font color="whitesmoke"> <input type="text" name="parameter" size="30"> (required) </font> </td></tr> <tr><td> </td><td><input type="Submit" value="Invoke"> </td></tr> </font> </table> </form> </p> </BODY> </HTML> |
Execute.jsp (Listing 24)contains all the interesting code. It detects which method was called and which parameters are passed. It will then send a method invocation call to the remote server.
<%@ page language="java" import="java.util.Vector" %>
<%@ page import="java.net.MalformedURLException, java.net.URL" %>
<%@ page import="java.util.Vector" %>
<%@ page import="org.apache.soap.SOAPException,
org.apache.soap.Constants" %>
<%@ page import="org.apache.soap.rpc.Call, org.apache.soap.rpc.Response,
org.apache.soap.rpc.Parameter" %>
<%@ page import="org.apache.soap.transport.http.SOAPHTTPConnection" %>
<%@ page import="org.apache.soap.Fault" %>
<HTML>
<BODY bgcolor="Teal">
<br/>
<p align="center">
<font color="whitesmoke">
<%
boolean isParameter = false ;
SOAPHTTPConnection soapTransport = new SOAPHTTPConnection();
// Address of the remote server.
// Normally this should be dynamically passed and detected.
// We have hard coded it only for demonstration.
URL url = new URL ("http://localhost:8080/soap/servlet/rpcrouter");
// Build the call.
Call call = new Call ();
call.setTargetObjectURI ("urn:MobilePhoneservice");
call.setSOAPTransport (soapTransport);
call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
// We'll detect which method user selected
// and give a call accordingly.
// We'll pass parameters if present.
if (request.getParameter("parameter")!=null)
isParameter = true;
if (request.getParameter("index").equals("0"))
{
call.setMethodName("getPrice");
Vector params = new Vector();
String message = new String (request.getParameter("parameter"));
params.addElement (new Parameter("message", String.class,
message , null));
call.setParams(params);
}
else
call.setMethodName("getListOfModels");
Response resp = call.invoke ( url, /* actionURI */ "" );
out.println("<p align=left>
<font size=\"4\" face=\"Arial\" color=\"white\">
Response of [ "+call.getMethodName()+" ]
</font><hr/>");
// Check the response.
if (resp.generatedFault ()) {
Fault fault = resp.getFault ();
out.println("<b>Fault is:</b>"+ fault.getFaultCode ()
+" ["+fault.getFaultString ()+"]");
} else {
Parameter result = resp.getReturnValue ();
out.println("<b>Response is: </b>"+ result.getValue ()+"");
}
%>
<font>
</p>
</BODY>
</HTML>
|
In order to run this application, you will need two Apache SOAP servers.
One of the servers will talk to the user and hosts
Listings 22, 23 and
24.
The other server (also called the remote server) is the place where we will need to deploy your WSDL-based service from Part 1 (described in a previous section, "Deployment of WSDL-based services on a SOAP server").
You have hard-coded the address of the remote server, http://localhost:8080/soap/servlet/rpcrouter, in Execute.jsp (Listing 24) only for demonstration. In practise you will read it from the WSDL file.
Simple and compound data types in SOAP
In this section, I will start by explaining the distinction between simple and compound datatypes. I'll then show you how to encode them in SOAP.
Simple types include string, float, integer, enumeration, etc.
For example the "name" of a mobile phone will have a type of "string".
Compound types are formed from simple types but represent a single entity. For example, the "Student" type record may have different attributes, such as "studentName" of type "string" and "studentRollNumber"
of type "int" but represents a single entity, "Student".
Listing 25 includes a compound datatype named "Mobile".
You'll use this type later in your SOAP request.
1<? xml version="1.0" ?> 2<xsd:schema xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" 3 xmlns:xsd="http://www.w3.org/1999/XMLSchema"> 4 targetNameSpace= "www.mobilephoneservice.com/phonequote"> 5 <xsd:element name ="Mobile"> 6 <xsd:complexType> 7 <xsd:element name="modelNumber" type="xsd:int"> 8 <xsd:element name="modelName" type="xsd:string"> 9 <xsd:element name="modelWeight" type="xsd:int"> 10 <xsd:element name="modelSize" type="xsd:int"> 11 <xsd:element name="modelColor"> 12 <simpleType base="xsd:string"> 13 <enumeration value="white" /> 14 <enumeration value="blue" /> 15 <enumeration value="black" /> 16 <enumeration value="red" /> 17 <enumeration value="pink" /> 18 </simpleType> 19 </xsd:element> 20 </complexType> 21 </xsd:element> 22</xsd:schema> |
Line 5 in Listing 25 shows the name (Mobile) of our type while line 6 acknowledges that it is a complex datatype. You know that complex datatypes have attributes. Lines 7 through 12 show the attributes of the "Mobile" datatype, defined as sub elements.
The element declared in line 7 shows that the "Mobile" type has an attribute named "modelNumber";
and its type is "int" (that is, "modelNumber" can take only integer values).
Similarly, the elements declared in lines 9 and 10 have the same types but different attribute names. The element defined in line 8 has the
attribute name "modelName" and is of type "string".
The element in line 11 requires a bit more understanding since it has a sub element named "simpleType"
in line 12. Here you are defining a simple type inside the complex type, Mobile. The name of your
simpleType is "modelColor" and it is an "enumeration".
It has an attribute, "base", carrying the value
"xsd:string", which indicates that the simple type "modelColor" has the functionality of
the "string" type defined in the SOAP schema. Each <enumeration> tag in lines 13 to 17 carries an attribute, "value" (
"white",
"blue",
"black",
"red" and
"pink").
The enumerated types enable us to select one value from multiple options.
Using compound data types types in SOAP requests
Listing 26 demonstrates the use of compound types in SOAP requests.
It shows an envelope carrying a request in the Body element, in which you are calling the addModel method
of an "m" namespace. Listing 26 uses the data type "Mobile" that was defined in
Listing 25.
The AddModel method takes an argument of type "Mobile". We're referring "Mobile" structure with "msd" namespace
reference. See the "xmlns:msd" declaration in <SOAP-ENV:Envelope> element of
Listing 26.
This is an example of employing user defined data types in SOAP requests.
1 <SoAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 2 xmlns:xsd="http://www.w3.org/1999/XMLSchema" 3 xmlns:msd="www.mobilephoneservice.com/phonequote"> 4 <SOAP-ENV:Body> 5 <m:addModel xmlns:m="www.mobilephoneservice.com"> 6 <msd:Mobile> 7 <modelNumber>1</modelNumber> 8 <modelName>mlr97</modelName> 9 <modelWeight>10</modelWeight> 10 <modelSize>4</modelSize> 11 <modelColor>white</modelColor> 12 </msd:Mobile> 13 </m:addModel> 14 </SOAP-ENV:Body> 15<SOAP-ENV:Envelope> |
In this installment, you have learned SOAP syntax, requests, responses, HTTP Binding, and the use of SOAP with e-mails. You also looked at the Apache SOAP server serving an Apache SOAP client. Finally, I briefly covered the topic of user-defined data types, which is an advanced topic that needs detailed study. In the next part of this series of articles, you will see more examples of user-defined data types. I'll also examine SOAP interoperability (that is, how SOAP implementations from different vendors coordinate with each other).
- Simple Object Access Protocol (SOAP) 1.1 is the official specification of SOAP at W3C.
- Part 1 of this series of articles: Deploying web services with WSDL.
- An interesting SOAP article at XML.Com.
- An introduction to SOAP basics.
- Scribner, Kenn et all "Understanding SOAP", Sams.
- Bequet, Henry "Professional Java SOAP", Wrox.
- Download the Apache SOAP toolkit that was used in this article from Apache's web site.
Bilal Siddiqui is an XML consultant. After graduating in Electronics Engineering from the University of Engineering and Technology, Lahore, in 1995, he began designing software solutions for industrial control systems. Later he turned to XML and used his experience programming in C++ to build Web and WAP-based XML processing tools, server-side parsing solutions, and service applications. You can e-mail Bilal for working copies of the code files contained in this article at wap_monster@yahoo.com.




