Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
The Florida State University
College of Arts and Sciences
A Java Implementation of the
Simple Object Access Protocol
By Darui Xu
October 21, 2002
A project submitted to the Department of Computer Science
In partial fulfillment of requirements for the
Degree of Master of Science
Major Professor: Dr. Robert van Engelen
Master Project committee
-----------------------------------
Prof. Robert van Engelen
Major Professor
-----------------------------------
Prof. Hilbert Levitz
Committee Member
----------------------------------
Prof. Daniel Schwartz
Committee Member
2
ACKNOWLOGEMENT
The author wants to thank her Major Professor Dr. van Engelen for providing the original
idea of the project. The project cannot be finished, without his constant help and
guidance. The author also wants to thank Dr. Levitz and Dr. Schwartz for agreeing to
serve as committee members.
The author wants to thank the entire faulty and staff of Computer Science Department at
the Florida State University for their help during her three years of study there.
3
TABLE OF CONTENTS
Abstract………………………………………………………………………………….. 6
1.
INTRODUCTION..................................................................................................... 7
1.1
WEB SERVICES AND SOAP .................................................................................. 7
1.2
SOAP FEATURES ................................................................................................. 9
1.3
SOAP AND XML ............................................................................................... 12
1.4
SOAP ARCHITECTURE ....................................................................................... 13
1.4.1
The SOAP Specification ........................................................................... 13
1.4.2
The Basic SOAP Payload Structure .......................................................... 14
1.5
2
3
THE USE OF SOAP FOR RPC ............................................................................. 18
1.5.1
SOAP, RMI and XML-RPC ..................................................................... 18
1.5.2
SOAP RPC format .................................................................................... 19
SOAP FOR JAVA: PROJECT MOTIVATION AND ACCOMPLISHMENT 21
2.1
SFJ MOTIVATION ............................................................................................... 21
2.2
SFJ ACCOMPLISHMENTS .................................................................................... 22
SJF DESIGN AND IMPLEMENTATION ........................................................... 25
3.1
SERIALIZATION .................................................................................................. 25
3.1.1
Locating Multi-references ......................................................................... 26
3.1.2
Construct the message............................................................................... 27
3.1.3
Print the independent elements ................................................................. 29
3.2
TRANSMISSION ................................................................................................... 30
3.3
DE-SERIALIZATION ............................................................................................ 30
3.3.1
Locate the start node ................................................................................. 31
3.3.2
Assign the values ...................................................................................... 31
4
3.3.3
4
5
Resolve Independent Element................................................................... 34
3.4
NAMESPACES ..................................................................................................... 36
3.5
POLYMORPHIC ACCESSOR .................................................................................. 37
3.6
FAULT CLASS ..................................................................................................... 38
CLIENT-SERVER APPLICATION EXAMPLE ................................................ 39
4.1
ECHOSTRUCTARRAY .......................................................................................... 40
4.2
POLYMORPHIC ACCESSOR .................................................................................. 44
CONCLUSIONS AND FUTURE WORK ............................................................ 46
REFERENCE .................................................................................................................. 47
5
Abstract
The Simple Object Access Protocol (SOAP) is a lightweight protocol for the exchange of
information in a decentralized, distributed environment. The SOAP protocol is based on
XML and HTTP, which makes it a programming language and platform neutral vehicle
for remote method invocation over the Internet and through firewalls. The SOAP for Java
(SFJ) project develops a tool for marshalling native and user-defined Java data structures
into SOAP message and deserializing SOAP message into Java objects. With SFJ a Java
program can be run and interoperate with other SOAP applications in a distributed
environment through SOAP remote method invocation.
6
1. Introduction
This section introduces the Simple Object Access Protocol (SOAP) as a language- and
platform-neutral protocol for exchange of information in a decentralized, distributed
environment. This section first illustrates how SOAP together with other protocols
supports the Web services. Next, it presents the features of SOAP and its relation with
Extensible Markup Language (XML). Finally, it gives the details about SOAP structure
and how SOAP is used to make Remote Procedure Call (RPC) calls.
1.1
Web Services and SOAP
A Web Service is programmable application logic accessible via standard Web protocols.
Web Services opens the Internet by providing remote computing services and dynamic
information exchange without the need for browsers. Dynamically generated HTML
content works fine in Web browsers, but it presents a nightmare for anyone trying to
utilize that data with other programs. For example, you can easily view an auction site in
a browser, but an application would require a complex HTML parser to read your bid's
status from the same site. Worse, you would need a different parser to track a different
auction site, and the simplest redesign of either site could throw off your program. Web
Services provides a solution for this problem with a consistent and easy method for
accessing online information. Web Services achieves this through the use of standardbased protocols like SOAP, which serves as the remote method invocation protocol and
WSDL (Web Service Description Language) and UDDI (Universal Description,
Discovery, and Integration) for service descriptions, registry, discovery and lookup.
SOAP is the heart of Web Services. Web Services utilizes SOAP as an XML-based
remote method invocation protocol. SOAP is a W3C submitted note (as of May 2000)
that uses standards based technologies (XML for data description and HTTP for
transport) to encode and transmit application data. Consumers of a Web Service do not
need to know anything about the platform, object model, or programming language used
to implement the service; they only need to understand how to send and receive SOAP
messages (HTTP and XML).
7
A WSDL file is an XML document that describes a set of SOAP messages and how these
messages are exchanged between SOAP processors. This enables companies to describe
their services and enables the client to consume the services in a standard way without
knowing much on the lower level exchange protocol (binding) like SOAP. This high
level abstraction on the service limits the human interaction and enables the automatic
generation of proxies for Web services. (These proxies can be static or dynamic).
Imagine you want to start calling a SOAP method provided by one of your business
partners. You could ask him for some sample SOAP messages and write your application
to produce and consume messages that look like the samples, but this can be error-prone.
For example, you might see a customer ID of 2837 and assume it's an integer when in
fact it's a string. WSDL allows the description of both document-oriented and RPCoriented messages. WSDL specifies what a request message must contain and what the
response message will look like in unambiguous notation. The WSDL description
published by Web Services can be used to automatically generate stub routines for the
development of SOAP clients within a specific programming environment.
UDDI is a specification for an Internet-wide registry of Web Services and their metadata.
The UDDI project creates a platform-independent, open framework for describing
services, discovering businesses, and integrating business services using the Internet, as
well as an operational registry that is available today. The metadata contains information
about the company offering a given service and technical details on how it can be
accessed through a WSDL description of the service.
SOAP, WSDL and UDDI work together in a three-folds service architecture (Fig. 1).
Service providers register their services in a UDDI registry. When a client wants to get
some web service, it makes a call to the UDDI registry and finds out the desired service.
Once the client locates the right service, it looks up the service’s WSDL interface to get
the appropriate request and responses format. Then the client can send the server a SOAP
message to invoke the service and wait for the result, which is also a SOAP message, to
be sent back by the server.
8
Service Provider
Authors
1
Codes
SOAP service
WSDL description
of service
Registers
Interact With
UDDI registry
Finds
Searches for
WSDL description
of service
Generate
Service client
Codes
SOAP Client
Figure 1 The web services process
1.2
SOAP Features
SOAP is a wire protocol similar to the IIOP (Internet Inter-ORB Protocol) for CORBA
(Common Object Request Broker Architecture), ORPC (Object Remote Procedure Call)
for DCOM (Distributed Component Object Model), or JRMP (Java Remote Method
Protocol) for RMI (Java Remote Method Invocation). However, SOAP is somewhat
different from the other wire protocols. When a CORBA client needs to obtain the
services of DCOM client or vice versa, the common solution is to use a COM/CORBA
bridge. The bridge's complexity results from the intricate back-and-forth translation that
it must complete from CORBA's IIOP to DCOM's ORPC. So it is fraught with failure
points. SOAP can help to alleviate the problem. The XML-based protocol is language
and platform neutral, which means that information sharing relationships can be initiated
9
among disparate parties, across different platforms, languages and programming
environments. SOAP is not a competitive technology to CORBA and DCOM, but rather
complements these technologies. CORBA, DCOM, and Enterprise Java enable resource
sharing within a single organization while SOAP technology aims to bridge the sharing
of resources among disparate organizations possibly located behind firewalls. SOAP
applications exploit a wire-protocol (typically HTTP) to communicate with Web services
to retrieve dynamic content.
The most compelling feature of SOAP is that it has been implemented on many different
hardware and software platforms. This means that SOAP can be used to link disparate
systems within and external to organization. Many attempts have been made in the past to
come up with a common communications protocol that could be used for systems
integration, but none of them has had a widespread adoption like SOAP.
Because SOAP can use existing XML Parsers and HTTP libraries to do most of the hard
work, a SOAP implementation can be completed in a matter of months and it is smaller
and easier to implement than most of the previous protocols. Because it is based on a
vendor-agnostic technology, namely XML, HTTP, and Simple Mail Transfer Protocol
(SMTP), SOAP appeals to all vendors. SOAP is a protocol created by Microsoft,
DevelopMentor, and Userland Software and backed by companies that include IBM,
Lotus, and Compaq.
While IIOP, ORPC, and JRMP are binary protocols, SOAP is a text-based protocol that
uses XML. Using XML for data encoding gives SOAP some unique capabilities. It is
much easier to debug applications based on SOAP because it is much easier to read XML
than a binary stream. And since all the information in SOAP is in text form, SOAP is
much more firewall-friendly than IIOP, ORPC, or JRMP.
The HTTP transport binding for SOAP makes it attractive for some users. Since most
organizations are familiar with HTTP and already have it incorporated into their network
infrastructure, SOAP fits right in without the complex changes to the network or firewalls
that many other protocols require. Because SOAP is layered on top of HTTP, it may
utilize any standard HTTP security feature or any endpoint application-specific security
10
feature. SOAP makes it possible for system administrators to configure firewalls to
selectively block out SOAP requests using SOAP-specific HTTP headers. They can also
be configured to allow only certain interfaces or methods to pass through by looking at
the Interface Name and Method Name extension headers defined by SOAP. The standard
authentication mechanisms that are HTTP-friendly can be used with SOAP. These
protocols can authenticate the server (and optionally the client), and can provide a
confidential channel over which SOAP payload can travel. However, when SOAP
expanded to become a more general-purpose protocol that runs on top of a number of
transports, security became a bigger issue. For example, HTTP provides several ways to
authenticate which user is making a SOAP call, but it doesn't provide a way for that
identity to be propagated when the message is routed from HTTP to an SMTP transport.
Fortunately, the W3C is already working on security for XML documents, so it's
probably safe to assume that at some point in the near future, the security issues
addressed by the W3C will be used to define a security implementation for SOAP.
Most people use SOAP because it supports interoperability among many different
environments and it supports HTTP, which has led to SOAP becoming an industry
standard. The biggest advantage of SOAP can also be a disadvantage. SOAP data is sent
as XML text to enable standard message formats, standard data representation, and
manipulation with standard XML tools—all good things. However, converting all you
data into text and parsing it back into data structures at the other end can use up quite a
bit of processing power. The tags that make SOAP self-describing make SOAP messages
bigger than the equivalent message without the tags. While these things add up to minor
performance penalty for using SOAP, many other protocols perform better than SOAP. If
you need SOAP for one of the reasons discussed earlier, then this minor performance
penalty is a small price to pay, but if these things don't apply to your situation, using
SOAP may not be the best choice. As SOAP implementations mature, the performance
gap between SOAP and other protocols will narrow.
There are many existing SOAP implementations (including Java implementations), such
as, Apache SOAP/Axis (Java), eSOAP, gSOAP, IONA XMLBus, kSOAP, pocketSOAP
11
1.1 beta SILAB/TclSOAP, SIM SOAP4R, Spray B2001, SQLData, WASP Advanced
3.0, WASP for C++, White Mesa 2.5, xSOAP (Java), and Interoperability.
1.3
SOAP and XML
SOAP uses XML as the data-encoding format. The idea of using XML is not original to
SOAP. Both XML-RPC and ebXML use XML as well. This section gives a brief
introduction to XML.
XML is the Extensible Markup Language. It is a subset of Standard Generalized Markup
Language (SGML) and it is much simpler and straightforward. Unlike HTML, XML is a
markup language that specifies neither the tag set nor the grammar for that language. This
is the power of XML: it allows you to define the content of your data in a variety of ways
as long as you conform to the general structure that XML requires. Any XML document
must be well formed, which means that every tag is closed, no tags nested out of order,
and is syntactically correct. An XML document can be, but are not required to be valid,
which means it conforms to the constraining documents such as Document Type
Definition (DTD) or XML schema. Since a user can freely define any tags, namespaces
are often used to allow parsers to handle collisions. A namespace is a mapping between
an element prefix and a URI. A namespace is associated with a prefix to an XML
element.
Because XML is plain text, any application can understand it as long as the application
understands the character encoding in use. By default, XML assumes that all characters
belong to ISO/IEC 10646, known as the Universal Character Set (UCS). The XML
specification (http://www.w3.org/XML/) mandates that all XML processors must accept
character data encoded using the UCS Transformation Formats UTF-8 or UTF-16.
Therefore, any XML data stream encoded in UTF-8 or UTF-16 can be understood
regardless of platform or programming language. This makes XML a good choice for
describing method invocations in a platform and language-neutral fashion.
12
1.4
SOAP Architecture
1.4.1 The SOAP Specification
The World Wide Web Consortium (W3C) has published a first working draft
specification for SOAP Version 1.2. The working draft has been produced by the XML
Protocol Working Group (WG), part of the W3C XML Protocol Activity. The SOAP 1.1
specification along with a SOAP Envelope schema and a SOAP Encoding schema was
published on May 08, 2000.
SOAP a lightweight protocol for exchange of information in a decentralized, distributed
environment. It is an XML based protocol that consists of four parts: an envelope that
defines a framework for describing what is in a message and how to process it, a set of
encoding rules for expressing instances of application-defined data types, a convention
for representing remote procedure calls and responses and a binding convention for
exchanging messages using an underlying protocol. SOAP can potentially be used in
combination with a variety of other protocols; however, the only bindings defined in this
document describe how to use SOAP in combination with HTTP and the experimental
HTTP Extension Framework.
The SOAP envelope is analogous to the envelope of an actual letter. It supplies
information about the message that is being encoded in a SOAP payload, including data
relating to the recipient and sender, as well as details about the message itself. The header
of the SOAP envelope can specify exactly how a message must be processed and a
typical SOAP message can also include the encoding style, which assists the recipient in
interpreting the message.
The second major element of the SOAP specification is a simple means of encoding userdefined data types. If your application doesn't understand XML, you will need to
represent your program's data types—integers, floats, arrays, structs, and so on—as XML
data in the SOAP message. Section 5 of the SOAP standard specifies an XML notation
for representing programming language types. Because it is defined in section 5 of the
standard, it is often called Section 5 encoding. The other alternative for defining the data
types of the elements in a SOAP message is to use a schema as defined in the XML
13
Schema (XSD) standard. Section 5 makes sense if you are using SOAP to support
Remote Procedure Calls from a local program to a remote program because the mapping
between XML and your programming language is simpler with Section 5 encoding. In
XML message-based applications with complex data, it may make more sense to provide
an XML schema for the SOAP message, rather than using SOAP encoding. The Section 5
encoded SOAP message is called an encoded message, and a message that contains an
XML document is called a literal message. While all major SOAP implementations
support section 5 encoding, it is an optional part of the spec and a conformant SOAP
implementation wouldn't have to support it. The .NET XML Web services defaults to
literal messages, but it does support encoded messages for interoperability.
SOAP can be used for Remote Procedure Call (RPC), in which a remote procedure is
invoked on a server and gets some sort of response, or for messaging, in which a client
simply sends pieces of information to a server. Most programmers are comfortable with
Remote Procedure Call (RPC) programming, so it's natural for SOAP to include an RPC
specification. Section 7 of the SOAP specification defines the XML element that
represents a function call and the element that contains the return code in the response
message. In this sense, SOAP is simply acting as a more extensible XML-RPC system,
allowing better error handling and passing of complex types across the network. SOAP
messaging provides for transfer of information and it doesn’t depend on a client knowing
about a particular method on some server. It models the distributed systems more closely
and more complicated that the RPC-style calls.
1.4.2
The Basic SOAP Payload Structure
A SOAP message is an XML document that consists of a mandatory SOAP envelope, an
optional SOAP header, and a mandatory SOAP body. Below is a simple SOAP message
complete with HTTP header.
14
POST /EventManager HTTP/1.1
Host: www.techmetrix.com
Content-Type: text/xml;
charset="utf-8"
Content-Length: 60
SOAPAction="http://www.techmetrix.com/Event#New Customer"
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xml.org/soap/envelope/"
SOAP-ENV :encodingStyle="http://schemas.xml.org/soap/encoding/"/>
<SOAP-ENV:Header>
<t:Name xmlns:t="www.techmetrix.com/EventManager"
SOAP-ENV :actor="http://schemas.xml.org/soap/actor
/next/"
SOAP-ENV :mustUnderstand="1">
Dumser
</t:Name >
</SOAP-ENV:Header>
<SOAP:Body>
<m:NewCustomer xmlns:m="www.techmetrix.com/Event">
<Entreprise>SQLI</Entreprise>
<Address>Paris</Address>
</m:NewCustomer>
</SOAP:Body>
</SOAP:Envelope>
1.4.2.1 HTTP header
The HTTP header for the request comes before the SOAP message. The first line defines
the type of request, the URI request and the protocol. The next line gives the target site,
followed by information about the MIME format for message display, the HTTP coding
and the length of the message. The HTTP header can also include the HTTP
SOAPAction header, which is optionally used by the server for routing the SOAP
message. The identifier following the # sign must match the name of the first tag in the
SOAP message body. Below is the header part:
15
POST /EventManager HTTP/1.1
Host: www.techmetrix.com
Content-Type: text/xml;
charset="utf-8"
Content-Length: 60
SOAPAction="http://www.techmetrix.com/Event#New
Customer"
1.4.2.2 SOAP Envelope
Following the HTTP headers is the body of the SOAP message. SOAP envelope is the
top element of the XML document representing SOAP message and the mandatory root
element of the XML document tree. It contains the name of the element (Envelope),
followed by namespace declarations including the SOAP version being used, and it may
also contain additional attributes such as encodingStyle attribute which points to a link
where the serialization (tree structure) and encoding rules are defined. The envelope is
presented as follows:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV=”http://schemas.xml.org/soap/envelope/”
SOAPENV:encodingStyle="http://schemas.xml.org/soap/encoding/"/>
……
</SOAP-ENV:Envelope>
1.4.2.3 SOAP Header
The SOAP header is optional. It is a generic mechanism that adds features to the SOAP
message in a decentralized manner without prior agreement between the communicating
parties. SOAP defines several attributes that can be used to indicate who must process the
message, and whether this process is optional or mandatory.
16
If present, the header must be the first immediate child element of the SOAP Envelop
element. It carries information to intermediaries, and is made up of one of more entries.
These bear a local name, a full name, a namespace and the two actor attributes which
designate the endpoint of the entry, and mustUnderstand, which indicates the optional
nature of the process. A SOAP application must include a correct SOAP namespace for
all the elements and attributes defined in the message generated. This is a URI that points
to a description of the message information in order to guarantee the uniqueness of the
message.
<SOAP-ENV:Header>
<t:newEvent xmlns:t="http://www.techmetrix.com/eventmanager"
SOAP-ENV :actor="http://schemas.xml.org/soap
/actor/next/"
SOAP-ENV :mustUnderstand="1">
Christmas Event
</t:newEvent>
</SOAP-ENV:Header>
1.4.2.4 SOAP Body
The SOAP body is the container for the mandatory information being sent to the message
endpoint. This can contain a set of entries that are all kept in the root of the message
body.
<SOAP-ENV:Body>
<m:NewCustomer xmlns:m="Some-URI">
<Name>Dumser</Name>
<Surname>Johann</Surname>
<City>Cambridge</City>
<ZipCode>01800</ZipCode>
<State>MA</State>
<Country>USA</Country>
</m:NewCustomer>
</SOAP-ENV:Body>
17
1.5
The Use of SOAP for RPC
As mentioned earlier, SOAP can be used for RPC-style calls. This section first discusses
the advantages SOAP RPC calls over similar technologies such as Java Remote Method
Invocation (RMI), and XML-RPC. Then the requirements for SOAP RPC calls are
covered.
1.5.1 SOAP, RMI and XML-RPC
RMI allows a program to invoke methods on an object when the object is not located on
the same machine as the program. This is at the heart of distributed computing in the Java
world, and is the backbone of many enterprise application implementations. RMI uses
client stubs to describe the methods a remote object has available for invocation. The
client acts upon these stubs and RMI translates the requests to a stub into a network call.
This call invokes the method on the machine with the actual object, and then streams the
result back across the network. Finally, the stub returns the result to the client that made
the original method call. There are several disadvantages of using RMI. First, using RMI
is resource-intensive. As clients issue RMI calls, sockets must be opened and maintained.
RMI also requires a server to bind objects using an RMI registry, LDAP or other forms of
Java Naming and Directory Interface. Finally, adding an additional method to the server
class results in a change to the interface and recompilation of the client stubs.
One of the most significant differences between RMI and RPC is the way methods are
made available. In RMI, a remote interface has the method signature for each remote
method. If a method is implemented on the server class, but no matching signature is
added to the remote interface, the new method cannot be invoked by an RMI client. This
process is quite different in RPC. The method requested is never explicitly defined in the
XML-RPC server, but in the request from the client. When a request comes in to an RPC
server, the request contains a set of parameters and a textual value. The server tries to
find a matching class and method that take parameter types that match the types within
the RPC request as input. Once a match is made, the method is called, and the result is
encoded and sent back to the client. If a method is added in the server, the method
signature can be published to the client community and used immediately, no client stubs,
18
skeletons or interface update necessary. RPC also allows disparate systems to work
together as the request parameters and the results are generally encoded as textual data
and the transport protocol can be HTTP. The greatest obstacle to using RPC has
traditionally been its encoding. But XML with its simple, textual data and a structure for
data solves the problem.
When used as RPC-style calls, SOAP is simply acting as a more extensible XML-RPC
system, with better error handling and passing of complex types across the network. In
XML-RPC, encoding can only occur for a predefined set of data types. With SOAP,
XML schema can be used to easily specify new data types and those new types can be
easily represented in XML as part of a SOAP payload.
1.5.2 SOAP RPC format
Section 7 of the SOAP specification titled Using SOAP with RPC defines the XML
element that represents a function call and the element that contains the return code in the
response message.
The payload is in XML, a single <methodCall> structure. The <methodCall> must
contain a <methodName> sub-item, which is a string containing the name of the method
to be called. If the procedure call has parameters, the <methodCall> must contain a
<params> sub-item. The <params> sub-item can contain any number of <param>s, each
of which has a <value>.
The following HTTP request represents how you would invoke a method using the SOAP
protocol:
POST /cgi-bin/purchase-book.cg HTTP/1.1
Content-Type: text/xml
Content-Length: 555
<SOAP-ENV:Envelope …
<SOAP-ENV:Body>
<PurchaseBook>
<ISBN xsi:type=”xsd:integer”>0201379368</ISBN>
19
</PurchaseBook>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This HTTP request points to a uniform resource identifier (URI) of /cgibin/purchase-book.cgi. Since the SOAP specification says nothing about how a
component is activated, it's up to the code behind this URI to decide how to activate the
component and invoke the specified method. The body of the response is also a single
XML structure, containing the Envelope, Body, and a <methodResponse>. When RPC
sends a wrong SOAP message, server will return a fault result that includes fault code,
fault string, and possible detail.
20
2 SOAP for Java: Project Motivation and Accomplishment
The SOAP for Java (SFJ) project aims at providing a tool for Java programs to
communicate with SOAP web services through RPC calls. With this tool, a Java program
can make a RPC call by creating an object with the name of the class as the procedure
name and the parameters as the fields of the object. Then the tool can be used to serialize
the Java object, send the XML message over the network, receive the result XML
message and de-serialize the XML message back into a Java Object.
2.1
SFJ Motivation
According to the SOAP specification, information can only be transmitted between a
sender and a receiver via XML. This means that Java objects cannot be exchanged
without being serialized and deserialized from XML.
Generally speaking, serialization is the process of converting a Java object into an XML
instance, and deserialization is process of reconstructing the Java object from the XML.
As mentioned in the introduction part, the current SOAP supports both messaging and
PRC interaction, the project concentrates on the RPC part only and adheres to the SOAP
1.1 specification. When performing PRC calls with SOAP, two types of payload are
exchanged between the Web services requestor and the provider:
Parameters to remote methods (RPC request)
Return values (RPC response)
The payloads are usually encoded using Section 5 encoding. Section 5 encoding
describes a methodology for transforming an object graph into XML. If the methodology
is adhered to religiously, then the SOAP XML can be reconstructed back to its original
form. Another encoding approach constrains the payloads with schema. This project
21
works with Section 5 encoding. This can be specified by setting the encodingStyle
attribute to the URI http://schemas.xmlsoap.org/soap/encoding/.
2.2
SFJ Accomplishments
With this SFJ package, a RPC client can make a call by creating a Java class with the
name of the class the same as the name of the remote procedure requested and the
parameters of the procedure as the fields of the class. Then instantiate an object of the
class and assign the values of the parameter to the corresponding fields of the object. For
example, if a client wants to invoke a method named echoString with namespace ns
associated with http://soapinterop.org/. The class should be defined as below:
public class ns_echoString{
public String inputString="";
public ns_echoString(){}
public ns_echoString(String input){
inputString=input;
}
}
With the SFJ serialization method, a SOAP message is created as shown below:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope
env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http://soapinterop.org/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Body>
<ns:echoString>
<inputString xsi:type="xsd:string">hello</inputString>
</ns:echoString>
</env:Body>
</env:Envelope>
22
When performing a RPC call with the SFJ tool, the process on the client side can be
summarized as listed below:
1. The client defines a class. The name of the class corresponds to the name of the
procedure the client wants to invoke. The fields of the class correspond to the
parameters of the procedure.
2. The client instantiate an object of the class and assign the values of the fields to be
the desired values of the parameters.
3. The client uses the SFJ package to send the object to the PRC server. Behind the
scene, the SFJ tool serialize the Java object, sends it over the network to the
server, get the response XML message and deserialize the message back into an
object. The result value(s) are the fields of the object.
The server side works symmetrically. The process is illustrated in the figure below:
As the project is an improvement over the project by a former graduate student Dongmei
Gao of the Computer Science Department here at FSU, it is worthwhile to point out some
of the majors differences between the two projects.
1. The start point of the Java object in the XML message is located by matching
both the expected class name (extracted from the WSDL file) and the namespace
URI, as apposed to assuming the first tag after the soap body is the start point.
23
2. The namespace prefix is located by pushing and popping the (prefix, URI) pair
onto and out of a stack with the corresponding level information. This can ensure
the proper scoping.
3. The multireferenced entities are serialized as empty elements. The elements that
contain the actual values are listed as the sibling elements of the serialized Java
object.
4. Multireferenced entities can be properly serialized and deserialized both as the
fields of an object and as an element of array.
5. Multi-dimensional arrays can be properly serialized and deserialized.
6. SOAP data types that are not built-in types in Java are handled by creating a
wrapper class with methods for encoding/decoding. Examples are base64Binary
and dateTime.
7. Handle polymorphic accessors.
24
3 SJF Design and Implementation
This section presents the design and implementation of SFJ in Java. The package of the
SFJ project contains several Java files with the Java class Soap as the entry point. The
constructor of the class Soap takes a String object as input, which is the name of the
result class that can be known through the WSDL file from the Web services. The RPC
request is sent to the server by calling the method send of Soap class. The result of the
RPC call is accessed by calling the method getResult of the Soap class. The
implementation can be described in three parts: serialization, transmission and
deserialization.
3.1
Serialization
The send method takes three parameters as input: a String object as the destination of the
RPC call, a String object as the action of the RPC call, and the Object to be serialized. As
explained in Section 2, this object represents the RPC call, with the name of the class as
the name of the RPC call and the fields as the input parameters of the RPC call.
The serialization part makes use of the Java reflection package to examine and
decompose an object into sub-objects that are then mapped to the SOAP basic types. The
mapping of the Java types to SOAP types are listed in the following table:
Table 1: type mapping between Java and SOAP
Java
SOAP
String/StringBuffer/char xsd:string
Boolean/Boolean
xsd:Boolean
Double/double
xsd:double
Long/long
xsd:long
Float/float
xsd:float
Integer/int
xsd:int
Short/short
xsd:short
Byte/byte
xsd:byte
BigDecimal
xsd:decimal
The serialization part of SFJ performs the following steps:
1) Create the SOAP message header in XML, which includes the namespaces attributes
of the messages. The mapping between the prefixes and the URL of the namespace is
kept in a Java hash table. This message is kept in a Java StringBuffer.
2) Serialize the RPC call object into XML format and keeps the message in the same
Java StringBuffer.
3) Create the HTTP header with the information provided by the destination URL and
action. The length of the content is just the length of the StringBuffer. Create socket
and the SOAP message is send to the server. If the destination URL is set to be null,
then the message is sent to standard input.
The second step is explained in details:
3.1.1 Locating Multi-references
The SOAP specification 1.1 requires that multi-referenced values should be encoded as
independent element with id attributes and each accessor to this value be an empty
element having a href attribute which references the corresponding independent elements.
To locate the multi-referenced value, the method serialize is called before constructing
the SOAP message. This method takes an object as input parameter and uses two
HashSets. One of the sets is called refs, which is used to hold objects. If an object cannot
be put into the refs HashSet, which signals that this is a multi-referenced object, it will be
put into the other HashSet multirefs, the container of multi-referenced objects. As the
object is successfully put into the multirefs HashSet, it is given an id, which is an Integer.
The fields of an object and the elements of arrays are de-composed into sub-objects by
recursively calling the method serialize. The primitive types are ignored as multireferences.
For example, an array is serialized by the following code:
26
if (o.getClass().isArray()){
if(!o.getClass().getComponentType().isPrimitive())
for (int i = 0; i <Array.getLength(o); i++)
serialize(Array.get(o,i));
}
If an array of String is declared as String[] s={“hello”, “hello”, “world”}, the String hello
will be determined to be a multi-referenced object. On the other hand, if an array of int is
serialized, none of the elements will be multi-referenced even some of the elements may
be of the same value.
3.1.2 Construct the message
The actual SOAP message is constructed with the method out, which takes an object as
input parameter. This method also uses recursion to print out the elements of an array and
the fields of an object. The base cases are the objects of the basic types as listed in the
Table 1. To print out multi-referenced object as an empty element, the method first tries
to determine if the object is in the HashSet multirefs, which is the container of the multireferenced objects. If it is indeed a multi-referenced object, the method will just print out
the tag of the object and its href attribute. If not, the method continues to determine the
type of the object by using the Java keyword instanceof.
For example, the String array in the previous case will be printed out as follows:
String [] s={“hello”, “hello”, “world”};
<s enc:arrayType="xsd:string[3]">
<enc:Array href="#_1"/>
<enc:Array xsi:type="xsd:string">world</enc:Array>
</s>
27
It is worthwhile to point out that this implementation uses recursion to dynamically
determine the dimensions of the input array and print out the elements of the array rowwise. This cannot be handled in the old implementation. The segments of this particular
part are shown here:
To dynamically determine the dimensions of the array, the following code is used:
if (o.getClass().isArray()){
StringBuffer dimension=new StringBuffer();
Object compo=o;
int c=0;
Class compClass=o.getClass();;
dimension.append("[");
while(compClass.isArray()){
if(c!=0)
dimension.append(",");
dimension.append(Array.getLength(compo));
c++;
compo=Array.get(compo,0);
compClass=compClass.getComponentType();
}
dimension.append("]");
if(compClass.getName().equals("java.lang.Object"))
return "xsd:ur-type"+dimension.toString();
try{
compo=compClass.newInstance();
}
catch(Exception e){System.out.println(e);}
return typeof(compo)+dimension.toString();
}
28
To print out multi-dimensional array, the following code is used:
private void printArray(Object o, String indent) throws IOException{
Class c=o.getClass();
if(c.isArray() && !c.getComponentType().isArray()){
for(int i=0; i<Array.getLength(o); i++)
out(Array.get(o,i),"enc:Array",indent);
return;
}
for(int i=0; i<Array.getLength(o); i++)
printArray(Array.get(o,i), indent);
}
A two-dimension String array whose element is the string representing the row number
and column number is printed in the following XML format:
<input2DStringArray enc:arrayType="xsd:string[2,3]">
<enc:Array xsi:type="xsd:string">row0col0</enc:Array>
<enc:Array xsi:type="xsd:string">row0col1</enc:Array>
<enc:Array xsi:type="xsd:string">row0col2</enc:Array>
<enc:Array xsi:type="xsd:string">row1col0</enc:Array>
<enc:Array xsi:type="xsd:string">row1col1</enc:Array>
<enc:Array xsi:type="xsd:string">row1col2</enc:Array>
</input2DStringArray>
3.1.3 Print the independent elements
According to the SOAP 1.1 specification, the independent elements should be printed out
at the end of the message. This project conforms to this specification and adds a method
29
printRef, which iterates through the multi-reference HashSet and prints out the
independent elements with the id attributes.
3.2
Transmission
SFJ uses sockets to send and receive messages. The default port number is 80. If the
server uses another port number, this number can be appended to the server’s host name.
After receiving the message from the server, the client first examines the HTTP header to
determine if there is a network error. The result is written into a XML file called
result.xml. If there is no error, the file will be deserialized using the class name given by
the constructor, otherwise, the file will be deserialized using a fault class. When the URL
of the destination is set to be null, the input file will be deserialized.
3.3
De-serialization
Deserialization refers to the process of converting a Java object from an XML file. In this
project, the process makes heavy use of an API, Document Object Model, commonly
called the DOM. At the core of DOM is a tree model. That is the XML document is
supplied in a tree format completely in memory. In a DOM tree, the textual value of a
node is represented as a child node of type Text. All DOM structures can be treated either
as their generic type, Node, or as their specific type. DOM level 2 provides some
additional modules. This project uses the TreeWalker to traverse the DOM tree.
The deserialization function is accomplished in a class Deserialize, whose constructor
takes a HashTable, which is the namespace HashTable and a String, which is the name of
the target class from the XML file. The entry point is the method processDes. This
method takes a String as input, which is the name of the XML file. The process of the
deserialization can be viewed in the following steps:
1. Locate the node in the DOM tree which corresponding to the start of the class
content.
2. Assign values to the fields of the class.
3. Resolve independent elements.
Each step is explained in details as follows:
30
3.3.1 Locate the start node
An Apache DOM parser is used to get the document and a TreeWalker is constructed
with the following code:
DOMParser parser=new DOMParser();
Parser.parse(response.xml);
Document doc=parser.getDocument();
TreeWalker
walker=((DocumentTrversal)doc).createTreeWalker(
doc, NodeFiler.SHOW_ALL, null, true);
To locate the start node, the DOM tree is traversed. The name of each node is compared
with the name of the class, and the namespace URI is also matched to the namespace of
the class. If both are matched, then that node is the start node for the class and the values
of the fields of the class can be located as the child nodes of the start node.
3.3.2 Assign the values
After the start node is located, the method deserialize is called to assign values to
instantiate objects and assign values. This method takes two parameters: a node and the
corresponding class. The return value of the method is an object instantiated from the
class with the values determined from the node. As in most of the methods in this project,
this method also uses recursion. The recursion stops when the class is of primary type in
Java.
To match a node with a field of the class, there are three things needs to be checked. First
is the matching between the name of the node and the name of the class. Second is the
match of the namespace of node and the namespace of the class. The namespace URI is
looked up using the prefix and the actual URIs are compared. Finally, the type of the
node and the type of the class are also compared if the node has type attribute. When
comparing the names of the node’s and the class, there is the so-called wildcard case.
This means that if the class name starts with an underscore, this name can match any
name. The following codes show the implementation of the matching process:
31
if(fields[childNum].getName().charAt(0)=='_'){
/*the wildCard case, try to match with the current field*/
if(typeMatch(child, fields[childNum].getType())==true){
fieldIndex=childNum;
fieldC=fields[fieldIndex].getType();
}
}
else{ /*look through each field to find the match*/
for(fieldIndex=0; fieldIndex<fields.length; fieldIndex++){
fieldName=fields[fieldIndex].getName();
int p=fieldName.indexOf("_");
if(p!=-1){
fieldPrefix=fieldName.substring(0,p);
fieldName=fieldName.substring(p+1);
}
else
fieldPrefix=null;
if(fieldName.equals(nodeName)){// same name, check the namespace
if(compareURI(nodePrefix, fieldPrefix)==true){
fieldC=fields[fieldIndex].getType();
if(typeMatch(child, fieldC)==true)
break;}
}
}
To instantiate a new object, the method newInstance in the Class class is used. Since this
method requires that there is an empty constructor present in the class, a nullary
constructor should be added to the class definition, if one is not present. When the class is
an array, the newInstance method in the Array class is used. This method takes two
arguments, one is the class of the component type, and the other is the dimension. The
array type and dimension information can be got from the node attribute. The array
component class can also be gotten from the class information. To create a primitive type
32
object, each different type has to use a different method. The following code illustrates an
example of creating a primitive type object.
String type=name.substring(name.lastIndexOf(".")+1);
if(type.equals("String"))
return new String(value);
The values of the fields of a class or the element of an array are assigned by using the set
function provided in both Field class and Array class. If the type of the field or element is
primitive, a wrapper for that primitive type should be passed as the input parameter.
One improvement of this project over the old one in the deserialization part is that it can
handle the case when the field of the class is multidimensional array. The array
component type and the array dimension is determined by the following code:
private Object [] getArrayDimenType(Class c){
int d=0;
Object[] result=new Object[2];
while(c.isArray()){
d++;
c=c.getComponentType();
}
result[0]=String.valueOf(d);
result[1]=c;
return result;
}
This array component type information can be used to check with the array type
information provided in the node attribute. Also, the type class can be used to instantiate
the array. It is better to used this class instead of using Class.forName(name) method,
since this can handle primitive array component case.
33
The following codes are used to set the element of a multidimensional array dynamically
using recursion:
private void setArray(Object o, Class arrayClass)throws Exception{
Class c=o.getClass();
if(c.isArray() && !c.getComponentType().isArray()){
setElement(o, arrayClass);
return;
}
for(int i=0; i<Array.getLength(o); i++)
setArray(Array.get(o,i), arrayClass);
}
private void setElement(Object o, Class arrayClass) throws Exception{
Node child;
for(int i=0; i<Array.getLength(o); i++){
child=arrayElements.item(k++);
if(typeMatch(child,arrayClass)==true){
if(arrayClass.isPrimitive())
Array.set(o,i,wrap(arrayClass,child.getFirstChild().getNodeValue()));
else
Array.set(o, i,deserialize(child,arrayClass));
}
}
}
}
3.3.3 Resolve Independent Element
When the deserialization process encounters a multi-referenced element, it first sets the
value of the corresponding object to null. Then the relevant information is used to create
an object of class obRef, which is then put into a hash table waitref. The obRef object is
used as a key and the href attribute is the value. The definition of the obRef class is listed
as follows where the fieldIndex can be either the index of the fields of a class or the index
of the element of an array. The class type is also kept in a hash table.
public class obRef{
int fieldIndex;
Object o;
public obRef(Object o, int i){
fieldIndex=i;
34
When the deserialization process encounters an independent element, it deserializes that
node using the class type associated with the id number. Then the deserialized object is
kept in a hash table called ref as value and the id attribute as the key.
After the deserialization process is finished, both the waitref and the ref hash tables are
iterated through and the object is assigned to corresponding fields of classes and elements
of arrays. The following code shows how this process is done:
Iterator refItor=ref.entrySet().iterator();
Iterator itor=waitref.entrySet().iterator();
Map.Entry entry;
while(refItor.hasNext()){
Map.Entry refEntry=(Map.Entry)refItor.next();
String ID=(String)refEntry.getKey();
while(itor.hasNext()){
entry=(Map.Entry)itor.next();
if(((String)entry.getValue()).equals(ID)){
Class c=((obRef)entry.getKey()).o.getClass();
int i=((obRef)entry.getKey()).fieldIndex;
try{
if(c.isArray())
Array.set(((obRef)entry.getKey()).o,i,refEntry.getValue()); }
else{
Field[] fields=((obRef)entry.getKey()).o.getClass().getFields();
fields[i].set(((obRef)entry.getKey()).o,refEntry.getValue());
}
}
catch(Exception e){System.out.println("Error here"+e);}
}
}
}
35
3.4
Namespaces
SOAP specification 1.1 states that a SOAP application SHOULD include the proper
SOAP namespace on all elements and attributes defined by SOAP in message that it
generates. A SOAP application MUST be able to process SOAP namespaces in messages
it receives. A namespace is a group of element and attribute names. Namespaces aren’t
useful only for preventing name clashes. More generally, they help the XML processor
sort out different groups of elements for different treatments. A namespace must be
declared in the document before being used. The declaration starts with the keyword
xmlns: followed by the namespace prefix, an equal sign and a URL. This declaration
is included as the attribute of a node.
<env:Envelope
env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
In java class code, namespace is indicated as ns_ClassName. ns is the namespace name.
The URI/URL of ns will be defined by clients according to server’s information.
Most often, the root element contains the declarations used in the document, but it is not
required. Namespaces apply only to the element declaring it and the descendants of that
element. When de-serialize objects, a stack is used to store the namespaces URL, the
prefix and the XML level. When the deserialization process encounters a new node, it
pushes the namespace information onto the stack, and pops the namespaces information
of itself and its descendants out of the stack when it leaves the node. In this way, only the
valid namespace information will be kept in the stack.
The following code shows how it is implemented:
36
NamedNodeMap attributes = node.getAttributes();
int prevLevel=getNodeLevel(prevNode);
int level=getNodeLevel(node);
if(level<prevLevel){
//leaving the current level, need to pop the stack
while(((Triple)uriStack.peek()).getLevel()>level){
uriStack.pop();
}
}
int p;
for(int i=0; i<attributes.getLength(); i++){
Node currattr=attributes.item(i);
String attrName=currattr.getNodeName();
String attrValue=currattr.getNodeValue();
p=attrName.indexOf("xmlns");
if(p!=-1){
if(attrName.charAt(p+5)==':'){
uriStack.push(new Triple(level,
attrName.substring(p+6),attrValue));
}
}
}
3.5
Polymorphic Accessor
SOAP 1.1 specifications require that a polymorphic accessor instance MUST contain a
type attribute that describe the type of the actual value. This can be easily accomplished
in Java since Java supports run time type determination. To handle the instantiation of
polymorphic accessor, the deserialization process first tries to match the type information
provided in the node’s type attribute with the Java class. If it fails, it proceeds to
37
determine if the Java class is a super class of the type using the method isAssignableFrom
provided in the Class class. If it is, the derived class is instantiated instead of the super
class.
3.6
Fault Class
When the application receives an error message from the server, the fault class is passed
as the name of the class to be deserialized, instead of the response class. The definition of
the fault class is as follows:
public class env_Fault{
public String faultcode="";
public String faultstring="";
public String detail="";
}
38
4 Client-Server Application Example
To test the functionality of the tool developed in the project, the interoperability (interop)
tests which are widely used in the SOAP world to test the interoperability of SOAP
implementations. The current version of the interop test is Round 2. The base group
provides 14 echo tests and Group B provides 5 echo tests, which introduces methods with
more complex serialization requirements than those of the base "interop" interface.
Base group tests include the following tests:
echoString
echoStringArray
echoInteger
echoIntegerArray
echoFloat
echoFloatArray
echoStruct
echoStructArray
echoVoid
echoBase64
echoHexBinary
echoDate
echoDecimal
echoBoolean
39
Group B tests include the following methods:
echoStructAsSimpleTypes
echoSimpleTypesAsStruct
echo2DStringArray
echoNestedStruct
echoNestedArray
The tool developed in this project has passed all these nineteen tests. In this section, two
examples are given.
4.1
echoStructArray
This method accepts an array of structures and echoes it back to the client. The structure
used is the same defined by the following schema:
<complexType name="SOAPStruct">
<all>
<element name="varString" type="xsd:string" />
<element name="varInt" type="xsd:int" />
<element name="varFloat" type="xsd:float" />
</all>
</complexType>
The relevant information to make the RPC call is listed as follows:
Service Endpoint URL: http://www.dolphinharbor.org/services/interop2001
SoapAction: http://soapinterop.org/
Method Name: echoStructArray
With this information, three Java classes are created: the s_SOAPStruct class is used to
define the structure to be echoed.
public class s_SOAPStruct{
public String varString;
public int varInt;
public float varFloat;
40
public s_SOAPStruct(){}
public s_SOAPStruct(String inputString, int inputInt, float inputFloat){
this.varString=inputString;
The ns_echoStructArray class is used to send the RPC request and the
ns_echoStructArrayResponse is used to define the return value.
public class ns_echoStructArray{
public s_SOAPStruct[] inputStructArray;
public ns_echoStructArray(int size){
inputStructArray=new s_SOAPStruct[size];
}
}
public class ns_echoStructArrayResponse{
public s_SOAPStruct[] _return;
}
The following code is used to instantiate the request object, and use the SFJ tool to send
the request to the server:
String endPoint="http://www.dolphinharbor.org/services/interop2001";
s_SOAPStruct s=new s_SOAPStruct("Hello", 3, (float)3.12);
Object o=new ns_echoStructArray(Integer.parseInt("2"));
Array.set(((ns_echoStructArray)o).inputStructArray, 0, s);
Array.set(((ns_echoStructArray)o).inputStructArray, 1, s);
Soap so=new Soap("ns_echoStructArrayResponse");
so.addNameSpace("ns", "http://soapinterop.org/");
so.addNameSpace("s", "http://soapinterop.org/xsd");
so.send(endPoint, action, o);
41
This piece of code instantiates an object of s_SOAPStruct and creates an array of
s_SOAPStruct with two elements with both of the elements pointing to the same
s_SOAPStruct object. So when an object of ns_echoStructArray is instantiated with this
array and sent over to the server using the SFJ tool, the SOAP message will contain an
independent element. The following shows the SOAP message generated:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope
env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http://soapinterop.org/"
xmlns:s="http://soapinterop.org/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Body>
<ns:echoStructArray>
<inputStructArray enc:arrayType="s:SOAPStruct[2]">
<enc:Array href="#_1"/>
<enc:Array href="#_1"/>
</inputStructArray>
</ns:echoStructArray>
<id id="_1" xsi:type="s:SOAPStruct">
<varString xsi:type="xsd:string">Hello</varString>
<varInt xsi:type="xsd:int">3</varInt>
<varFloat xsi:type="xsd:float">3.12</varFloat>
</id>
</env:Body>
</env:Envelope>
The following Java code shows how the result is got and printed out:
Object result=so.getResult();
for(int i=0; i<((ns_echoStructArrayResponse)result)._return.length; i++){
print(((ns_echoStructArrayResponse)outObj)._return[i].varString);
print(((ns_echoStructArrayResponse)outObj)._return[i].varInt);
print(((ns_echoStructArrayResponse)outObj)._return[i].varFloat);
}
42
The response message from the server is:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns2="http://soapinterop.org/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<m:echoStructArrayResponse
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:m="http://soapinterop.org/">
<return SOAP-ENC:arrayType="ns2:SOAPStruct[2]">
<item href="#id1"/>
<item href="#id1"/>
</return>
</m:echoStructArrayResponse>
<id1 SOAP-ENC:root="0"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
id="id1" xsi:type="ns2:SOAPStruct">
<varString xsi:type="xsd:string">Hello</varString>
<varInt xsi:type="xsd:int">3</varInt>
<varFloat xsi:type="xsd:float">3.12</varFloat>
</id1>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
43
4.2
Polymorphic accessor
This example shows polymorphic accessors in SOAP message. The Java code declares an
array of objects with and sets the first two elements to be the same s_SOAPStruct objects
and the last one a String.
public class ns_echoObjectArray{
public Object[] inputArray;
public ns_echoObjectArray(){}
public ns_echoObjectArray(int size){
inputArray=new Object[size];
}
}
so=new Soap("ns_echoObjectArray");
int size=3;
o=new ns_echoObjectArray(size);
s=new s_SOAPStruct("Hello", 3, (float)3.12);
Array.set(((ns_echoObjectArray)o).inputArray, 0, s);
Array.set(((ns_echoObjectArray)o).inputArray, 1, s);
Array.set(((ns_echoObjectArray)o).inputArray, 2, new String("world"));
This is the SOAP message generated by the SFJ tool. In this message, each of the
elements shows the correct type information as required. When the same message is
deserialized, the same object array can be got with proper class types for individual array
elements.
44
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope
env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http://soapinterop.org/"
xmlns:s="http://soapinterop.org/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Body>
<ns:echoObjectArray>
<inputArray enc:arrayType="xsd:ur-type[3]">
<enc:Array href="#_1"/>
<enc:Array href="#_1"/>
<enc:Array xsi:type="xsd:string">world</enc:Array>
</inputArray>
</ns:echoObjectArray>
<id id="_1" xsi:type="s:SOAPStruct">
<varString xsi:type="xsd:string">Hello</varString>
<varInt xsi:type="xsd:int">3</varInt>
<varFloat xsi:type="xsd:float">3.12</varFloat>
</id>
</env:Body>
</env:Envelope>
45
5 Conclusions and Future work
SFJ is a useful tool to enable Java applications to interact with other applications using
SOAP. It helps a Java program to perform a SOAP remote method call to the SOAP
server. The type of parameters of the remote call can be most of the SOAP data types
such as boolean, int, float, string, array or more complex types such as dateTime and
base64, which have no direct corresponding Java built in types. All a client needs to do is
to create one class whose name is the same as the name of the remote method and whose
fields are the method’s parameters and another class corresponding to the return value.
Then with the SFJ tool, the client can make a method call to the SOAP server and get the
result back as a Java object. Since the deserialization process uses DOM, which incurs
heavy overhead, creating a more efficient deserialization process without DOM will be
one potential for improvement.
46
Reference
[1] Robert van Engelen: The SOAP Stub and Skeleton Compiler For C and C++.
http://www.cs.fsu.edu/~engelen/soap.html
[2] Robert A. van Engelen and Kyle Gallivan, The gSOAP Toolkit for Web Services
and Peer-To-Peer Computing Networks, in the proceedings of the 2nd IEEE
International Symposium on Cluster Computing and the Grid (CCGrid2002),
pages 128-135, May 21-24, 2002, Berlin, Germany.
[3] Bruce Eckel: Thinking in Java, Second Edition
[4] W3C Simple Object Access Protocol (SOAP) 1.1. & 1.2.
http://www.w3.org/TR/2000/NOTE-SOAP-20000508
http://www.s3.org/TR/2001/WD-soap12-20010709/
[5] Java 2 Platform, Standard Edition, v 1.4.0 API Specification.
http://java.sun.com/j2se/1.4/docs/api/
[6] Brett McLaughlin, Java and XML 2nd Edition
[7] Xerces 1.4.3 API Specification. http://xml.apache.org/xercesj/apiDocs/index.html
[8] CML-RPC Specification. http://www.xmlrpc.com/spec
47