Web Services Conceptual Architecture
Web Services Overview
This section briefly reviews Web Services as an application integration technology, defines the term
web service
and describes the Web Services model.
Web Services: The Next Horizon for e-business
What the Web did for program-to-user interactions, Web Services are poised to do for programto-program interactions. Web Services allow companies to reduce the cost of doing e-business,to deploy solutions faster and to open up new opportunities. The key to reaching this new horizon is a common program-to-program communications model, built on existing and emerging standards such as HTTP, Extensible Markup Language (XML), Simple Object Access
Protocol (SOAP), Web Services Description Language (WSDL) and Universal Description,
Discovery and Integration (UDDI).
Web Services allow applications to be integrated more rapidly, easily and less expensively than ever before. Integration occurs at a higher level in the protocol stack, based on messages centered more on service semantics and less on network protocol semantics, thus enabling loose integration of business functions. These characteristics are ideal for connecting business functions across the Web
both between enterprises and within enterprises. They provide a unifying programming model so that application integration inside and outside the enterprise can be done with a common approach, leveraging a common infrastructure. The integration and application of Web Services can be done in an incremental manner, using existing languages and platforms and by adopting existing legacy applications. Moreover, Web Services compliment Java
2 Platform, Enterprise Edition (J2EE), Common Object Request Broker Architecture (CORBA) and other standards for ntegration with more tightly coupled distributed and nondistributed applications. Web Services are a technology for
deploying and providing access
to business functions over the Web; J2EE, CORBA and other standards are technologies for
implementing
Web Services.
Although early use of Web Services is peer-wise and
ad hoc
, it still addresses the complete
problem of program-to-program communications including describing, publishing and finding
interfaces. And, as the use of Web Services grows and the industry matures, more dynamic
models of application integration will develop. Eventually systems integration through Web
Services will happen dynamically at runtime. Just-in-time integration will herald a new era of business-to-business integration over the Internet.
Definition of Web Services
A
Web service
is an interface that describes a collection of operations that are network accessible through standardized XML messaging.
A Web service is described using a standard, formal XML notion
, called its
service description
.
It covers all the details necessary to interact with the service, including message formats (that detail the operations), transport protocols and location. The interface hides the implementation details of the service, allowing it to be used independently of the hardware or software platform on which it is implemented and also independently of the programming language in which it is written. This allows and encourages Web Services-based applications to be loosely coupled, component-oriented, cross-technology implementations. Web Services fulfill a specific task or a set of tasks. They can be used alone or with other Web Services to carry out a complex aggregation or a business transaction.
The Web Services Model
The Web Services architecture is based upon the interactions between three roles: service
provider, service registry and service requestor.
The interactions involve the publish, find and bind operations. Together, these roles and operations act upon the Web Services artifacts: the Web service software module and its description. In a typical scenario, a service provider hosts a network-accessible software module (an implementation of a Web service). The service provider defines a service description for the Web service and publishes it to a service requestor or service registry. The service requestor uses a find operation to retrieve the service description locally or from the service registry and uses the service description to bind with the service provider and invoke or interact with the Web service implementation. Service provider and service requestor roles are logical constructs and a service can exhibit characteristics of both.
Figure 1 illustrates these operations, the components providing them and their interactions.
Figure 1. Web Services roles, operations and artifacts
Roles in a Web Services Architecture
。
Service provider.
From a business perspective, this is the owner of the service. From an architectural perspective, this is the platform that hosts access to the service.
。
Service requestor.
From a business perspective, this is the business that requires
certain functions to be satisfied. From an architectural perspective, this is the application that is looking for and invoking or initiating an interaction with a service. The service requestor role can be played by a browser driven by a person or a program without a user interface, for example another Web service.
。
Service registry.
This is a searchable registry of service descriptions where service
providers publish their service descriptions. Service requestors find services and obtain
binding information (in the service descriptions) for services during development for
static binding or during execution for dynamic binding. For statically bound service
requestors, the service registry is an optional role in the architecture, because a service
provider can send the description directly to service requestors. Likewise, service
requestors can obtain a service description from other sources besides a service
registry, such as a local file, FTP site, Web site, Advertisement and Discovery of
Services (ADS) or Discovery of Web Services (DISCO).
Operations in a Web Service Architecture
For an application to take advantage of Web Services, three behaviors must take place:
publication of service descriptions, lookup or finding of service descriptions, and binding or invoking of services based on the service description. These behaviors can occur singly or iteratively. In detail, these operations are:
。
Publish.
To be accessible, a service description needs to be published so that the
service requestor can find it. Where it is published can vary depending upon the
requirements of the application (see
“Service Publication” for more details).
。
Find.
In the find operation, the service requestor retrieves a service description directly or queries the service registry for the type of service required (see
“Service Discovery” for more details). The find operation can be involved in two different lifecycle phases for the service requestor: at design time to retrieve the service’s interface description for program development, and at runtime to retrieve the service’s binding and location description for invocation.
。
Bind.
Eventually, a service needs to be invoked. In the bind operation the service
requestor invokes or initiates an interaction with the service at runtime using the binding
details in the service description to locate, contact and invoke the service.
Artifacts of a Web Service
。
Service.
Where a Web service is an interface described by a service description, its
implementation is the service. A service is a software module deployed on networkaccessible
platforms provided by the service provider. It exists to be invoked by or to
interact with a service requestor. It can also function as a requestor, using other Web
Services in its implementation.
。
Service Description.
The service description contains the details of the interface and
implementation of the service. This includes its data types, operations, binding
information and network location. It could also include categorization and other metadata
to facilitate discovery and utilization by service requestors. The service description
might be published to a service requestor or to a service registry.
The Web Services architecture explains how to instantiate the elements and implement the
operations in an interoperable manner.
Web Services Development Lifecycle
The Web Services development lifecycle includes the design, deployment, and runtime
requirements for each of the roles: service registry, service provider and service requestor. Each role has specific requirements for each element of the development lifecycle. The development and deployment of a service registry is outside the scope of this paper.
The development lifecycle can have four phases:
1.Build
The build phase of the lifecycle includes development and testing of the Web service
implementation, the definition of the service interface description and the definition of the service implementation description. Web service implementations can be provided by
creating new Web Services, transforming existing applications into Web Services, and
composing new Web Services from other Web Services and applications.
2. Deploy
The deploy phase includes the publication of the service interface and service
implementation definition to a service requestor or service registry and deployment of the
executables for the Web service into an execution environment (typically, a Web application
server).
3.Run
During the run phase, the Web service is available for invocation. At this point, the Web
service is fully deployed, operational and network-accessible from the service provider. Now the service requestor can perform the find and bind operations.
4. Manage
The manage phase covers ongoing management and administration of the Web service
application. Security, availability, performance, quality of service and business processes must all be addressed.
The details of each of these lifecycle phases are discussed in the
Web Services Development
Concepts
paper.
Deploying Web services with WSDL
This new breed of dotcom needs a solution that can describe the services -- the Web services -- it offers. Specifically, this means that you need a format or some type of grammar, with which you can describe the answers to the following questions:
-
What are the services offered in your online business?
-
How can you invoke your business services?
-
What information do your business services need from the user when he or she invokes your service?
-
How will the user provide the required information?
-
In which format will the services send information back to the user?
Happily, WSDL provides the mechanism for doing all of these jobs.
To better understand how WSDL works, I will first describe how SOAP and HTTP work with WSDL. The purpose of WSDL is to "describe" your Web services. Businesses will exchange WSDL files to understand the other's services. SOAP comes in once you know your partners' services and wish to invoke them.
You can think of services as objects which are accessed by SOAP.
Most likely you will be communicating with potential partners via the Internet or through e-mail. The Internet, of course, uses HTTP and e-mail works on SMTP, making HTTP and SMTP the favored candidates for acting as "transport service providers" to SOAP.
Now I'll look at the process of writing WSDL for the Web service. The goal is to expose the existing Web services. Your own situation may be any one of the following:
-
You have an existing service (for instance, a Web site) and you want to expose its functionality.
-
You have a WSDL and you want to implement Web server-side logic according to what you have already decided to expose. (Some people may think this an unlikely scenario, but UDDI's idea of fingerprints makes it quite probable; I will discuss UDDI in the fourth part of this series of articles).
-
You are starting from scratch and have neither a Web site nor a WSDL interface.
The information covered in this article allows for any or all of these possibilities.
I will divide WSDL authoring in four simple steps. Follow each step, and your Web service will be ready for deployment.
As a sample project, you will build the service interface of a mobile phone retail company (I will call this service
MobilePhoneService
). This company sells mobile phones in different models, so back-end data storage of this company's Web service will contain a single table with two columns,
model number
and
price
. (I am keeping this simple in order to maintain the focus on WSDL itself). You will have two methods on your service which you will expose using WSDL:
-
getListOfModels ()
-
getPrice (modelNumber)
The
GetListOfModels
method provides an array of strings, where each string represents the model number of a mobile phone.
GetPrice
takes a model number and returns its price. WSDL calls these methods as operations. Now you'll start building the
WSDL interface file
.
The root element of every WSDL file is
<definitions>
, in which you must provide a complete description of services. First of all, you have to provide various namespace declarations in the
<definitions>
element.
The three external namespace declarations you have to make are WSDL, SOAP, and XSD (XML Schema Definition).
There is another namespace, TNS, that refers to your MobilePhoneService (this means TNS -- which is short for targetNamespace -- will contain all names of elements and attributes that will be defined specifically for the
MobilePhoneService
). But WSDL is the primary namespace that you'll use in most of your WSDL authoring. I will mention the utility of other namespaces as they are used in this series of articles.
Just a note about namespaces: WSDL uses the concept of namespaces extensively. I encourage you to visit W3C's official Web site to learn more about namespaces (see Resources). WSDL is an implementation of this idea, since namespaces provide an infinite degree of flexibility and this is exactly what is required in a portable format for electronic data interchange.
The
<definitions>
element contains one or more
<portType>
elements, each of which is actually a set of
operations
that you want to expose. Alternatively, you can think of a single portType element as a logical grouping of methods into classes. For example, if your supply chain management solution requires interaction with both customers and suppliers, you will most probably define functionality for interaction with them separately; that is, you will define one portType for customers and one for suppliers. You should call each portType a service, so that your complete WSDL file will become a collection of services.
You have to provide a name for each service. In this case, you have only one service (so one
<portType>
element). You need to use the
name
attribute of this portType element to assign a name to your mobile phone sales service.
Within each service you may have several methods, or
operations
, which WSDL refers to via
<operation>
elements. The sample application has two methods to expose, namely
getListOfModels
and
getPrice
. Therefore, you need to provide two
<operation>
elements, each having a
name
. I have used the
name
attribute of the
<operation>
element to name each operation.
At this point the WSDL file looks like Listing 1.
Listing 1: Defining operations
<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="MobilePhoneService"
targetNamespace="www.mobilephoneservice.com/MobilePhoneService-interface"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.mobilephoneservice.com/MobilePhoneService"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<portType name="MobilePhoneService_port">
<operation name="getListOfModels ">
.......
.......
</operation>
<operation name="getPrice">
.......
.......
</operation>
</portType>
</definitions>
|
Having defined the operations (or methods), you now need to specify the parameters that you will send to them and the parameters that they will return. In WSDL terms, all parameters are called "messages." It is useful to think that you are sending in messages and as a result getting back return messages. Method calls are the operations that take place to prepare return "messages" in response to incoming messages.
Recall from the first step that you have two operations to expose. The first operation,
getListOfModels
, does not take any parameter and returns an array of strings, where each string represents the model number of a mobile phone. Therefore, you have to define a
<message>
element that contains an array of strings.
Have a look at the various
<message>
elements in Listing 2. The first of these has a name attribute equal to
ListOfPhoneModels
(a logical name for this message), and a single
<part>
element with the name models, which means
ListOfPhoneModels
is a one-part message, where the name of the only part present is "models." You can have any number of parts in a message -- so long as you remember to give them different names for unique identification.
I have included another attribute of the
<part>
element, which is
type
. Think of this "type" attribute as data types in C++ or Java. I have specified the data type of
models
as tns:Vector. (Recall that I specified a few namespaces in the root
<definitions>
element, one of which was
tns
). This refers to the
MobilePhoneService
namespace. What this means is that you can create your own namespace while authoring WSDL. You may now be asking two logical questions: Why? And how?
To answer the why, let's take the array of strings returned by the
getListOfModels
operation as an example. WSDL uses a few primitive data types that XML Schema Definition (XSD) defines (like int, float, long, short, byte, string, Boolean, etc.) and allows you to either use them directly or to build complex data types based on these primitive ones, before using them in messages. This is why you need to define your own namespace when referring to complex data types. In this case, you need to build a complex data type for an
array of strings
.
Now coming to the how question, you will use XSD to create your namespace. For this purpose I have used the xsd:complexType element within the
<types>
element to define data type named
Vector
.
Vector
uses two primitive data types -- string (element data) and Integer (element count). Hence
Vector
becomes part of the namespace and can be referred to by the alias
tns
.
In a similar manner, I have defined the other two messages,
PhoneModel
and
PhoneModelPrice
, in Listing 2. These two messages use only string primitive data types of the xsd namespace and therefore you do not need to define any more complex data types in order to use them.
You may have noticed that while creating the
<message>
elements, you did not specify whether these messages are incoming parameters or return values. This is a job you will take care of in the
<operation>
element within the
<portType>
element. Therefore, as you can see in Listing 2, I have added the
<input>
and
<output>
elements to each of the two operations. Each input element refers to a message by its name and treats it as a parameter that the user will provide when invoking this operation. Each
<output>
element similarly refers to a message; it treats the message as the return value of the operation call.
Listing 2: Defining parameters
<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="MobilePhoneService"
targetNamespace="http://www.mobilephoneservice.com/MobilePhoneService-interface"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.mobilephoneservice.com/MobilePhoneService"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<types>
<xsd:schema targetNamespace="http://www.mobilephoneservice.com/MobilePhoneService"
xmlns="http://www.w3.org/1999/XMLSchema/">
<xsd:complexType name="Vector">
<xsd:element name="elementData" type="xsd:String" />
<xsd:element name="elementCount" type="xsd:int" />
</xsd:complexType>
</xsd:schema>
</types>
<message name="ListOfPhoneModels">
<part name="models" type="tns:Vector">
</message>
<message name="PhoneModel">
<part name="model" type="xsd:String">
</message>
<message name="PhoneModelPrice">
<part name="price" type="xsd:String">
</message>
<portType name="MobilePhoneService_port">
<operation name="getListOfModels ">
<output message="ListOfPhoneModels"/>
</operation>
<operation name="getPrice">
<Input message="PhoneModel"/>
<output message="PhoneModelPrice"/>
</operation>
</portType>
</definitions>
I have defined operations and messages in an abstract way, without worrying about the details of implementation. In fact, WSDL's job is to define or describe Web services and then to provide a reference to an external framework to define how the WSDL user will reach the implementation of these services. You can think of this framework as a
binding
between WSDL's abstract definitions and their implementation.
Currently, the most popular
binding
technique is to use the Simple Object Access Protocol (SOAP). WSDL will specify a SOAP server that has access to the actual implementation of your Web service, and from there it is entirely SOAP's job to take the user from the WSDL file to its implementation. SOAP is the topic of next installment in this series of articles, so for the time being I will avoid SOAP details and keep focused on WSDL authoring.
The third step in WSDL authoring is to describe the process of SOAP binding with a WSDL file. You will include a
<binding>
element within the
<definitions>
element. This binding element should have a
name
and a
type
. The
name
will identify this binding and
type
will identify the portType (set of operations) that you want to associate with this binding. In Listing 3, you will find that the
name
of the
<portType>
element matches the type attribute value of the
<binding>
element.
The WSDL binding element contains a declaration of which external technologies you will use for binding purposes. Since you are using SOAP, you will use SOAP's namespace here. In WSDL terminology, the use of an external namespace is called the
extensibility
element.
In Listing 3, you will see an empty
<soap:binding/>
element. The purpose of this element is to declare that you are going to use SOAP as a binding and transport service.
The
<soap:binding>
element has two attributes: style and transport. Style is an optional attribute that describes the nature of operations within this binding. The transport attribute specifies HTTP as the lower-level transport service that this binding will use.
A SOAP client will read the SOAP structure from your WSDL file and coordinate with a SOAP server on the other end, so you must be very concerned with
interoperability
. I intend to cover this in detail in the third part of this series of articles.
After the empty
<soap:binding/>
element, you have two WSDL
<operation>
elements, one for each of your operations from Step 1. Each
<operation>
element provides binding details for individual operations. Therefore, I have provided another
extensibility
element, namely
<soap:operation/>
(again an empty element that relates to the operation in which it occurs). This
<soap:operation/>
element has a soapAction attribute that a SOAP client will use to make a SOAP request.
Recall from Step 2 that the
getListOfModels
operation only has an output and does not have any input. Therefore, you have to provide an
<output>
element for this operation. This output contains a
<soap:body/>
element (again an empty element that relates to the output in which it occurs). The SOAP client needs this information to create SOAP requests. The value of the namespace attribute of
<soap:body/>
should correspond to the name of the
service
that you will deploy on your SOAP server in the next part of this series of articles.
You are nearly finished with Step 3. Just copy the next operation after this one and you will come up with Listing 3.
Listing 3: Adding SOAP support
<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="MobilePhoneService"
targetNamespace="http://www.mobilephoneservice.com/MobilePhoneService-interface"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.mobilephoneservice.com/MobilePhoneService"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<types>
<xsd:schema targetNamespace="http://www.mobilephoneservice.com/MobilePhoneService"
xmlns="http://www.w3.org/1999/XMLSchema/">
<xsd:complexType name="Vector">
<xsd:element name="elementData" type="xsd:String" />
<xsd:element name="elementCount" type="xsd:int" />
</xsd:complexType>
</xsd:schema>
</types>
<message name="ListOfPhoneModels">
<part name="models" type="tns:Vector">
</message>
<message name="PhoneModel">
<part name="model" type="xsd:String">
</message>
<message name="PhoneModelPrice">
<part name="price" type="xsd:String">
</message>
<portType name="MobilePhoneService_port">
<operation name="getListOfModels ">
<output message="ListOfPhoneModels"/>
</operation>
<operation name="getPrice">
<Input message="PhoneModel"/>
<output message="PhoneModelPrice"/>
</operation>
</portType>
<binding name="MobilePhoneService_Binding" type="MobilePhoneService_port">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="getListOfModels ">
<soap:operation soapAction="urn:MobilePhoneService" />
<input>
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:MobilePhoneService" use="encoded" />
</input>
<output>
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:MobilePhoneService" use="encoded" />
</output>
</operation>
<operation name="getPrice">
<soap:operation soapAction="urn:MobilePhoneService" />
<input>
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:MobilePhoneService" use="encoded" />
</input>
<output>
<soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:MobilePhoneService" use="encoded" />
</output>
</operation>
</binding>
</definitions>
You have produced a WSDL file that completely describes the
interface
of your service. WSDL now requires the additional step of creating a summary of the WSDL file. WSDL calls this a an
implementation
file, which you will use while publishing your Web service at a UDDI registry in the fourth part of this series of articles. Have a look at Listing 4, a WSDL implementation file. Its main features are the following:
-
The root
<definitions>
element is exactly the same as in Listing 3 (a WSDL interface file), except that Listing 4 (the implementation file) refers to a different
targetNamespace
, which refers to your implementation file.
-
There is an
<import>
element that refers to the interface file of Listing 3 (file name MobilePhoneService-interface.wsdl) and its namespace.
-
There is a
<service>
tag with a logical
name
for this service. Within the service element is a port element that refers to the SOAP binding that you created in Listing 3.
Listing 4: WSDL implementation file
<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="MobilePhoneService"
targetNamespace="http://www.mobilephoneservice.com/MobilePhoneService"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.mobilephoneservice.com/MobilePhoneService"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<import location="http://localhost:8080/wsdl/MobilePhoneService-interface.wsdl"
namespace="http://www.mobilephoneserviceservice.com/MobilePhoneService-interface" />
<service name="MobilePhoneService">
<documentation> Mobile Phone Information Service </documentation>
<port binding="MobilePhoneService_Binding" name="MobilePhoneService_ServicePort">
<soap:address location="http://localhost:8080/soap/servlet/rpcrouter" />
</port>
</service>
</definitions>
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:
1.
SOAP client
2.
SOAP server
3.
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
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
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:
1.
service manager
2.
deployed services list
3.
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 actual service
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.
SOAP binding with HTTP
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.
A SOAP request using HTTP
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.
SOAP response using HTTP
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>
SOAP Schema and authoring
SOAP message
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>
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 inListing 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.
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>
posted on 2007-01-02 23:21
阿郎( 行者无疆) 阅读(193)
评论(0) 编辑 收藏