Академический Документы
Профессиональный Документы
Культура Документы
by
Michael Ryan
at
Pace University
August 2005
ii
ABSTRACT
Web services are gaining a tremendous amount of momentum in recent years as a viable tool in
distributed computing. Web Services have evolved from other distributed technologies, which
include Java RMI, CORBA, and DCOM, but their specification deficiencies with respect to
complete platform and programming language independence, and interoperability are creating a
need for a more suitable solution. Despite its youth, Web Services offer to provide such a
solution by inheriting the beneficial traits of its predecessors, utilization of an IDL in the form of
a WSDL (Web Service Description Language) for one, and at the same time, avoiding the
negative aspects associated with its predecessors, which include tight coupling specifications,
potential for firewall blocking, long development times, and higher costs. Through the use of
standardized technologies (HTTP, SOAP, and XML), Web Services offer to deliver results.
I present a book broker in two formats: as a web interface and as a Composite Web Service.
Both formats provide book-pricing data from various vendors and book search functionality
based on any combination of factors, such as author, title, publisher, keyword and ISBN. The
purpose of this project is to provide a publicly accessible book broker that is superior in
functionality to existing book brokers today, to enable developers to integrate my Web Service
into their own applications, promoting data exchange regardless of the platform or programming
language being used and lastly, to provide a good case study of how to bring out the best in Web
Services.
iii
ACKNOWLEDGEMENTS
I would like to thank my advisor, Dr. Lixin Tao, for his guidance and expertise. Many times
when I began to veer off course, he would step in and put me back on track.
I would like to thank the department Chairperson, Dr. Narayan Murthy, for convincing me to
pursue my thesis and making me aware of the potential personal rewards that come about from
the entire process.
A special thank you to Dr. Mary Courtney for her motivational comments, finding time to
discuss my project and for re-shuffling her schedule on my behalf.
Finally, I would like to thank my entire family for their feedback, support and love.
iv
TABLE OF CONTENTS
LIST OF FIGURES ix
CHAPTER 1 INTRODUCTION
4.1 Overview 31
APPENDIX 2 Index.jsp 84
APPENDIX 3 Results.jsp 86
APPENDIX 4 Controller.java 88
REFERENCES 146
viii
LIST OF TABLES
LIST OF FIGURES
CHAPTER 1 INTRODUCTION
meet the demands of business. Firms struggle to manage the costs associated with
applications to trading partners, service providers or third parties. Firms are continuously
technology, are appropriate to any type of networking environment and can support
peer-to-peer relations. Web services incorporate open standards (i.e. SOAP, XML,
HTTP), which result in a modular structure that provides a foundation for application
interoperability. The functionality provided by a Web service can vary from simple data
discovered and invoked to access a weather report, research currency exchange rates, or
retrieve a book price. A more complex Web service may be invoked to handle multiple
orders, work orders, financial and client reporting, and manufacturing data.
One of the most compelling aspects of Web services is the ability to aggregate various
Web services into one higher-level Web service by way of process composition that is
executed in a specific sequence. The open standard, building blocks that make up the
Web service architecture allow for the implementation of multiple Web service
invocations and can lead to new functionality. A consumer can now invoke a composite
Web service and shop for multiple currency exchange rates from numerous Web services
all from one locale. An enterprise can improve their supply chain application by adding a
composite Web service that researches suppliers offering the best prices. Web service
composition creates more flexibility for consumers and enterprises, promotes code re-
Through the use of open standards, process composition, and loose coupling
specifications, Web services offer to correct the integration problems many Enterprises
face today. The cause of these integration problems is that since many applications are
built around different platforms and programming languages, it is difficult to have these
programming languages, such as C++, Java, Visual Basic, and reside on various
3
platforms, such as Windows or Linux based systems. Moreover, most business data are
barriers. A few specific conflicts include the use of Java’s Collection class, passing an
array with a null element, and namespace conflicts. Despite these obstacles, Web
services present a solution by establishing a common ground for all parties to interoperate
effectively.
formed and delivers sets of use cases, profiles, sample applications and test tools. WS-I
has provided the Basic Profile (BP) 1.0 specification to address existing interoperability
Overall, Web services are still in their youth, but the technology is being employed today
and is continuously undergoing fine-tuning. The optimism is so high that research firms
Surveys from leading market research firms (Gartner Group, Forrester, IDC, and others)
find the adoption of Web services involves three distinct phases of progression. The
initial phase entails organizations beginning to adopt Web Services behind the firewall.
They experiment with pilot projects to gain hands-on experience and implement low-risk
incremental strategies when migrating over to a Web service solution. As firms establish
a comfort zone, they progress to the next phase of Web service adoption where they start
integrating applications and business processes beyond the firewall. Enterprises begin to
build sophisticated, collaborative systems with trading partners. The final phase deals
with the presence of numerous publicly available Web Services. Firms initiate the
public Web Services. Each phase presents numerous challenges for enterprises and
developers. These include security issues, interfacing with legacy systems, and service
level agreements.
I present CWS, a book broker composite Web service that fulfills three objectives. First,
CWS provides a superior tool for consumers, allowing them to search for book
information from numerous web sites from one centralized web site. Currently,
numerous book brokers (i.e. Chambal.com, FetchBook, BookFinder4U) exist, but fail to
offer the same robust, book search functionality that CWS offers and are not making the
Secondly, CWS enables developers to integrate CWS’ J2EE-based Web service into their
being used on their end. A .NET client application has no difficulty exposing CWS’
methods.
Lastly, CWS presents a good case study of how to bring out the best in Web Services by
emphasizing the power of process composition, the ability to alter the building blocks of
the Web service stack and providing dual B2B and B2C supports.
1.6 Overview
Chapter 2 begins with a brief summary of B2B distributed technologies and details the
component layers of the Web service standard. Recent Web service trends and the
current book broker environment are also discussed. Chapter 3 outlines CWS’
requirements, functional specifications through specific use cases and CWS’ architecture.
Chapter 4 addresses the implementation of CWS’ Web interface and composite Web
service. Chapter 5 covers test cases which verify how successful CWS is in satisfying the
use cases specified in Chapter 3, and how CWS’ functionality matches up to third party
Web services and the major book brokers. Lastly, Chapter 6 details the future of Web
Distributed computing, in its simplest form, deals with providing a tool for a client
program, running on a local host, to call or invoke a server method, running on a remote
host, and to retrieve the result of the remote execution. A client can utilize different
communication styles when contacting a remote server. A client can simply call a remote
object (Remote Method Invocation or RMI) or even put messages or receive messages
from a remote queue (Message queuing). Many distributed technologies have been
developed over the years utilizing various styles, but three key distributed technologies
stand out from the rest: Java RMI, CORBA, and DCOM. Each distributed computing
paradigm is unique in its own right, but they all share one critical trait: they have all
Java RMI or Java Remote Method Invocation entails having an object call a method of a
remote object. The remote object is located on a different Java Virtual Machine (JVM)
and possibly, on another machine. In order for the two objects to communicate, a "stub"
or "proxy", located on the caller's JVM, and a "skeleton" or “tie”, located on the remote
object's JVM, are needed. The “stub” and “skeleton” represent Java public interfaces.
The process involves a caller gaining direct access to the stub, the stub transforms the
“marshaling” or “serialization”), the stub relays the caller's method call to the skeleton
7
using a given protocol and transport mechanism, the skeleton converts the incoming byte
object based on the received parameters, and the response comes back through the
reverse path. Java RMI utilizes a wire protocol known as Java Remote Method Protocol
(JRMP).
2.1.2 CORBA
CORBA utilizes an Interface Definition Language (IDL), which allows for client/server
object interaction within a specific Object Request Broker (ORB). The ORB is the
intermediary that creates the connection between distributed objects. A CORBA object is
acquires its object reference and uses it as a handle to make method calls. The ORB is
responsible for all the mechanisms required to find the object's implementation, prepare it
to receive the request, communicate the request to it, and carry the reply back to the
client. The wire protocol that is used by CORBA is known as Internet Inter-ORB
2.1.3 DCOM
DCOM is the distributed form of Component Object Model (COM), which builds an
object remote procedure call layer on top of DCE RPC. A COM client interacts with a
8
COM object by acquiring a reference to one of the object's interfaces and invoking
style where the client interface is called the “proxy” and the server interface is called the
“stub.” The specification of DCOM is at the binary level and permits integration of
Java RMI, CORBA, and DCOM are still utilized today, but their specification
and interoperability are creating a need for a more suitable solution: Web Services. Web
Services are evolving by inheriting the beneficial traits of its predecessors which include
the utilization of an IDL in the form of a WSDL (Web Service Description Language)
and the use of object-oriented RPC style communication via “stubs” and “skeletons.” At
the same time, the specification of Web Services is avoiding the negative aspects
associated with its predecessors, which include tight coupling specifications, potential for
specification, meaning a client can only interact with a server when both sides have the
appropriate libraries installed on their machines. CORBA requires each endpoint, the
client at one end and the server at the other, to have a compatible Object Request Broker
(ORB). The same holds true for Microsoft DCOM and Java RMI where endpoint
9
implementations must match. Granted a tight coupling specification has its place when
needed, but a more diplomatic and flexible format is the answer. Fortunately,
Web services specifications enforce loose coupling, meaning a client and a server can
client can interact with a J2EE server without having to worry about installing required
Additionally, distributed technologies in use today, namely CORBA and DCOM, are
geared more for internal enterprise use and utilize non-standard ports to communicate.
Thus, a client from outside the enterprise utilizing a standard port, who has appropriately
installed the required libraries, attempting to interact with a firm’s server is going to be
unsuccessful. Aside from the security benefits for the enterprise, such traffic is blocked
by the institution’s firewall by default due to port differentials. This limits the use of
time an open port has to enter the mix. This is time consuming, inefficient and costly.
place expands the use of distributed technologies beyond the enterprise arena. Web
services operate generally via one standard protocol, Hyper Text Transmission Protocol
(HTTP), over open port 80. This eliminates the problem of firewalls blocking traffic due
furthers relationships beyond the enterprise and expands the use of distributed
technologies.
Finally, the development process for distributed technologies of the past tends to take an
cost associated with the additional development time is a major drawback, especially for
IT managers. A more cost effective and reduced development time solution is desired.
Web services are simple to implement and deploy. The components associated with
Web services generally revolve around three technologies: HTTP, SOAP and XML.
Web services operate under a text based protocol, unlike the binary protocols employed
by past distributed technologies. This expedites the development process, reduces costs
Admittedly, Web services possess their share of disadvantages. One of the key issues
facing Web services today is misuse. Web services have generated a tremendous amount
of hype. It is very common to get caught up in the latest industry trend or buzzword.
Freeman and Jones point out that “when a new and exciting technology arises, it is
people misunderstand the benefits and limitations of the technology, but also because
programmers simply want to experiment with the new technology.” [1] Additional
disadvantages include security loopholes, network failures, service level agreements and
11
the few negative aspects surrounding Web Services, the technology is being utilized
Currently, the Web Service architecture consists of many layers. The following stack
demonstrates the building blocks of a Web Service and the corresponding technologies:
The initial layer is the Protocol layer. This layer specifies which mechanism is used to
communicate or invoke a Web Service over a network. FTP or File Transfer Protocol is
used for transmitting files across networks and SMTP or Simple Mail Transfer Protocol
is used for sending e-mail. The most common protocol used over the Internet today is
12
style protocol where a client opens a connection to a server, sends a request, the server
processes its specific utility based on the client request and sends a response back to the
client.
The packaging layer houses a mechanism or protocol that packages and binds messages
sent over a network. SOAP or Simple Object Access Protocol occupies this layer. SOAP
is a lightweight protocol that specifies the format of messages used in Web services and
distributed object infrastructure being used. For a detailed description of SOAP, visit
SOAP messages crossing the wire: a client request and a server response. SOAP
messages are formatted in XML or Extensible Markup Language and consist of four
parts: an optional XML declaration, a SOAP Envelope, an optional SOAP Header, and a
where a client is invoking a server method named multiply with two parameters:
Request
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns1:multiply
xmlns:ns1="urn:MyWebService">
<param1 xsi:type="xsd:int">2</param1>
<param1 xsi:type="xsd:int">3</param1>
13
</ns1:multiply>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Response
<?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/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns1:multiplyResponse
xmlns:ns1="urn:MyWebService"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<return xsi:type="xsd:int">6</return>
</ns1:multiplyResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Both SOAP messages contain the XML declaration <?xml version="1.0" encoding="UTF-8"?>
which specifies the XML version and the character encoding of the XML message. The
SOAP Envelope consists of the XML root element, SOAP-ENV:Envelope, which specifies
the namespaces used in the SOAP message. The optional SOAP Header tag is contained
within the SOAP Envelope, but is not represented in the example above for simplicity.
The SOAP Header is commonly used to transmit authentication and session management
data. The SOAP Body, located within the SOAP Envelope, contains what is commonly
called the “payload.” In the client request, the SOAP Body contains the name of the
method the client wishes to call, multiply, along with the method's input parameters, 2 and
3 in this case. The server response SOAP Body contains the method name concatenated
with Response and the results of the method invocation, 6. Note that even if there is no
return value, a message is still sent back to verify that the method executed.
14
XML occupies the Information layer of the Web Services stack. XML or Extensible
Markup Language is a text-based meta-language that not only describes how data is
structured, but also describes the context of the data, gaining a better understanding of its
detailed introduction to XML. XML plays a key role as the main data interchange format
The Service layer specifies the mechanism, WSDL in this case, for describing the Web
Service and the actual Web Service itself. WSDL or Web Service Description Language
is an XML vocabulary for describing web services. A client needs to know various
pieces of information in order to interact with the Web Service. These include: where the
service can be reached, how the service can be reached, what methods and parameters are
required, and what data types are used by messages sent or received by the web service.
The WSDL document provides all this information in a very unambiguous way. A
WSDL document consists of six major elements and two utility elements:
• The definitions element is the root element and specifies the name of the web service and the
namespaces used throughout the document.
• The message element specifies the message name along with zero or more part elements. The part
elements define the parameters that are required. Zero parts means zero parameters. The message
element only specifies the name, value(s) and the type of each value. It is the job of the portType
element to specify whether the message is for input or output.
• The portType element defines a group of one or more operations, each of which has an operation
element. Each operation element has a name value and defines which message is the input and
which is the output. If an operation represents a request/response dialogue, then the operation
would include two messages. If an operation represents only a request with no response or a
response with no request, it would include only a single message.
15
• The types element declares all the types that are used between the client and the web service for
all the services declared in the WSDL document. Types can be simple or complex.
• The binding element defines a specific portType implemented using a specific protocol such as
SOAP. If a service supports more than one protocol (SOAP, CORBA, etc.), the WSDL document
includes a listing for each.
• The service element specifies the actual location or endpoint of the web service in the form of a
URL.
• The documentation element is a utility element which permits comments to be placed throughout
the WSDL document
• The import element is utilized to import other WSDL documents or XML Schemas
<message name="SayHelloRequest">
<part name="firstName" type="xsd:string"/>
</message>
<message name="SayHelloResponse">
<part name="greeting" type="xsd:string"/>
</message>
<portType name="Hello_PortType">
<operation name="sayHello">
<input message="tns:SayHelloRequest"/>
<output message="tns:SayHelloResponse"/>
</operation>
</portType>
<service name="Hello_Service">
<documentation>WSDL File for HelloService</documentation>
<port binding="tns:Hello_Binding" name="Hello_Port">
<soap:address
location="http://localhost:8080/soap/servlet/rpcrouter"/>
</port>
</service>
</definitions>
A client in possession of the HelloService WSDL document has all the required data
needed to invoke the service. By checking the service element, the client discovers the
reveals the web service can be invoked with an RPC communication style via HTTP and
SOAP. Lastly, the client learns from the portType element that the actual name of the
method to be called is sayHello and the method requires one parameter in the form of a
String type, specified by the part element within the message element.
Not only does a WSDL document describe fully the details of a Web Service, but also a
key selling point for its continued use is that its structure makes it possible to generate
code from WSDL descriptions and WSDL descriptions from code. This expedites client
code development and reinforces the use of XML as a universal format for data
interchange.
The Discovery layer completes the Web Service stack and is occupied by a mechanism,
Description, Discovery, and Integration resides here. For a detailed description of UDDI,
visit http://www.uddi.org . UDDI provides a repository where any entity, at design or run
17
time, can search to find specific Web Services. As the number of Web Service systems
grows, the need for an organized directory is a necessity. The repository contains
information about businesses, the services they provide(Web Services and Non-Web
Services), version changes, and how to access services. A UDDI can be structured for
public use where any person or business can publish their services to the world and
establish partnerships or for private use, where an individual company can create their
own isolated UDDI registry to list the services available within their private network.
An entity that wishes to register their Web Service must do so using XML-based
documents and provide four key data elements, which are used in the discovery process:
• The businessEntity element specifies the web service owner and includes business name,
description, address, and contact information. Every business receives its own UUID (Universally
Unique Identifier) called a businessKey.
• The businessService element describes one specific service. A business can have multiple web
services. Each service is given a unique serviceKey.
• The bindingTemplate element specifies the technical aspects of a single service such as the
endpoint URL and interface information. Each template is uniquely identified by a bindingKey.
• The tModel element or serviceType provides a URL location to a document that provides more
information (metadata) about the service. This document can be a WSDL document(preferred) ,
HTML page, etc. Each tModel is uniquely identified by a tModelKey
Alternative mechanisms can be added to the Web Service stack and consequently,
removing a few existing mechanisms in the process. Two tools that are in widespread
use today are REST and “HTML Scraping.” Both tools simplify the Web Service Stack
dissertation [5], which attempts to capture the characteristics of the Web. In short, a
client using HTTP specifies or binds the method name and parameters directly into the
18
REST example using a similar method call from the SOAP request/response example
above is:
http://www.mywebservice.com/xml?method=multiply¶m1=2¶m2=3
The server makes available a URL to a resource to multiply numbers and return the
results in an XML-formatted response. The REST style, commonly termed “XML over
HTTP”, eliminates the SOAP layer in the Web Services stack and is especially useful for
URL, gathering the HTML source code from the URL, and then pulling the necessary
data from the code through pattern matching. The process does not involve calling a
method and receiving a response, but more of locating a resource through a URL and
housekeeping on the part of a client since any change to the HTML source code from the
URL forces a client to alter their pattern matching code. On the flip side, HTML
scraping is dynamic, can gather up to the minute data and is considered a legitimate last
Overall, the Web Services stack presents a framework for seamless interoperability.
HTTP is a common transport protocol that everyone can utilize. SOAP can bridge the
gap between parties of different languages and platforms. XML is a data exchange
19
mechanism that every a programming language can employ by its text based nature.
WSDL documents provide a universal guidebook and key starting point. Lastly, the
UDDI provides the window to web services, providing a yellow pages for existing
Theoretically, the Web Service distributed architecture appears to have the ingredients for
success and current industry trends support this. Perhaps the most compelling trend deals
with the number of companies that have already deployed Web services. Line56.com
points out that in a Yankee Group survey of 437 enterprises, 48 percent have already
deployed Web services, and another 39 percent plan to do so in 2005 [2]. Additionally,
corporations are solidifying their positions in the Web Service’s market through
talks to acquire Talking Blocks. This can be a huge driving force and can generate a
Software vendors are making a key contribution to the success of Web Services by
creating formidable Web service enabling products for various platforms and
programming languages. Not only do they provide the tools for implementing the
distributed component, but are simplifying the process. One Java toolkit that is in use
today is Apache Axis. Axis through its API simplifies the Web Service building process
by performing many low level tasks (i.e. dynamic WSDL creation and “stub”/”skeleton”
code generation), enabling a developer to focus more on higher level problem solving
and faster deployment of the finished product. JavaSkyline [3] outlines a few Java
20
effort exists among big corporations like IBM, Microsoft, and Hewlett-Packard to
standardize the distributed technology. In the past, these firms were competing amongst
themselves to get the upper hand and gain market share. Today, firms are working
together to come up with a standard and are realizing the financial benefits of forming
The combination of all these factors demonstrate that the Web Services architecture is
gaining the support and confidence of many corporations and this foundation can lead to
The following table illustrates a list of current book brokers on the Web:
CWS is a Web-based book broker application designed to provide book pricing and book
search functionality for a client via a browser and for a client via an application. CWS
allows a client to input specific, book search criteria. Search criteria includes author
name, book title, ISBN, publisher, year of publication, subject, and keyword. In addition,
a client can input a combination of search criteria and not be limited to just one form.
This promotes search refinement and faster response time. Upon receiving a search
request, CWS takes on the role of a book broker and a client itself, and begins to navigate
to various vendors searching for book data originally specified by the client. Once CWS
gathers all the book information from its business partners, CWS presents the results in
list form to the client. Results from a price search are presented with a complete book
detail summary (author, title, publisher, ISBN, manufacturer’s retail price) and a list of
the vendor, current price, and vendor link. Results from a book search are presented with
a total number of books found, a brief summary for each book and option to perform a
price search for a selected book. In the event of an error, an error message is displayed
and a client is asked to perform a new search. Overall, CWS responds to all requests
within 60 seconds.
For a client utilizing a Web browser over the Internet, CWS offers a Web interface,
allowing a user to provide the necessary search criteria for CWS to process and respond
For a client accessing CWS via an application, CWS supplies a composite Web service.
A client application can initially find CWS through a UDDI registry. Upon successful
CWS discovery, a client application can invoke CWS’ Web service. CWS in turn
invokes Amazon’s Web service to gather all book data originally specified by the client
application. Upon completion, CWS’ Web service returns book results in XML format.
In the event of an error, an error message is returned in XML format. Only client
applications that can parse XML documents can utilize CWS’ Web service.
In order to demonstrate CWS’ functionality, use cases are presented. Use cases are
written reports describing a system and its functionality from an external usage
case, the external point of view comes from a person shopping for book prices via their
browser, accessing CWS through CWS’ web user interface (CWSUI) or from an
application searching for book data, accessing CWS through CWS’ composite Web
service (CWSWS).
parameters
2. Verify parameter(s) have been sent
3. Retrieve books from Amazon
4. Build results in XML format
5. Return book results.
6. Parse results
Exception- Step 2: Search parameter(s) are invalid. Return error to user in XML
3.3.1 Architecture
applies two design patterns. The first is the Service Oriented Architecture (SOA) model
(see Figure 2), which consists of a service provider, service broker and service requester.
Figure 2: SOA Model. Source: www.ibm.com IBM Systems Journal Vol. 41, No 2, 2002
CWSWS fills the role of the service provider, providing a service interface to a specific
resource and publishing its service with the UDDI registry. The UDDI registry takes on
the role of the service broker, providing a locale for service requesters to find Web
services. The role of the service requester is filled by a client, usually a person or
computer, who searches registries for Web Services and then binds itself to the provider.
25
The second design framework that CWS applies is Model 2 architecture. Since the
introduction of Java Server Page (JSP) technology, Model 1 and Model 2 architectures
have emerged for building server-side applications. Model 1 (see Figure 3) employs the
use of JSP and JavaBeans to separate business logic from presentation. Model 2 (see
Figure 4) takes it a step further by incorporating Servlets and presenting a format that
follows the Model-View-Controller (MVC) model. The Model consists of data and
business logic, the View is responsible for presenting data and the Controller takes in
client requests, dictates application behavior and dispatches responses to the View.
In the Model 2 framework, the Servlet acts as the controller, taking in requests,
forwarding responses to the appropriate JSP (the view), and instantiating any required
developers. These benefits include capturing the experience of developers from the past
who have already tested such patterns, providing a common vocabulary for team
validation and invokes a normalize() method to housekeep and trim client parameters.
There is a method for each of the 11 vendors. A searchIsbn() method addresses client
requests that specify an ISBN parameter and invokes each of the 11 vendor methods. All
other types of client requests are handled by an amazon() method. A scrape() method
performs HTML scraping and is invoked by each vendor who does not provide Web
services functionality (At the time of this writing, Amazon is the only CWS vendor
the amazon() method with spacing when there are multiple authors for a given book.
27
The methods of the BookBean class (Model) consist of all the accessor methods
pertaining to properties of a given book. These properties include vendor, retail price,
vendor link, title, publisher, year of publication and author. A compareTo() method is
The following diagram presents CWS’ MVC architecture, classes, class inter-
The following sequence diagram demonstrates the events that can potentially take place
CWS does not utilize a database. The BookList, an instance of the Java Vector class,
serves as the key data structure for storing book results. The BookList is not to be
shared by all client requests. Each individual client request must result in the creation of
a new BookList.
CWS’ Web user interface operates as a form page and lists each search criteria: Author,
Title, Publisher, Publish Year, Subject, Keyword, and ISBN. To the right of each
criteria, a user can enter their corresponding search text. In order to initiate a search, a
user selects the “CWS Search” button. The “Clear” button erases all text entered by a
user. CWS’ logo, “About Us” link, “Contact Us” link, and “Home” page link are also
displayed.
In order for CWS to meet the role of a Web service provider, CWS will register via a
Web browser with two UDDIs (IBM and Microsoft) to facilitate discovery. In addition,
CWS provides two methods for client consumption: searchIsbn() and searchAll().
The searchIsbn() method addresses client requests that have specified an ISBN
parameter. The searchAll() method handles all other types of client requests. Each
method returns book results in XML format. CWS utilizes the Apache Axis 1.1 toolkit as
its SOAP engine for deploying CWSWS dynamically and WSDL generation.
30
4.1 Overview
The following implementation of the CWS web interface and the CWS Web Service
demonstrate how effective Web service technology can lead us closer to seamless
interoperability. The chapter is divided into two sections. The first section details the
CWS web interface, which provides book search functionality to the public over the
Internet via a browser. The second section details the actual CWS web service. The
4.2.1 View
The web interface follows Model 2 architecture and consists of a total of seven files:
Index.jsp represents the home page for CWS, providing a means for a user to enter any
publication year, subject, keyword and international standard book number (ISBN).
Once a user selects the search button, the request is passed via the HTTP post method to
the servlet, Controller. The following excerpt from index.jsp demonstrates how the
<table border="10">
<form name= advsearch method=post action="http://matrix.csis.pace.edu:23451/pace/servlet/Controller"
ID="form">
<tr valign=middle>
<td align=left><font face="verdana,arial,helvetica" size=-1><strong>Author:</strong></font></td>
<td align=left><input type=text name=author value="" size=40></td>
</tr>
32
text field, the name/value pair becomes author/James Gosling. If a user selects the search
button without making changes to the text fields, then the request is still sent with the
corresponding name and all values defaulting to “”. Index.jsp does not perform form
Results.jsp displays the results of an ISBN search. The page displays the details of the
specific book (i.e. author, title, cover image icon, etc.), how many vendors have been
found, and a listing of the results with vendor, price and buy-link headings. Since results
are forwarded from the Controller servlet as a session attribute in the form of a Vector
of BookBean objects, the BookBean class must be imported via a JSP page directive and
an instance of a BookBean must be created via the useBean JSP standard tag as follows:
This allows the id value, booklist, to be used like any Vector object. In order to access
each BookBean, the elementAt() method of the Vector class is utilized along with a
BookBean cast, since the method returns an Object type. The following scriptlet
Search.jsp displays the results of a non-ISBN search. The page displays how many
books have been found, the details of each book, a corresponding radio button, and a
Shop Prices button to search prices for a specified book. The page lists twenty books
per page. The Shop Prices button forwards a request to the Controller via the HTTP
33
get method. If a radio button is not selected by the user, the request is still forwarded, but
Error.jsp displays any errors, which may have occurred servicing a request. The page
accesses a session attribute in the form of a String, displays that String, invalidates the
4.2.2 Controller
The servlet, Controller, is the workhorse of the application performing numerous tasks,
which include processing all requests, forwarding requests, bean creation, and form
validation. The following excerpt from the doPost method shows how the user’s search
session.setAttribute("err", err);
object, which returns an array of Strings. Utilizing the James Gosling search example
earlier, the String is not tokenized, but placed entirely into the author array at index
zero. As for validation, if all parameters equal “”, then a user has not entered any search
criteria, resulting in the servlet setting up an error session attribute labeled “err” and
forwarding the request to the error.jsp page. Form validation also addresses the
possibility of a user entering a white space for all parameters. This results in an error as
well.
valid parameters, the Controller creates a bookList, an instance of the Vector class, to
serve as the data structure to gather all the books that surface from a search. In order to
ensure thread safety, the bookList is declared as a local variable inside the doPost
method. This guarantees that a bookList is created for each request that the servlet
receives. If bookList is declared as a global variable, then all requests would share the
same bookList.
The Controller verifies if an ISBN number has been requested. If so, the
Upon completion of the relevant method call, the Controller sorts the bookList by
35
price, establishes a bookList session attribute named “bookList”, and forwards the
request to either the results.jsp page for an ISBN search or to the search.jsp page
The searchIsbn() method accepts two parameters: the ISBN request from the user and
the bookList. Initially, the ISBN is edited in the event that a user has entered an ISBN
number with hyphens or spaces. The StringTokenizer class is utilized to break up the
ISBN into tokens or pieces, eliminate hyphens and spaces, then concatenate to ensure a
pure number sequence. From here, each vendor method is invoked accepting the newly
With the exception of the amazon() method, all vendor websites utilized by CWS are
method resorts to HTML scraping to gather book data. Each vendor possesses a specific
Uniform Resource Locator (URL) for accessing his or her book data. Each vendor
method invokes the scrape() method with their corresponding URL concatenated with
the user’s ISBN request. A connection to the URL is made using the java classes,
object, urlconnx. Then the setup parameter, setDoInput, is assigned to true since the
URL connection is being used for input. Lastly, the connection is made using a socket
36
for a network connection or a file input stream for a local connection. The response
header information is read from the server. Data is read from the connection by using the
the entire web page. In the event a connection can not be made and an exception occurs,
the exception is caught and the scrape() method returns null. This enables processing
Each vendor method utilizes the String from the scrape() method, captures the specific
price that is offered from the vendor based on a stable identifier, creates a book object of
the BookBean class, sets the price, vendor and URL link of the book via the accessor
methods of the BookBean class, and finally adds the book to the bookList.
The difficulty with the HTML scraping process is that all the URLs and stable identifiers
Additionally, if a vendor alters their respective site or URL, then existing code must be
altered to reflect such changes. HTML scraping requires a tremendous amount of upkeep
and is prone to generating numerous runtime errors. However, it does serve as a last
resort when no other alternative, data-gathering methods exist. One common strategy
that is used to reduce the amount of upkeep is to centralize all URL and stable identifier
information from each vendor into one “key” file on the server. This way when changes
Amazon.com’s Amazon Web Services (AWS 3.0). AWS, recently changed to Amazon
E-Commerce Service (ECS 4.0), allows access to numerous Amazon.com’s web sites in
accessed through either SOAP or REST requests. CWS utilizes the REST or XML over
HTTP approach via Amazon.com’s “PowerSearch” function. AWS is utilized for ISBN
searches and is the only vendor CWS utilizes for non-ISBN searches due to its
request data, and AWS returns book results in the form of an XML document (AWS
returns ten items per page, so subsequent connections are required for multiple pages).
The CWS amazon() method retrieves the XML document as a String, parses the
document utilizing the Document Object Model (DOM) from the Java APIs for XML
Processing (JAXP), creates a book of the BookBean class for Amazon books as well as
for used books being sold by the public through Amazon.com, sets numerous properties
of the book via accessor methods, and finally adds the book to the bookList.
Regarding XML processing, DOM is utilized instead of SAX or JDOM for two reasons.
First, DOM’s biggest drawback is its efficiency problems which can impact performance,
but performance is not a critical ingredient to CWS’ functionality. Moreover, the AWS
XML document is not exceptionally large and combined with the fact that CWS sets a
500 book-result threshold, loading the entire document into memory is not very resource
38
intensive. Secondly, the DOM API offers feature-rich methods, specifically the
4.2.3 Model
The BookBean class is a JavaBean component that represents a single book. Each book
possesses numerous properties, which include title, author, vendor, ISBN and price.
method. The BookBean class implements the Comparable interface to provide a price
sorting mechanism for the bookList. Sorting is initiated by the Controller using the
sort() method of the Collections class. The Comparable interface assists the sort()
method, compareTo(), which takes an Object as a parameter and returns an integer. The
compareTo() method returns zero if the object passed is equal to the current instance. It
returns a positive integer or a negative integer if the current object is greater or smaller
than the passed object. The bookList is sorted by price in ascending order.
The CWS Web Service (CWSWS) consists of the following source files:
IBookSearch is an interface that defines the two methods that are to be exposed as Web
IBookSearch interface and is derived from the Controller class of the CWS web
interface. The key difference is that CWSWS does not use the BookBean class, but
resorts to a more simplified type, the String class. Instead of constructing a bookList,
CWSWS sequentially builds an XML document consisting of the book results from each
vendor. An instance of the StringBuffer class is utilized to contain the book results.
The append() method of the StringBuffer class is called to add book information to
the buffer as they come about in the form of a String. A relevant property of a book
(vendor, title, author, ISBN, etc) is added to the buffer in XML format. The following
sb.append("<Vendor>");
sb.append("half.com");
sb.append("</Vendor>");
sb.append("<Price>");
sb.append(priceHalf);
sb.append("</Price>");
sb.append("<Link>");
sb.append(halfUrl);
sb.append("</Link>");
In the event of a successful book search, the assembled XML document within the buffer
is edited. Certain characters in XML have special meaning to XML parsers and can be
represented incorrectly in an XML document. Such characters include < , >, and &.
commonly used URL character and therefore, CWS replaces all instances of ‘&’ with
int ind=sb.indexOf("&");
while(ind != -1){
sb.replace(ind,ind+1,"&");
ind=sb.indexOf("&",ind+1);
Finally, the toString() method of the StringBuffer class is invoked to change the
entire buffer to a String and this String is returned to a client. If an unsuccessful book
4.3.1.1 Deployment
Utilizing the Apache Axis 1.1 framework, there are two ways to deploy a web service:
JWS instant deployment and WSDD custom deployment. CWS utilizes the JWS (Java
Web Service) method of deployment which simply involves changing the extension of a
java source file, BookServerImpl.java in this case, from .java to .jws and placing it into
the Axis webapps folder. CWSWS can then be accessed via the following URL:
http://matrix.csis.pace.edu:23451/axis/BookServerImpl.jws
Moreover, the WSDL for CWSWS is accessed by adding ?wsdl to the above URL:
http://matrix.csis.pace.edu:23451/axis/BookServerImpl.jws?wsdl
Axis automatically compiles the class and dynamically generates the WSDL document.
The WSDD (Web Service Deployment Descriptor) method involves static deployment of
2) creation of WSDD file, deploy.wsdd, specifying methods to be exposed and type mappings
4) generate server-side wrapper code and stubs using Axis’ WSDL2Java tool
5) modify the xxxxSoapBindingImpl file with correct return statements and objects
8) start the server and deploy service using Axis’ AdminClient tool with deploy.wsdd
The WSDD-deployed service can then be accessed via the following hypothetical URL:
http://matrix.csis.pace.edu:23451/axis/services/XXXX
The WSDD-deployed service can be undeployed using the AdminClient tool with a auto-
CWS utilizes JWS instead of the WSDD because of its simplicity, dynamic capabilities
and loosely coupled structure. The WSDD method promotes a tightly coupled structure
due to the presence of stubs and skeletons. Each time the underlying implementation
changes, new “glue” code must be generated as well. David Bau states “since automatic
WSDL and stub-generation tools work by directly generating a message shape from a
function signature (or vice versa), when you change your implementation code, it
A client has two options when invoking a JWS service. The first option is dynamic
WSDL is not directly used, but can be referenced for endpoint, namespace, and operation
42
CWSWS’ interoperability, a Java client and a .NET client (C# implementation) are
presented. Both clients implement a graphical user interface (GUI) to facilitate use.
try {
call.setTargetEndpointAddress(new java.net.URL(endPoint));
call.addParameter("isbn", XMLType.XSD_STRING,ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);
results.setText(ret);
results.setCaretPosition(0);
catch (Exception e) {
After gathering and setting the endpoint, operation, parameter type, and return type
information from the CWSWS WSDL, the service is invoked using the invoke() method
of the Call class, which takes an array of Objects as a parameter. The CWSWS XML
The .NET client, cwsForm.cs, invokes CWSWS using stub (proxy) generation:
The .NET framework provides a tool, wsdl.exe, for generating proxy classes for XML
Web Services clients from WSDL contract files. The following command generates a
The client then creates an instance of the proxy class and simply calls the desired service
method. The .NET client has no difficulty processing the String returned from the J2EE
based CWSWS.
Numerous firms or operators provide public, UDDI registries and testing registries. A
HP http://uddi.hp.com/inquire https://uddi.hp.com/publish
UDDI registries can be accessed using an operator’s web interface via a browser or
programmatically. Java developers can utilize SOAP APIs, custom Java-based UDDI
client APIs (i.e. UDDI4J and WASP UDDI), and the Java API for XML Registries
(JAXR). CWS utilizes Microsoft’s and IBM’s UDDI registry for publishing and IBM’s
CWS utilizes the web interfaces from Microsoft and IBM to register and publish CWS’
information, overview document (location of CWS’ WSDL file) and tModel data.
Further data can be entered such as business relationships and categories, which refine
the search process. The following is a screen capture of CWS’ data from the IBM
registry:
45
A CWS query can be performed using IBM’s UDDI4J project. UDDI4J is a Java class
library that provides an API that can be used to interact with a UDDI registry. The UDDI
client implementation is derived from IBM’s sample files from the UDDI4J kit and
propCWS is a properties file which centralizes all the key information needed to interact
with a UDDI registry. This information includes usernames and passwords when
publishing, the URLs for the inquiry and publish APIs of the target registry, SOAP
46
transport classes, security settings, and logging options. When a developer needs to
access a different registry, one only has to alter the settings of the properties file. This is
Configurator is responsible for reading the properties file, setting the SOAP transport,
FindCWS is the driver of the client application and performs a simple query based on
business name. FindCWS begins by enabling the Configurator to perform its duties via
the creation of a Configurator object, config, then calling the load() method of
config. Once the correct environment settings are configured, FindCWS creates a
UDDIProxy object, proxy. UDDIProxy is the central class in the UDDI4J class library
and represents a proxy for the UDDI server. Its methods map to the UDDI Version 2 API
then sets the URL for the inquiry API of the target registry, Microsoft UDDI registry in
proxy.setInquiryURL(config.getProperty("inquiryURL"));
names.add(new Name("CWS"));
Lastly, FindCWS adds a specific case sensitive qualifier to the query and calls the
find_business() method of the UDDIProxy class to initiate the query to the Microsoft
registry. Surprisingly, the client application returns two business names for CWS. This
47
is due to the fact that CWS is published with Microsoft and IBM, and the registries not
only return data from their side, but from their companions as well.
Queries are not limited to just business names, but can include business descriptions,
Each use case has been tested to verify if CWS can fulfill the specific requests for
resources. Each test case number corresponds to each use case number. Test cases 1 and
2 have been tested using Microsoft’s Internet Explorer and Mozilla’s Firefox browsers.
Test Case 1
A student is greeted with the CWS’ homepage which displays the user interface:
50
The student, shopping various prices for Steve Graham’s Building Web Services with
Java, enters the book’s correct ISBN number 0672326418:
51
After the student clicks on CWS Search, CWS successfully returns a book summary,
sorted prices, and links from numerous vendors:
52
Test Case 2
A student searching for books written by Walter Savitch with a publication year of 2004
enters the data as follows:
53
After the student clicks on CWS Search, CWS successfully returns various books based
on the student’s search parameters:
54
Regarding Test cases 1 and 3, in the event of an error, CWS displays the following:
55
Test Case 3
Launching the Java client application, CWSBookSearchClient, from the command line or
from an IDE results in the display of a user interface:
56
A user of the application, shopping various prices for Microsoft .NET XML Web Services
Step by Step written by Adam Freeman, enters the book’s correct ISBN number
0735617201:
57
After the user clicks the Search button, CWS successfully returns the following XML
document:
58
The output displays a well formed XML document. The complete XML document is as
follows:
<?xml version="1.0"?>
<Results>
<Book>
<Title>Microsoft .NET XML Web Services Step by Step</Title>
<Authors>Adam Freeman,Allen Jones,Adam Freeman</Authors>
<Publisher>Microsoft Press</Publisher>
<ISBN>0735617201</ISBN>
<RetailPrice>39.99</RetailPrice>
</Book>
<Vendor>Amazon</Vendor>
<Price>26.39</Price>
<Link>http://www.amazon.com/exec/obidos/ASIN/0735617201</Link>
<Vendor>Amazon-Used</Vendor>
<Price>16.50</Price>
<Link>http://www.amazon.com/exec/obidos/ASIN/0735617201</Link>
<Vendor>Barnes and Noble</Vendor>
<Price>31.99</Price>
<Link>http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?endeca=1&isbn=07356
17201</Link>
<Vendor>eCampus</Vendor>
<Price>27.99</Price>
<Link>http://www.ecampus.com/bk_detail.asp?ISBN=0735617201</Link>
<Vendor>Powells</Vendor>
<Price>20.80</Price>
<Link>http://www.powells.com/cgi-bin/biblio?isbn=0735617201</Link>
<Vendor>BiggerBooks</Vendor>
<Price>27.43</Price>
<Link>http://www.biggerbooks.com/bk_detail.asp?ISBN=0735617201</Link>
<Vendor>BooksAMillion</Vendor>
<Price>27.99</Price>
<Link>http://www.booksamillion.com/ncom/books?isbn=0735617201</Link>
<Vendor>AllDirect.com</Vendor>
<Price>24.79</Price>
<Link>http://www.alldirect.com/book.asp?isbn=0735617201</Link>
<Vendor>VarsityBooks</Vendor>
<Price>39.99</Price>
<Link>http://www.varsitybooks.com/Search.aspx?SearchType=ISBN&SearchValue=0735617
201</Link>
<Vendor>half.com</Vendor>
<Price>16.50</Price>
<Link>http://half.ebay.com/search/search.jsp?&product=books&keyword=0735617201<
/Link>
</Results>
59
Test Case 4
Launching the .NET client application, cwsForm.cs, from the command line or from an
IDE results in the display of a user interface:
60
A user of the application, searching for books written by M. Morris Mano with a
publication year 1992, enters the information as follows:
61
After the user clicks on the Search button, CWS successfully returns the following XML
document:
Xmethods.net is a popular Web site that offers a listing of third party web services. Only
three Web services exist which provide book search functionality. One Web service,
BNPriceWS, returns Barnes and Noble book prices based on a client ISBN number
62
request. The Xmethods listing directs one to the publisher’s Web page at
http://www.abundanttech.com/default.asp?content=WebServices/BNPrice/default.aspx.
Initially, the Web service appears to be a legitimate resource for CWS to incorporate in
disappointing:
63
If one compares BNPriceWS’ generated price to Barnes and Noble’s actual price listed
on their Web page, BNPriceWS does not provide accurate pricing. They provide the
publisher’s list price, not Barnes and Noble’s price. The screen captures above
demonstrate that the correct Barnes and Noble price is $39.99, not $49.99.
The second Web service that provides book search functions is ISBNInformation,
returns in XML format basic book information such as title, author, publisher and year of
returns in XML format title, author, publisher, publication year and price information, but
5.2.2 BookFinder4u.com
includes price alerts, currency converter, and a broad scope of bookstores. CWS fails to
match BookFinder4u in this regard. However, CWS does distinguish itself from
BookFinder4u in two areas. One, BookFinder4u does not expose its functionality as a
Web service. The only way to programmatically access this resource is via HTML
scraping. Secondly, BookFinder4u does not allow a user to enter a combination of search
parameters in their request. The following screen capture displays their search
mechanism:
BookFinder4u’s radio button structure limits a user’s search to only one criteria. CWS
enables a user to submit multiple search parameters in a single request resulting in a more
5.2.3 Chambal.com
Chambal.com is one step ahead of all book brokers by providing 13 digit ISBN search
plans to transition from the existing 10 digit ISBN structure to a 13 digit ISBN structure
[14]. The change is taking place because the supply of available 10 digit numbers is
65
exhausting. By January 1, 2007, all book and book-related products must carry 13 digit
ISBN numbers. Currently, no other book brokers offer this functionality. CWS executes
a 13 digit ISBN search request, but responses are limited to prices from Barnes and Noble
and Booksamillion. However, Chambal’s advantage is short lived once Amazon and the
other players update their systems for 13 digit ISBN compliance. Also, Chambal only
provides ISBN, title and author search functionality, reducing the effectiveness of their
search mechanism.
5.2.4 FetchBook.info
and customizable views of search results. However, they only allow keyword, title,
author and ISBN search capabilities. Additionally, if a user submits a 13 digit ISBN
request, the request is altered to a title-type request, probably due to a 10 digit form
CHAPTER 6 CONCLUSION
Certainly, CWS does not solve the interoperability problem at all levels, but has
languages. The CWS solution itself has its disadvantages and advantages. One
structure. Secondly, the burden of interpreting and parsing the XML response is placed
on the client. Thirdly, the solution breaks down the layers of abstraction in the Web
service stack and does not hide the complexities of the service, but exposes the
implementation details.
On the positive side, the solution makes full use of the XML language. Any entity
programming with XML parsing capability can utilize CWS as a resource. Also, the
solution avoids some of the current, interoperability trouble spots, which include
employing Java Collection classes and returning an array with null elements. Lastly,
the solution omits the use of creating book instances of the BookBean class to optimize
performance. By this omission, specifically the omission of the “new” keyword, this
conserves server resources, reduces memory usage, and potential garbage collection.
Overall, this optimization can increase performance between CWS and a client.
Furthermore, CWS raises a few key points. First, XML is the pivotal, underlying
language that can connect disparate systems and lead to seamless interoperability. There
must be some common ground allowing for two parties to communicate. XML provides
67
this. Secondly, the decision by WS-I through its Basic Profile 1.1 towards RPC-literal
solutions. Thirdly, the CWS solution demonstrates that complexity is not always a
required ingredient for every software solution. Security is one functionality that CWS
does not need to operate since the data being sent by the client and server is publicly
available. Fundamentally, CWS is passing XML documents over the HTTP wire.
LaMonica states that “sending XML documents over existing Internet protocols is suited
for relatively simple applications. But businesses wanting the benefits of the flexible
systems design called a services-oriented architecture should adopt Web services.” [11]
The important issue is to recognize the needs of the application and compose a solution
based on those needs. Additional levels of complexity may be unwarranted. Lastly, the
ability to aggregate various Web services into one higher-level Web service by way of
The future of Web services is difficult to forecast. Recent market research data and
trends illustrate the outlook appears promising, but a few potential pitfalls must not be
overlooked.
An October 2004 Evans Data Corp survey [15] of over 400 developers finds that 60
lower costs. Other findings specify that the top three services being developed with Web
commerce applications.
According to the Yankee Group 2004 U.S. Enterprise Web Services Survey [Yankee], 65
are being widely used, but penetration is low, and enterprises are gearing up for higher
The Radicati Group Web Services Market, 2004-2008 Survey [9] affirms that the increase
in Web service deployment is not limited to enterprises in the U.S., but all over the world
Survey results point out that the majority of Web service deployments fall within the
North American region, but are on the rise in Europe and Asia.
The W3C XML Binary Characterization Working Group is exploring the possibility of
creating a binary version of XML that is faster than the current text-based version of the
standard. “Since XML is designed to be read by both machines and humans, it results in
message sizes that can easily be 10 to 50 times larger than equivalent messages sent via
binary encodings.” [12] A client and server XML conversation might require the
document signing and encryption. Binary XML may reduce a lot of the overhead
Another potential trend Web services may experience in the future is the burial of the
Web service stack into the application integration runtimes and tooling. The trend has
actually started. “BEA, IBM, Microsoft, Oracle, and others all have Web services firmly
The following table lists additional potential Web services trends in the future:
Language (BPEL)
A few potential pitfalls that may limit the success of Web services are: semantic
sense, by utilizing XML as the key intermediary language. However, Web services can
not interpret the meaning of the actual data being sent in XML and therefore, fail to
communicate, but Web services themselves do not have an inherent understanding of the
words and grammar of XML.” [10] From a business standpoint, it would be beneficial
for a Web service to be able to distinguish between an invoice or a work order and
interpret it based on common business rules. If Web services fail to provide semantic
70
interoperability, this may result in “passing the torch” to another technology to solve the
Interfacing to existing legacy systems has been an ongoing problem. Further findings
from the October 2004 Evans Data Corp survey [15] of over 400 developers specify that
legacy system interfacing is “the biggest obstacle to web services by 20 percent of the
respondents, compared with 8 percent a year ago.” Failure to provide such a solution
may put Web services into the same camp as its distributed predecessors of the past.
Lastly, the W3C is generating numerous specifications, which include hundreds of pages
of technical guidelines. This makes it difficult for professionals to keep abreast of all the
changes taking place. “The ongoing process of specification development has caused
consternation among some people, who claim that programmers and their employers
cannot absorb the flow of new specifications.” [11]. Moreover, as enterprises and
vendors build applications now in an effort to acquire market share, if a W3C entity
suddenly prohibits a specific technology, as is the case in the Basic Profile 1.1, this can
be costly to enterprises and vendors who may have to go back to the drawing board in an
effort to be compliant. Such parties are required to make educated guesses and build
APPENDIX 1
See Whitepaper
AmberPoint Management Web service Security Monitor Web services, enforce and
Security, SAML,
XACML
Apache XML SOAP SOAP API for Java; Reference implementation of W3C
Apache XML Axis 1.0 SOAP API for Java - JAX-RPC, SAAJ compatible
Guide.
72
based on Atomikos's
TransactionsJTA product.
BEA WebLogic EJB => WSDL Weblogic 6.1 exports WSDL from a
tutorial/demos page.
MIME, XPATH,
73
CORBA
screen shot
collection
Epicentric Web Services RAD Tool, Portal Epicentric provides a RAD tool and
HP Web services RAD Tool, Web Creates and deploys Web services;
HP e-speak Web services serivces integrator, derives Web services from EJBs.
IBM Dynamic WSDK Web service WSDK (Web services Tool Kit). See
Browser.
Kao
toolkit.
Server integration.
Company changed
Idoox See SystInet
names.
intelliun Virtual Enterprise RAD Tool and Web The framework Web service
implementation on a J2EE-based
Insession WebGate SOAPTP Web service Exposes EJB as a Web service and
transactions.
overviews.
Enterprise messaging;EDI to
Integrator XML
(PDF)
77
transaction,load balancing,
Oracle XDK for Java Web service Combines a number of Oracle XML
Polar Lake Polar Lake XPath Rule engine, XML enabling desktop and server
XML Server with Web platform for J2EE that provides Web
SilverStream eXtend Workbench RAD Tool, Web J2EE Web Services Integration tool
eXtend Home
Sun Sun ONE Web services strategy Sun ONE (Open Network
services and
Web services.
Java 101.
Java 093.
Java 093.
Long Term Bean XML bean persistence Enables serialization of Java bean
implementation of JSR-057.
capable.
Systinet WASP for Java Web service Systinet publishes a series of Web
Product matrix Advanced integrator: MIME, service tools and has this product
WASP/J2EE Tutorial
PostGres.
J2EE integration.
81
WASP Developer RAD Tools for J2EE Distributed with WASP Lite. Works
Talking Talking Blocks 2.0 Web service contract Provides contract management of
load balancing.
Versata Versata for Web BPM, Logic Exposes simple Web services;
Velocigen VelocigenX Web service integrator Web Services- EJB Wrapper, and
Velocigen VelocigenX Web service integrator Web Services- EJB Wrapper and
WebMethods B2BI
reference WSDL
implementation
Borland BizSnap Web service integrator: See Kylix news and datasheet (PDF).
Web services
Microsoft .Net, .Net Overall Web service Microsoft's new overall software
Roger Wolter
Mirus NetHesive Web service integrator: Provides Web services (as Apache Web
Phalanxsys WSDL COM => WSDL Provides Web services capabilities for
83
products.
Python RPC
Python Web SOAPpy and Web service integrator: Web services for Python. Capabilities
Soap Infrastructure
SoapLite Soap::Lite Web service messaging: Also provides non-blocking TCP, COM
for Perl MQ, Jabber, RPC HTTPS. interface. Supports SMTP, POP3 for
eMail.
integrator: Mac OS X,
Win32, RPC
APPENDIX 2
Index.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<html>
<head><title>CWS.com Book Search</title></head>
<body bgcolor="#BDB76B">
<center>
<img src= "http://matrix.csis.pace.edu:23451/pace/logo.GIF" alt="CWS.com">
<p>
<table width="80%" border="0" cellspacing="0" cellpadding="5">
<tr>
<td align=center>
<a href = "http://matrix.csis.pace.edu:23451/pace/aboutus.jsp" >
<img src = "http://matrix.csis.pace.edu:23451/pace/about.GIF" name=aboutus
alt="About Us"</a>
</td>
<td align=center>
<a href = "mailto:mr13204w@pace.edu" </a>
<img src = "http://matrix.csis.pace.edu:23451/pace/contact.GIF" name=contact
alt="Contact Us"</a>
</td>
<td align=center>
<a href = "http://matrix.csis.pace.edu:23451/pace/index.jsp" >
<img src = "http://matrix.csis.pace.edu:23451/pace/home.GIF" name=home alt =
"Home"</a>
</td>
</tr>
</table>
<h3><i>CWS.com is the ideal place to shop for the best book prices from various
bookstores
around the world</i></h3>
<p>
<p>
<table border="10">
<form name= advsearch method=post
action="http://matrix.csis.pace.edu:23451/pace/servlet/Controller" ID="form">
<tr valign=middle>
<td align=left><font face="verdana,arial,helvetica" size=-
1><strong>Author:</strong></font></td>
<td align=left><input type=text name=author value="" size=40></td>
</tr>
<tr valign=middle>
<td align=left><font face="verdana,arial,helvetica" size=-
1><strong>Title:</strong></font></td>
<td align=left><input type=text name=title value="" size=40></td>
</tr>
<tr valign=middle>
<td align=left><font face="verdana,arial,helvetica" size=-
1><strong>Publisher:</strong></font></td>
<td align=left><input type=text name=publisher value="" size=40></td>
</tr>
85
<tr valign=middle>
<td align=left><font face="verdana,arial,helvetica" size=-1><strong>Publish
Year: </strong></font></td>
<td align=left><input type=text name=year value="" size=40></td>
</tr>
<tr valign=middle>
<td align=left><font face="verdana,arial,helvetica" size=-
1><strong>Subject:</strong></font></td>
<td align=left><input type=text name=subject value="" size=40></td>
</tr>
<tr valign=middle>
<td align=left><font face="verdana,arial,helvetica" size=-
1><strong>Keyword:</strong></font></td>
<td align=left><input type=text name=keyword value_u34 ?" size=40></td>
</tr>
<tr valign=middle>
<td align=left><font face="verdana,arial,helvetica" size=-
1><strong>ISBN:</strong></font></td>
<td align=left><input type=text name=isbn value="" size=40></td>
</tr>
<tr valign=middle>
<td> </td>
<td> <input type=submit value="CWS Search" >
<input type =reset value="Clear" ></td>
</tr>
</form>
</table>
<p>
APPENDIX 3
Results.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@page import="java.util.*, java.text.*, CWS.BookBean" %>
<jsp:useBean id="bookList" class="java.util.Vector" scope="session"/>
<jsp:useBean id="decoy" class="java.util.Vector" scope="session"/>
<html>
<head><title>CWS.com Book Search</title></head>
<body bgcolor="#BDB76B">
<center>
<img src="http://matrix.csis.pace.edu:23451/pace/logo.GIF" alt="CWS.com">
<p>
<table width="80%" border="0" cellspacing="0" cellpadding="5">
<tr>
<td align=center>
<a href = "http://matrix.csis.pace.edu:23451/pace/aboutus.jsp">
<img src = "http://matrix.csis.pace.edu:23451/pace/about.GIF" name=aboutus
alt="About Us"</a>
</td>
<td align=center>
<a href = "mailto:mr13204w@pace.edu" </a>
<img src = "http://matrix.csis.pace.edu:23451/pace/contact.GIF" name=contact
alt="Contact Us"</a>
</td>
<td align=center>
<a href = "http://matrix.csis.pace.edu:23451/pace/index.jsp" >
<img src = "http://matrix.csis.pace.edu:23451/pace/home.GIF" name=home alt =
"Home"</a>
</td>
</tr>
</table>
<h3><i>CWS.com is the ideal place to shop for the best book prices from various
bookstores
around the world</i></h3>
<p>
<p>
<a href="http://matrix.csis.pace.edu:23451/pace/index.jsp"> Click Here for New
Search</a>
<h3 align=center>The results of your search are:</h3>
<p>
<p>
<%
if (!bookList.isEmpty()){
DecimalFormat decFor = new DecimalFormat("#0.00");
decFor.setMaximumFractionDigits(2);%>
<center>
<table border="10" bgcolor="#ffff99">
<tr> <td rowspan="20"><img src="<%= ((BookBean)
decoy.elementAt(0)).getCover()%>"></td></tr>
<tr> <td><b><font face="Verdana"><%= ((BookBean)
decoy.elementAt(0)).getTitle()%></font></b></td></tr>
<tr> <td><b><font face="Verdana">Author(s):  <%= ((BookBean)
decoy.elementAt(0)).getAuthor()%></font></b></td></tr>
<tr> <td><b><font face="Verdana">Publisher:  <%= ((BookBean)
decoy.elementAt(0)).getPublisher()%></font></b></td></tr>
87
<% }
else out.println("Sorry, your book search was unsuccessful. Please try
again."); %>
<% bookList.removeAllElements();
session.invalidate();
decoy.removeAllElements();%>
<a href="http://matrix.csis.pace.edu:23451/pace/index.jsp"> Click Here for New
Search</a>
<hr>
<p>
<h6 align=center>Copyright © 2005 CWS.com. All rights reserved.</h6></center>
</body>
</html>
88
APPENDIX 4
Controller.java
import java.io.*;
import java.util.*; //for Vector
import java.net.*; //for URL,URLConnection
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import CWS.BookBean;
if( !(isbn[0].equals("")) ){
onlyISBN = true;
searchIsbn(isbn,bookList);
if ( (!(bookList.isEmpty()) ) ){
decoy.add(0,bookList.elementAt(0));
89
session.setAttribute("decoy", decoy);
}
}
else{
if(!(author[0].equals("")) ) temp = temp + "author:" +
normalize(author);
if(!(title[0].equals("")) && !(author[0].equals("")) ) temp = temp +
"%20title:" + normalize(title);
else if (!(title[0].equals(""))) temp = temp + "title:" +
normalize(title);
else;
if(!(publisher[0].equals("")) && (!(title[0].equals("")) ||
!(author[0].equals("") )) )
temp = temp + "%20publisher:" + normalize(publisher);
else if(!(publisher[0].equals(""))) temp = temp + "publisher:" +
normalize(publisher);
else;
if(!(year[0].equals("")) && (!(publisher[0].equals("")) ||
!(title[0].equals("")) ||
!(author[0].equals("") ) ))
temp = temp + "%20pubdate:" + normalize(year);
else if (!(year[0].equals(""))) temp = temp + "pubdate:" +
normalize(year);
else;
if(!(subject[0].equals("")) && (!(year[0].equals("")) ||
!(publisher[0].equals("")) ||
!(title[0].equals("")) || !(author[0].equals("") )) )
temp = temp + "%20subject:" + normalize(subject);
else if (!(subject[0].equals(""))) temp = temp + "subject:" +
normalize(subject);
else;
if(!(keyword[0].equals("")) && (!(subject[0].equals("")) ||
!(year[0].equals("")) ||
!(publisher[0].equals("")) || !(title[0].equals("")) ||
!(author[0].equals("") ) ))
temp = temp + "%20keywords:" + normalize(keyword);
else if (!(keyword[0].equals(""))) temp = temp + "keywords:" +
normalize(keyword);
else;
amazon(temp, "Other", bookList);
if(onlyISBN){
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher("/results.jsp");
dispatcher.forward(request,response);
}
else{
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher("/search.jsp");
dispatcher.forward(request,response);
}
searchIsbn(searchTextGet,bookList);
if( (!(bookList.isEmpty() ))){
Vector decoy = new Vector();
decoy.add(0,bookList.elementAt(0));
session.setAttribute("decoy", decoy);
}
if( (!(bookList.isEmpty() ))) Collections.sort(bookList);
session.setAttribute("bookList", bookList);
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher("/results.jsp");
dispatcher.forward(request,response);
}
}
amazon(x,"ISBN",bookList);
barnes(isbn,bookList);
ecampus(isbn,bookList);
powells(isbn,bookList);
biggerBooks(isbn,bookList);
booksMillion(isbn,bookList);
blackwell(isbn,bookList);
allDirect(isbn,bookList);
deals(isbn,bookList);
varsity(isbn,bookList);
half(isbn,bookList);
if(format.equals("ISBN")){
NodeList productName = doc.getElementsByTagName("ProductName");
NodeList imageMed = doc.getElementsByTagName("ImageUrlMedium");
NodeList imageSmall = doc.getElementsByTagName("ImageUrlSmall");
NodeList ourPrice = doc.getElementsByTagName("OurPrice");
NodeList usedPrice = doc.getElementsByTagName("UsedPrice");
NodeList retailPrice = doc.getElementsByTagName("ListPrice");
NodeList publisher = doc.getElementsByTagName("Manufacturer");
NodeList author = doc.getElementsByTagName("Author");
NodeList isbnq = doc.getElementsByTagName("Asin");
// in case of multiple authors
StringBuffer sb = new StringBuffer();
for (int i = 0; i < author.getLength(); i++) {
if (i != 0)
sb.append(',');
sb.append(author.item(i).getFirstChild().getNodeValue());
}
if(ourPrice.getLength()!=0){
BookBean book = new BookBean();
book.setVendor("Amazon");
if(productName.getLength()>0) book.setTitle(
productName.item(0).getFirstChild().getNodeValue());
if(imageMed.getLength()>0) book.setCover(
imageMed.item(0).getFirstChild().getNodeValue());
if(imageSmall.getLength()>0)
book.setCoverSmall(imageSmall.item(0).getFirstChild().getNodeValue());
tempPrice = ourPrice.item(0).getFirstChild().getNodeValue();
tempPrice = tempPrice.substring(1);
book.setPrice(Double.parseDouble(tempPrice));
if(retailPrice.getLength()>0){
tempRetail = retailPrice.item(0).getFirstChild().getNodeValue();
92
tempRetail = tempRetail.substring(1);
book.setRetail(Double.parseDouble(tempRetail));
}if(publisher.getLength()>0) book.setPublisher(
publisher.item(0).getFirstChild().getNodeValue() );
book.setAuthor(sb.toString());
if(isbnq.getLength()>0) book.setIsbn(
isbnq.item(0).getFirstChild().getNodeValue() );
book.setBuyLink("http://www.amazon.com/exec/obidos/ASIN/"+
book.getIsbn());
bookList.addElement(book);
}// end inner if
if(usedPrice.getLength()!=0){
BookBean book = new BookBean();
book.setVendor("Amazon-Used");
if(productName.getLength()>0) book.setTitle(
productName.item(0).getFirstChild().getNodeValue() );
if(imageMed.getLength()>0) book.setCover(
imageMed.item(0).getFirstChild().getNodeValue() );
if(imageSmall.getLength()>0)
book.setCoverSmall(imageSmall.item(0).getFirstChild().getNodeValue() );
tempPrice = usedPrice.item(0).getFirstChild().getNodeValue();
tempPrice = tempPrice.substring(1);
book.setPrice(Double.parseDouble(tempPrice));
if(retailPrice.getLength()>0){
tempRetail = retailPrice.item(0).getFirstChild().getNodeValue();
tempRetail = tempRetail.substring(1);
book.setRetail(Double.parseDouble(tempRetail));
}
if(publisher.getLength()>0) book.setPublisher(
publisher.item(0).getFirstChild().getNodeValue() );
book.setAuthor(sb.toString());
if(isbnq.getLength()>0) book.setIsbn(
isbnq.item(0).getFirstChild().getNodeValue() );
book.setBuyLink("http://www.amazon.com/exec/obidos/ASIN/"+
book.getIsbn());
bookList.addElement(book);
} // end inner if
} // end outer if
else{
NodeList totalPages = doc.getElementsByTagName("TotalPages");
NodeList productName = doc.getElementsByTagName("ProductName");
NodeList imageSmall = doc.getElementsByTagName("ImageUrlSmall");
NodeList publisher = doc.getElementsByTagName("Manufacturer");
NodeList year = doc.getElementsByTagName("ReleaseDate");
NodeList isbnq = doc.getElementsByTagName("Asin");
NodeList authors = doc.getElementsByTagName("Authors");
int pages =
Integer.parseInt(totalPages.item(0).getFirstChild().getNodeValue());
if (pages > 50) pages = 50;
int pagesLeft = pages - 1;
for(int z = 0; z < productName.getLength(); z++){
BookBean book = new BookBean();
if(productName.item(z) != null) book.setTitle(
productName.item(z).getFirstChild().getNodeValue());
if(imageSmall.item(z) != null)
book.setCoverSmall(imageSmall.item(z).getFirstChild().getNodeValue());
if(publisher.item(z) != null) book.setPublisher(
publisher.item(z).getFirstChild().getNodeValue() );
else book.setPublisher(
"Unavailable");
if(year.item(z) != null) book.setYear(
year.item(z).getFirstChild().getNodeValue() );
93
//get price
BookBean book = new BookBean();
start = inputBig.indexOf("$",bigPivotStartPrice);
end = inputBig.indexOf("</span>",start);
priceBig = inputBig.substring(start+1,end);
book.setPrice(Double.parseDouble(priceBig));
book.setVendor("BiggerBooks");
book.setBuyLink(bigUrl);
bookList.addElement(book);
} // end else
} // end else
book.setVendor("VarsityBooks");
book.setBuyLink(varUrl);
bookList.addElement(book);
} // end else
}
private String getCharacterDataFromElement(Element e) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
return "Unknown";
}
private String normalize(String []norm){
String ttt = "";
StringTokenizer t = new StringTokenizer(norm[0]," ");
while(t.hasMoreTokens()){
ttt = ttt + t.nextToken() + "%20";
99
}
int last = ttt.lastIndexOf("%20");
ttt = ttt.substring(0, last);
return ttt;
}
APPENDIX 5
BookBean.java
package CWS;
public class BookBean implements Comparable {
private String vendor;
private double price;
private String buyLink;
private String title;
private String cover;
private String coverSmall;
private double retail;
private String publisher;
private String year;
private String author;
private String isbn;
}
public void setCoverSmall(String strcs) {
coverSmall=strcs;
}
public String getCoverSmall() {
return coverSmall;
}
public void setRetail(double strr) {
retail=strr;
}
public double getRetail() {
return retail;
}
public void setPublisher(String strpp) {
publisher=strpp;
}
public String getPublisher() {
return publisher;
}
public void setYear(String stry) {
year=stry;
}
public String getYear() {
return year;
}
public void setAuthor(String stra) {
author=stra;
}
public String getAuthor() {
return author;
}
public void setIsbn(String stri) {
isbn=stri;
}
public String getIsbn() {
return isbn;
}
public int compareTo(Object otherObject) throws ClassCastException {
if (!(otherObject instanceof BookBean))
throw new ClassCastException("A BookBean object is expected.");
BookBean anotherBook = (BookBean)otherObject;
if(price < anotherBook.price) return -1;
if(price > anotherBook.price) return 1;
return 0;
}
}
102
APPENDIX 6
Error.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<html>
<head><title>CWS.com Book Search</title></head>
<body bgcolor="#BDB76B">
<center>
<img src= "http://matrix.csis.pace.edu:23451/pace/logo.GIF" alt="CWS.com">
<p>
<table width="80%" border="0" cellspacing="0" cellpadding="5">
<tr>
<td align=center>
<a href = "http://matrix.csis.pace.edu:23451/pace/aboutus.jsp" >
<img src = "http://matrix.csis.pace.edu:23451/pace/about.GIF" name=aboutus
alt="About Us"</a>
</td>
<td align=center>
<a href = "mailto:mr13204w@pace.edu" </a>
<img src = "http://matrix.csis.pace.edu:23451/pace/contact.GIF" name=contact
alt="Contact Us"</a>
</td>
<td align=center>
<a href = "http://matrix.csis.pace.edu:23451/pace/index.jsp" >
<img src = "http://matrix.csis.pace.edu:23451/pace/home.GIF" name=home alt =
"Home"</a>
</td>
</tr>
</table>
<p>
<p>
<h2 align=center>
<% String err = (String)session.getAttribute("err");
out.println(err);
session.invalidate();%><br>
<a href="http://matrix.csis.pace.edu:23451/pace/index.jsp">Click here to search
again.</a>
</h2>
</body>
</html>
103
APPENDIX 7
Search.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@page import="java.util.*, CWS.BookBean" %>
<jsp:useBean id="bookList" class="java.util.Vector" scope="session"/>
<html>
<head><title>CWS.com Book Search</title></head>
<body bgcolor="#BDB76B">
<center>
<img src= "http://matrix.csis.pace.edu:23451/pace/logo.GIF" alt="CWS.com">
<p>
<table width="80%" border="0" cellspacing="0" cellpadding="5">
<tr>
<td align=center>
<a href = "http://matrix.csis.pace.edu:23451/pace/aboutus.jsp" >
<img src = "http://matrix.csis.pace.edu:23451/pace/about.GIF" name=aboutus
alt="About Us"</a>
</td>
<td align=center>
<a href = "mailto:mr13204w@pace.edu" </a>
<img src = "http://matrix.csis.pace.edu:23451/pace/contact.GIF" name=contact
alt="Contact Us"</a>
</td>
<td align=center>
<a href = "http://matrix.csis.pace.edu:23451/pace/index.jsp" >
<img src = "http://matrix.csis.pace.edu:23451/pace/home.GIF" name=home alt =
"Home"</a>
</td>
</tr>
</table>
<hr>
<h3><i>CWS.com is the ideal place to shop for the best book prices from various
bookstores
around the world</i></h3>
<hr>
<hr>
<p>
<% if (!bookList.isEmpty()){
int display = 20;
int start = 0;
String begin = request.getParameter("start");
try {start = Integer.parseInt(begin);} catch (Exception ex) {}
int end = start + display;%>
<a href="http://matrix.csis.pace.edu:23451/pace/index.jsp"> Click Here for New
Search</a>
<center>
<h3 align=center><font color="#990000"> CWS search found <%= bookList.size()%>
book(s):</h3>
<p>
<table align="center" border="0" cellpadding="0" width="100%"
bgcolor="#ffff99">
<form name=shop
action="http://matrix.csis.pace.edu:23451/pace/servlet/Controller" id="formx"
method=get>
<% if (end > bookList.size() ){ %>
<tr><td><font color="#990000">Results <%= start+1 %>-<%= bookList.size()
%></font></td></tr>
104
<% }
}
else { %>
<tr><td><font color="#990000">Results <%= start+1 %>-<%= end-1
%></font></td></tr>
<% for (int index=start; index < end; index++) { %>
<tr><td align=left><hr><img src="<%= ((BookBean)
bookList.elementAt(index)).getCoverSmall()%>"></td></tr>
<tr><td align=left><%= ((BookBean) bookList.elementAt(index)).getTitle()
%></td></tr>
<tr><td align=left>Author(s):  <%= ((BookBean)
bookList.elementAt(index)).getAuthor() %></td></tr>
<tr><td align=left>Publisher:  <%= ((BookBean)
bookList.elementAt(index)).getPublisher() %></td></tr>
<tr><td align=left>ISBN:  <%= ((BookBean)
bookList.elementAt(index)).getIsbn() %></td></tr>
<% if(bookList.size() == 1) { %>
<tr><td align=left><input type="radio" name=textboxget value="<%= ((BookBean)
bookList.elementAt(index)).getIsbn()%>">
<%} else { %>
<tr><td align=left><input type="radio" name=textboxget value="<%= ((BookBean)
bookList.elementAt(index)).getIsbn()%>">
<% } %>
<input type="submit" value="Shop Prices!"></td></tr>
<% } %>
<table align="center">
<a href="<%= request.getRequestURI() %>?start=<%= end %>">Next <%= display %>
results</a>
</table>
<% } %>
</form>
</table>
<% }
else out.println("Sorry, your book search was unsuccessful. Please try
again."); %>
<br>
<hr>
<p>
<a href="http://matrix.csis.pace.edu:23451/pace/index.jsp"> Click Here for New
Search</a>
</body>
</html>
105
APPENDIX 8
CWS.wsdl
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://DefaultNamespace" use="encoded"/>
</wsdl:input>
<wsdl:output name="searchAllResponse">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://matrix.csis.pace.edu:23451/axis/BookServerImpl.jws" use="encoded"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="BookServerImplService">
<wsdl:port binding="impl:BookServerImplSoapBinding" name="BookServerImpl">
<wsdlsoap:address location="http://matrix.csis.pace.edu:23451/axis/BookServerImpl.jws"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
107
APPENDIX 9
Aboutus.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<html>
<head><title>CWS.com Book Search</title></head>
<body bgcolor="#BDB76B">
<center>
<img src= "http://matrix.csis.pace.edu:23451/pace/logo.GIF" alt="CWS.com">
<p>
<table width="80%" border="0" cellspacing="0" cellpadding="5">
<tr>
<td align=center>
<a href = "http://matrix.csis.pace.edu:23451/pace/aboutus.jsp" >
<img src = "http://matrix.csis.pace.edu:23451/pace/about.GIF" name=aboutus
alt="About Us"</a>
</td>
<td align=center>
<a href = "mailto:mr13204w@pace.edu" </a>
<img src = "http://matrix.csis.pace.edu:23451/pace/contact.GIF" name=contact
alt="Contact Us"</a>
</td>
<td align=center>
<a href = "http://matrix.csis.pace.edu:23451/pace/index.jsp" >
<img src = "http://matrix.csis.pace.edu:23451/pace/home.GIF" name=home alt =
"Home"</a>
</td>
</tr>
</table>
<p>
<h1>About our Firm</h1>
<p align=left>
CWS.com, a small firm headquarterd in New York City, has been in
business for over 20 years. We specialize in providing Web Service tools for
consumers
all over the world. These tools range from public interfaces to application-
to-application functionality.
CWS.com provides one stop shopping from numerous vendors which include Amazon,
Ebay and Barnes and Noble.
<br>
<br>
Michael Ryan CEO
</body>
</html>
108
APPENDIX 10
BookServerImpl.jws
import java.io.*;
import java.util.*; //for Vector
import java.net.*; //for URL,URLConnection
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
sb.append("</Results>");
}catch (IOException io){}
if(sb.length() == 0){
sb = null;
sb.append("<?xml version=\"1.0\"?><Results><Books>No books found </Books>
</Results>");
return sb.toString();
}
else{
int ind=sb.indexOf("&");
while(ind != -1){
sb.replace(ind,ind+1,"&");
ind=sb.indexOf("&",ind+1);
}
return sb.toString();
}
} // end searchIsbn method
else{
String temp = "&PowerSearch=";
if(!(author.equals("")) ) temp = temp + "author:" + normalize(author);
if(!(title.equals("")) && !(author.equals("")) ) temp = temp +
"%20title:" + normalize(title);
else if (!(title.equals(""))) temp = temp+"title:"+
normalize (title);
else;
if(!(publisher.equals("")) && (!(title.equals("")) ||
!(author.equals("") )) )
temp = temp + "%20publisher:" + normalize(publisher);
else if(!(publisher.equals(""))) temp = temp + "publisher:" +
normalize(publisher);
else;
if(!(year.equals("")) && (!(publisher.equals("")) ||
!(title.equals("")) ||
!(author.equals("") ) ))
temp = temp + "%20pubdate:" + normalize(year);
else if (!(year.equals(""))) temp = temp + "pubdate:" +
normalize(year);
else;
if(!(subject.equals("")) && (!(year.equals("")) ||
!(publisher.equals("")) ||
!(title.equals("")) || !(author.equals("") )) )
temp = temp + "%20subject:" + normalize(subject);
else if (!(subject.equals(""))) temp = temp + "subject:" +
normalize(subject);
else;
if(!(keyword.equals("")) && (!(subject.equals("")) ||
!(year.equals("")) ||
!(publisher.equals("")) || !(title.equals("")) ||
!(author.equals("") ) ))
temp = temp + "%20keywords:" + normalize(keyword);
else if (!(keyword.equals(""))) temp = temp + "keywords:" +
normalize(keyword);
else;
if(sb.length() == 0){
sb.append("<?xml version=\"1.0\"?><Results><Books>No books
found</Books></Results>");
return sb.toString();
}
else{
int ind=sb.indexOf("&");
while(ind != -1){
sb.replace(ind,ind+1,"&");
ind=sb.indexOf("&",ind+1);
}
return sb.toString();
if(format.equals("ISBN")){
NodeList productName = doc.getElementsByTagName("ProductName");
NodeList imageMed = doc.getElementsByTagName("ImageUrlMedium");
NodeList imageSmall = doc.getElementsByTagName("ImageUrlSmall");
NodeList ourPrice = doc.getElementsByTagName("OurPrice");
NodeList usedPrice = doc.getElementsByTagName("UsedPrice");
NodeList retailPrice = doc.getElementsByTagName("ListPrice");
NodeList publisher = doc.getElementsByTagName("Manufacturer");
NodeList author = doc.getElementsByTagName("Author");
NodeList isbnq = doc.getElementsByTagName("Asin");
// in case of multiple authors
StringBuffer sa = new StringBuffer();
for (int i = 0; i < author.getLength(); i++) {
if (i != 0)
sa.append(',');
sa.append(author.item(i).getFirstChild().getNodeValue());
}
sb.append("<Book>");
if(productName.getLength()>0){
sb.append("<Title>");
sb.append(productName.item(0).getFirstChild().getNodeValue());
sb.append("</Title>");
sb.append("<Authors>");
sb.append(sa.toString());
sb.append("</Authors>");
}
111
if(publisher.getLength()>0){
sb.append("<Publisher>");
sb.append(publisher.item(0).getFirstChild().getNodeValue() );
sb.append("</Publisher>");
}
if(isbnq.getLength()>0){
sb.append("<ISBN>");
sb.append( isbnq.item(0).getFirstChild().getNodeValue() );
sb.append("</ISBN>");
}
if(retailPrice.getLength()>0){
sb.append("<RetailPrice>");
tempRetail = retailPrice.item(0).getFirstChild().getNodeValue();
tempRetail = tempRetail.substring(1);
sb.append(tempRetail);
sb.append("</RetailPrice>");
}
sb.append("</Book>");
if(ourPrice.getLength()!=0){
sb.append("<Vendor>Amazon</Vendor>");
tempPrice = ourPrice.item(0).getFirstChild().getNodeValue();
tempPrice = tempPrice.substring(1);
sb.append("<Price>");
sb.append(tempPrice);
sb.append("</Price>");
sb.append("<Link>");
sb.append("http://www.amazon.com/exec/obidos/ASIN/" +
isbnq.item(0).getFirstChild().getNodeValue());
sb.append("</Link>");
} // end inner if
if(usedPrice.getLength()!=0){
sb.append("<Vendor>Amazon-Used</Vendor>");
tempPrice = usedPrice.item(0).getFirstChild().getNodeValue();
tempPrice = tempPrice.substring(1);
sb.append("<Price>");
sb.append(tempPrice);
sb.append("</Price>");
sb.append("<Link>");
sb.append("http://www.amazon.com/exec/obidos/ASIN/"+
isbnq.item(0).getFirstChild().getNodeValue() );
sb.append("</Link>");
} // end inner if
} // outer if
else{
NodeList totalPages = doc.getElementsByTagName("TotalPages");
NodeList productName = doc.getElementsByTagName("ProductName");
NodeList imageSmall = doc.getElementsByTagName("ImageUrlSmall");
NodeList publisher = doc.getElementsByTagName("Manufacturer");
NodeList isbnq = doc.getElementsByTagName("Asin");
NodeList authors = doc.getElementsByTagName("Authors");
NodeList year = doc.getElementsByTagName("ReleaseDate");
NodeList error2 = doc.getElementsByTagName("ErrorMsg");
if(error2.item(0) != null){
if( error2.item(0).getFirstChild().getNodeValue().equals("There are
no exact matches for the search."))
return;
}
int pages =
Integer.parseInt(totalPages.item(0).getFirstChild().getNodeValue());
112
sb.append("<ISBN>");
if(isbnq.item(z) != null){
sb.append(isbnq.item(z).getFirstChild().getNodeValue());
}
else
sb.append("NA");
sb.append("</ISBN>");
sb.append("</Book>");
} // end for loop
DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder =
docBuilderFact.newDocumentBuilder();
doc = docBuilder.parse(in);
}
catch(SAXException saxEx){}
catch (ParserConfigurationException pc) {}
totalPages = doc.getElementsByTagName("TotalPages");
productName = doc.getElementsByTagName("ProductName");
imageSmall = doc.getElementsByTagName("ImageUrlSmall");
publisher = doc.getElementsByTagName("Manufacturer");
isbnq = doc.getElementsByTagName("Asin");
authors = doc.getElementsByTagName("Authors");
year = doc.getElementsByTagName("ReleaseDate");
sb.append("<ISBN>");
if(isbnq.item(z) != null){
sb.append(isbnq.item(z).getFirstChild().getNodeValue());
}
else
sb.append("NA");
sb.append("</ISBN>");
sb.append("</Book>");
} // end for loop
114
sb.append("http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?endeca=1
&isbn="+ key);
sb.append("</Link>");
}
if(bnPivotStartUsed > -1 && bnPivotStartUsed != bnPivotStartNew){
sb.append("<Vendor>");
sb.append("Barnes & Noble-Used");
sb.append("</Vendor>");
//get barnes used price
start = inputBn.indexOf("$",bnPivotStartUsed);
end = inputBn.indexOf("</SPAN>",bnPivotStartUsed);
priceUsed = inputBn.substring(start+1,end);
sb.append("<Price>");
sb.append(priceUsed);
sb.append("</Price>");
sb.append("<Link>");
sb.append("http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?endeca=1
&isbn="+ key);
sb.append("</Link>");
} // inner if
} // end else
} // end barnes method
private void ecampus(String key, StringBuffer sb) throws IOException{
String ecUrl = "http://www.ecampus.com/bk_detail.asp?ISBN="+key;
String inputEc = scrape(ecUrl);
if(inputEc.equals(null))return;
String ecPivot = "Our Price";
String priceEc = null;
115
} // end else
} // end ecampus method
private void powells(String key, StringBuffer sb) throws IOException{
String powUrl = "http://www.powells.com/cgi-bin/biblio?isbn="+key;
String inputPow = scrape(powUrl);
if(inputPow.equals(null))return;
String powPivot = "<FONT FACE=\"Verdana, Helvetica, Arial, sans-serif\"
COLOR=\"#990000\" SIZE=\"3\">";
String pricePow = null;
int start,end,powPivotStart = 0;
powPivotStart = inputPow.indexOf(powPivot);
if( powPivotStart == -1);
else{
//get price
sb.append("<Vendor>");
sb.append("Powells");
sb.append("</Vendor>");
start = inputPow.indexOf("$",powPivotStart);
end = inputPow.indexOf("<",start);
pricePow = inputPow.substring(start+1,end);
sb.append("<Price>");
sb.append(pricePow);
sb.append("</Price>");
sb.append("<Link>");
sb.append(powUrl);
sb.append("</Link>");
} // end else
else{
//get price
sb.append("<Vendor>");
sb.append("BiggerBooks");
sb.append("</Vendor>");
start = inputBig.indexOf("$",bigPivotStartPrice);
end = inputBig.indexOf("</span>",start);
priceBig = inputBig.substring(start+1,end);
sb.append("<Price>");
sb.append(priceBig);
sb.append("</Price>");
sb.append("<Link>");
sb.append(bigUrl);
sb.append("</Link>");
} // end else
} // end else
priceBlack = inputBlack.substring(start+1,end);
sb.append("<Price>");
sb.append(priceBlack);
sb.append("</Price>");
sb.append("<Link>");
sb.append(blackUrl);
sb.append("</Link>");
} // end else
} // end else
} // end else
118
} // end else
} // end else
}
private String getCharacterDataFromElement(Element e) {
Node child = e.getFirstChild();
if (child instanceof org.w3c.dom.CharacterData) {
org.w3c.dom.CharacterData cd = (org.w3c.dom.CharacterData) child;
return cd.getData();
}
return "Unknown";
}
private String normalize(String norm){
String ttt = "";
StringTokenizer t = new StringTokenizer(norm," ");
while(t.hasMoreTokens()){
ttt = ttt + t.nextToken() + "%20";
}
int last = ttt.lastIndexOf("%20");
ttt = ttt.substring(0, last);
return ttt;
}
APPENDIX 11
IBookSearch.java
}
121
APPENDIX 12
CWSBookSearchClient.java
package cwsclient;
import java.util.*;
import java.text.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import java.net.URL;
public CWSBookSearchClient() {
setTitle(TITLE);
setSize(WIDTH, HEIGHT);
contentPane = getContentPane();
paneldetails = new JPanel();
contentPane.add(paneldetails, BorderLayout.CENTER);
paneldetails.setBorder(BorderFactory.createEtchedBorder());
box.add(box1);
// "Search" button
searchButton = new JButton("Search");
box8.add(searchButton);
searchButton.addActionListener(new
ActionListener() {
public void actionPerformed(ActionEvent evt) {
author = authorText.getText();
title = titleText.getText();
publisher = publisherText.getText();
year = yearText.getText();
subject = subjectText.getText();
keyword = keywordText.getText();
isbn = isbnText.getText();
123
if ( !isbn.equals("") ){
searchIsbn(isbn);
}
else if(!author.equals("") ||!title.equals("") ||!publisher.equals("")||
!year.equals("") || !subject.equals("") || !keyword.equals("")){
searchAll(author, title, publisher, year, subject, keyword);
}
else results.setText("Select at least one search criteria");
}
});
Box box9 = Box.createHorizontalBox();
box9.setAlignmentX(Component.LEFT_ALIGNMENT);
box9.add(new JLabel("Search Results: "));
results = new JTextArea("",20,40);
results.setBorder(BorderFactory.createEtchedBorder());
box9.add(results);
box9.add(new JScrollPane(results));
box.add(box9);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
show();
} // end constructor
}
catch (Exception e) {results.setText("Unable to process searchIsbn request at
this time. Please try again.");}
} // end searchIsbn method
params[2] = publisher;
params[3] = year;
params[4] = subject;
params[5] = keyword;
ret = (String)call.invoke(params);
results.setText(ret);
results.setCaretPosition(0);
}
catch (Exception e) {
results.setText("Unable to process searchAll request at this time. Please
try again.");
e.printStackTrace(); }
}
APPENDIX 13
cwsForm.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace Search
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class cwsForm : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox authorx;
private System.Windows.Forms.TextBox titlex;
private System.Windows.Forms.TextBox publisherx;
private System.Windows.Forms.TextBox yearx;
private System.Windows.Forms.TextBox subjectx;
private System.Windows.Forms.TextBox keywordx;
private System.Windows.Forms.TextBox isbnx;
private System.Windows.Forms.RichTextBox display;
private System.ComponentModel.Container components = null;
public cwsForm()
{
InitializeComponent();
this.label7.Name = "label7";
this.label7.TabIndex = 6;
this.label7.Text = "ISBN:";
//
// author
//
this.authorx.Location = new System.Drawing.Point(200, 32);
this.authorx.Name = "author";
this.authorx.Size = new System.Drawing.Size(152, 20);
this.authorx.TabIndex = 7;
this.authorx.Text = "";
//
// title
//
this.titlex.Location = new System.Drawing.Point(200, 62);
this.titlex.Name = "title";
this.titlex.Size = new System.Drawing.Size(152, 20);
this.titlex.TabIndex = 8;
this.titlex.Text = "";
//
// publisher
//
this.publisherx.Location = new System.Drawing.Point(200, 92);
this.publisherx.Name = "publisher";
this.publisherx.Size = new System.Drawing.Size(152, 20);
this.publisherx.TabIndex = 9;
this.publisherx.Text = "";
//
// year
//
this.yearx.Location = new System.Drawing.Point(200, 122);
this.yearx.Name = "year";
this.yearx.Size = new System.Drawing.Size(152, 20);
this.yearx.TabIndex = 10;
this.yearx.Text = "";
//
// subject
//
this.subjectx.Location = new System.Drawing.Point(200, 152);
this.subjectx.Name = "subject";
this.subjectx.Size = new System.Drawing.Size(152, 20);
this.subjectx.TabIndex = 11;
this.subjectx.Text = "";
//
// keyword
//
this.keywordx.Location = new System.Drawing.Point(200, 182);
this.keywordx.Name = "keyword";
this.keywordx.Size = new System.Drawing.Size(152, 20);
this.keywordx.TabIndex = 12;
this.keywordx.Text = "";
//
// isbn
//
this.isbnx.Location = new System.Drawing.Point(200, 212);
this.isbnx.Name = "isbn";
this.isbnx.Size = new System.Drawing.Size(152, 20);
this.isbnx.TabIndex = 13;
this.isbnx.Text = "";
this.isbnx.TextChanged += new
System.EventHandler(this.textBox7_TextChanged);
//
// button1
128
//
this.button1.Location = new System.Drawing.Point(144, 248);
this.button1.Name = "button1";
this.button1.TabIndex = 14;
this.button1.Text = "Search";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// display
//
this.display.Location = new System.Drawing.Point(40, 296);
this.display.Name = "display";
this.display.Size = new System.Drawing.Size(312, 208);
this.display.TabIndex = 16;
this.display.Text = "";
//
// cwsForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(384, 558);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.display,
this.button1,
this.isbnx,
this.keywordx,
this.subjectx,
this.yearx,
this.publisherx,
this.titlex,
this.authorx,
this.label7,
this.label6,
this.label5,
this.label4,
this.label3,
this.label2,
this.label1});
this.Name = "cwsForm";
this.Text = "CWS Book Search";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
[STAThread]
static void Main()
{
Application.Run(new cwsForm());
}
}
else
{
result = svc.searchAll(authorx.Text,titlex.Text,
publisherx.Text,yearx.Text,subjectx.Text,
keywordx.Text);
display.AppendText(result);
result = null;
authorx.Text = "";
titlex.Text = "";
publisherx.Text = "";
yearx.Text = "";
subjectx.Text = "";
keywordx.Text = "";
isbnx.Text = "";
}
}
catch(Exception ee)
{
APPENDIX 14
BookServerImplService.cs
//-----------------------------------------------------------------------------
-
// <autogenerated>
// This code was generated by a tool.
// Runtime Version: 1.0.3705.6018
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
//-----------------------------------------------------------------------------
-
//
// This source code was auto-generated by wsdl, Version=1.0.3705.6018.
//
namespace Search
{
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Web.Services;
/// <remarks/>
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="BookServerImplSoapBinding
", Namespace="http://matrix.csis.pace.edu:23451/axis/BookServerImpl.jws")]
public class BookServerImplService :
System.Web.Services.Protocols.SoapHttpClientProtocol
{
/// <remarks/>
public BookServerImplService()
{
this.Url = "http://matrix.csis.pace.edu:23451/axis/BookServerImpl.jws";
}
/// <remarks/>
[System.Web.Services.Protocols.SoapRpcMethodAttribute("",
RequestNamespace="http://DefaultNamespace",
ResponseNamespace="http://matrix.csis.pace.edu:23451/axis/BookServerImpl.jws")]
[return: System.Xml.Serialization.SoapElementAttribute("searchAllReturn")]
public string searchAll(string author, string title, string publisher, string
year, string subject, string keyword)
{
object[] results = this.Invoke("searchAll", new object[] {
author,
title,
publisher,
year,
131
subject,
keyword});
return ((string)(results[0]));
}
/// <remarks/>
public System.IAsyncResult BeginsearchAll(string author, string title, string
publisher, string year, string subject, string keyword, System.AsyncCallback
callback, object asyncState)
{
return this.BeginInvoke("searchAll", new object[] {
author,
title,
publisher,
year,
subject,
/// <remarks/>
public string EndsearchAll(System.IAsyncResult asyncResult)
{
object[] results = this.EndInvoke(asyncResult);
return ((string)(results[0]));
}
/// <remarks/>
[System.Web.Services.Protocols.SoapRpcMethodAttribute("",
RequestNamespace="http://DefaultNamespace",
ResponseNamespace="http://matrix.csis.pace.edu:23451/axis/BookServerImpl.jws")]
[return: System.Xml.Serialization.SoapElementAttribute("searchIsbnReturn")]
public string searchIsbn(string isbn)
{
object[] results = this.Invoke("searchIsbn", new object[] {
isbn});
return ((string)(results[0]));
}
/// <remarks/>
public System.IAsyncResult BeginsearchIsbn(string isbn, System.AsyncCallback
callback, object asyncState)
{
return this.BeginInvoke("searchIsbn", new object[] {
APPENDIX 15
AssemblyInfo.cs
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build //
// Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly
signing.
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which
// contains a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name)
utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile
// is located in the project directory, you would specify the
// AssemblyKeyFile attribute as [assembly:
AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
133
APPENDIX 16
PublishCWS.java
import org.uddi4j.client.*;
import org.uddi4j.datatype.*;
import org.uddi4j.datatype.business.*;
import org.uddi4j.datatype.tmodel.*;
import org.uddi4j.response.*;
import org.uddi4j.util.*;
import java.util.*;
// Add SSL support (this is IBM's SSL support but it can be replaced
// with other implementations)
//System.setProperty("java.protocol.handler.pkgs",
// "com.ibm.net.ssl.internal.www.protocol");
//java.security.Security.addProvider(new com.ibm.jsse.JSSEProvider());
// Create businessEntity
BusinessEntity businessEntity = new BusinessEntity();
businessEntity.setBusinessKey("");
// Set contacts
Contacts contacts = new Contacts();
contacts.add(ceo);
134
businessEntity.setContacts(contacts);
// Save businessEntity
Vector businessEntityList = new Vector();
businessEntityList.add(businessEntity);
BusinessDetail businessDetail =
uddiProxy.save_business(authToken.getAuthInfoString(), businessEntityList);
// Display businessKey
System.out.println("Published businessEntity key: " + businessKey + ".");
}
catch (Exception e) {
System.out.println("EXCEPTION: " + e.toString());
}
System.exit(0);
}
}
135
APPENDIX 17
FindCWS.java
/*
* The source code contained herein is licensed under the IBM Public License
* Version 1.0, which has been approved by the Open Source Initiative.
* Copyright (C) 2001, International Business Machines Corporation
* Copyright (C) 2001, Hewlett-Packard Company
* All Rights Reserved.
*
*/
import java.util.Properties;
import java.util.Vector;
import org.uddi4j.UDDIException;
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.datatype.Name;
import org.uddi4j.response.BusinessInfo;
import org.uddi4j.response.BusinessList;
import org.uddi4j.response.DispositionReport;
import org.uddi4j.response.Result;
import org.uddi4j.util.FindQualifier;
import org.uddi4j.util.FindQualifiers;
/**
* Sample code that exercises the Enquiry API. Attempts
* to find a business by name.
*
* <OL>
* <LI>Sets up a UDDIProxy object
* <LI>Finds businesses by name.
* </OL>
*
* @author David Melgar (dmelgar@us.ibm.com)
* @author Rajesh Sumra (rajesh_sumra@hp.com)
*/
try
136
{
// Select the desired UDDI server node
proxy.setInquiryURL(config.getProperty("inquiryURL"));
proxy.setPublishURL(config.getProperty("publishURL"));
Vector businessInfoVector =
businessList.getBusinessInfos().getBusinessInfoVector();
for( int i = 0; i < businessInfoVector.size(); i++ )
{
BusinessInfo businessInfo = (BusinessInfo)businessInfoVector.elementAt(i);
APPENDIX 18
Configurator.java
/*
* The source code contained herein is licensed under the IBM Public License
* Version 1.0, which has been approved by the Open Source Initiative.
* Copyright (C) 2001, International Business Machines Corporation
* Copyright (C) 2001, Hewlett-Packard Company
* All Rights Reserved.
*
*/
import java.util.Properties;
import org.uddi4j.transport.TransportFactory;
/**
* Configures the environment for UDDI4J
* <OL>
* <LI>Reads samples property file.
* <LI>Sets SOAP transport according to property file.
* <LI>Configures SSL/JSSE provider
* </OL>
*
* @author David Melgar (dmelgar@us.ibm.com)
*/
/**
* Loads configuration file. File may require
* modification before running samples.
*
* @return Loaded properties object
*/
public static Properties load() {
Properties config = new Properties();
try {
config.load(new java.io.FileInputStream("C:\\Documents and
Settings\\Web\\CWSws\\src\\propCWS.properties"));
} catch (Exception e) {
System.out.println("Error loading samples property file\n" + e);
}
APPENDIX 19
PropCWS.properties
# -----------------------------------------------------------------------
# inquiryURL: The URL for the inquiry API of the target UDDI registry
# publishURL: URL for the publish API of the target UDDI registry
# A list of UDDI URLs is on the UDDI4J website http://www.uddi4j.org/
#
# A typical entry would be of the form
# inquiryURL=http://company.com/uddi_node
# publishURL=https://company.com/uddi_publish_node
# -----------------------------------------------------------------------
# UDDI site
# inquiryURL = http://uddi.ibm.com/beta/inquiryapi
# publishURL = https://uddi.ibm.com/beta/publishapi
inquiryURL = http://uddi.microsoft.com/inquire
publishURL = https://uddi.microsoft.com/publish
# -----------------------------------------------------------------------
# Userid/passwords should not generally be stored in clear text
# -----------------------------------------------------------------------
userid = mr13204w@pace.edu
password = cwspacepass1
# -----------------------------------------------------------------------
# Transport classname. Typically defined on commandline as
# -Dorg.uddi4j.TransportClassName=xxx.
# -----------------------------------------------------------------------
# TransportClassName=org.uddi4j.transport.ApacheSOAPTransport
TransportClassName=org.uddi4j.transport.ApacheAxisTransport
# TransportClassName=org.uddi4j.transport.HPSOAPTransport
# -----------------------------------------------------------------------
# Debug log enabled or not. Typically defined on command line as
# -Dorg.uddi4j.logEnabled=true
# -----------------------------------------------------------------------
logEnabled=false
# logEnabled=true
# -----------------------------------------------------------------------
# Values used to determine the implementation of JSSE to use. Provided
# for convenience, this is typically configured within the jdk
# in JAVA_HOME\jre\lib\security
# -----------------------------------------------------------------------
# Sun JSSE implementation
handlerPackageName=com.sun.net.ssl.internal.www.protocol
securityClassName=com.sun.net.ssl.internal.ssl.Provider
# -----------------------------------------------------------------------
# UDDI names to use.
# -----------------------------------------------------------------------
businessName=
serviceName=
tmodelName=
sampleEntityName=
140
assertionRelationship=peer-peer
# -----------------------------------------------------------------------
# Additional values can be added as needed as a convenient repository
# for data relevant to the UDDI4J samples
# -----------------------------------------------------------------------
141
APPENDIX 20
Tomcat Installation
1) Download the Apache Tomcat Server and Tomcat installation instructions from
http://jakarta.apache.org/tomcat/index.html. (Certain IDEs, like Netbeans, come
with Tomcat Server and the Sun JDK, which facilitate creating a Web Service
locally)
Axis Installation
1) Download Axis 1.1 from http://ws.apache.org/axis/releases.html
2) Complete instructions are located at http://ws.apache.org/axis/java/install.html
3) After expanding the Axis 1.1 file, copy the webapps/axis folder to Tomcat’s
webapp directory using SSH File Transfer
4) Using SSH File Transfer, copy jaxrpc.jar and saaj.jar from
$CATALINA_HOME/webapps/axis/WEB-INF to
$CATALINA_HOME/common/lib folder
5) Restart Tomcat
6) To verify correct installation, visit http://matrix.csis.pace.edu:port#/axis (port# is
an assigned Tomcat port number from a system administrator)
7) Select Validate. Correct any errors before continuing by referencing Axis’ guide
8) Using SSH Terminal Window, add Axis’ jar files from the Tomcat root directory
to the Java CLASSPATH as follows:
export AXIS_HOME=$CATALINA_HOME/webapps
export AXIS_LIB=$AXIS_HOME/axis/WEB-INF/lib
export AXISCLASSPATH=$AXIS_LIB/axis.jar:$AXIS_LIB/commons-discovery.jar:
$AXIS_LIB/commons-logging.jar:$AXIS_LIB/jaxrpc.jar:
$AXIS_LIB/saaj.jar:$AXIS_LIB/log4j-1.2.8.jar:
$AXIS_LIB/wsdl4j.jar:$AXIS_LIB/axis-ant.jar
export CLASSPATH=$CLASSPATH:$AXISCLASSPATH
9) If XML parsing capabilities are required, ensure XERCES libraries are in the
CLASSPATH
142
1) Using SSH File Transfer, place all .gif, .jpg, .html, and .jsp files in the
$CATALINA_HOME/webapps/pace directory. For CWS, all required .gif files
and the following .jsp files are to be uploaded:
aboutus.jsp error.jsp index.jsp
results.jsp search.jsp
2) Using SSH File Transfer, upload Controller.java to the
$CATALINA_HOME/webapps/pace/WEB-INF/classes directory and
BookBean.java to the $CATALINA_HOME/webapps/pace/WEB-
INF/classes/CWS directory
3) Using SSH Terminal, navigate to the corresponding directories and compile the
two java files as follows:
javac Controller.java
javac BookBean.java
APPENDIX 21
Once search criteria is entered, a user selects the “CWS Search” button to initiate a
search. A user can opt to select the “Clear” button to erase all search criteria and begin a
new search.
For Non-ISBN searches, search results are displayed with 20 books per page. Click on
“Next 20 Results” to view subsequent pages or utilize the “Back” button on the browser
to view previous pages. A user can make a book selection by clicking with their mouse
on a specific radio button and selecting the “Shop Prices” button. This launches the CWS
price-search tool (Searches with an ISBN parameter launch the price-search tool
directly). Book prices are displayed and sorted in ascending order. Select the
corresponding vendor book image to navigate to the vendor’s web site to make a
purchase.
A new search can be initiated at any time by clicking on the “Click Here For New
Search” link. In the event of an error, an error message is displayed and the “Click here
to search again” link is provided to begin a new search.
144
CWS can be discovered programmatically or via a Web browser using IBM’s and
Microsoft’s UDDI. To search CWS via a browser use the following link(s):
http://www-.ibm.com/services/uddi/inquiryapi
http://uddi.microsoft.com/inquire
http://matrix.csis.pace.edu:23451/axis/BookServerImpl.jws?wsdl
Both methods return book results as XML. The following sample, browser-based request
demonstrates the XML that is returned from invoking CWS’ searchIsbn method:
Request
http://matrix.csis.pace.edu:23451/axis/BookServerImpl.jws?method=searchIsbn&
isbn=0672326418
XML Response
.
.
.
<?xml version="1.0"?>
<Results>
<Book>
<Title>Building Web Services with Java : Making Sense of
XML, SOAP, WSDL, and UDDI (2nd Edition) (Developer's
Library)</Title>
<Authors>Steve Graham,Doug Davis,Simeon Simeonov,Glen
Daniels,Peter Brittenham,Yuichi Nakamura,Paul
Fremantle,Dieter Koenig,Claudia Zentner</Authors>
<Publisher>Sams</Publisher>
<ISBN>0672326418</ISBN>
<RetailPrice>49.99</RetailPrice>
</Book>
<Vendor>Amazon</Vendor>
<Price>34.97</Price>
145
<Link>http://www.amazon.com/exec/obidos/ASIN/067232
6418</Link>
<Vendor>Amazon-Used</Vendor>
<Price>25.11</Price>
<Link>http://www.amazon.com/exec/obidos/ASIN/067232
6418</Link>
<Vendor>Barnes and Noble</Vendor>
<Price>49.99</Price>
<Link>http://search.barnesandnoble.com/booksearch/isbnI
nquiry.asp?endeca=1&isbn=0672326418</Link>
.
.
.
</Results>
CWS’ MVC architecture consists of a Controller class, BookBean class, and three
presentation classes: index.jsp, results.jsp, search.jsp, and error.jsp. The
Controller is the workhorse of the group containing all the key vendor methods and
supporting methods. A majority of the vendor data is accessed via html scraping, and
therefore such methods require continuous housekeeping. In the event that a vendor
alters their web page, the corresponding method must be adjusted with changes
entailing resetting stable identifiers which target specific book prices or altering
access URLs. Additional vendors and business partners may be added to the
Controller class.
After such changes, the Tomcat server must be stopped and started again for changes
to take effect. Using SSH Terminal, navigate to $CATALINA_HOME/bin directory
and stop and start the Tomcat Server with the following commands:
./shutdown.sh
./startup.sh.
146
REFERENCES
[1] Freeman, Adam and Allen Jones. Microsoft .NET XML Web Services Step by
http://www.line56.com/articles/default.asp?articleid=6028
http://www.adtmag.com/java/article.asp?id=354&mon=3&yr=2001
[5] http://www.ebuilt.com/fielding/pubs/dissertation/top.htm
[7] Bau, David. “JWS: Web Services in Java-Making Integration easier.” Web
http://www.sys-con.com/webservices/articleprint.cfm?id=211
http://ws-i.org/Profiles/Basic/2003-08/BasicProfile-1.0a.htm
147
[9] The Radicati Group. “Web Services Market, 2004-2008.” (Sep. 2004)
http://www.radicati.com/
[10] Jenz, Dieter E. “A View at Total Cost of Ownership and Return on Investment –
http://www.webservices.org/ws/content/view/full/1605
[11] LaMonica, Martin. “Where’s the Simplicity in Web Services.” News.com (Oct
2004), http://news.com.com/Wheres+the+simplicity+in+Web+services/2100-
7345_3-5395630.html
[12] Seeley, Rich. “Binary XML is Fast in Theory but Slow in Adoption.”
[13] Graham, Steve. Building Web Services with Java: Making sense of XML,
http://www.niso.org/standards/resources/ISBN.html