Creating a Web service from a Java
class
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Table of Contents
If you're viewing this document online, you can click any of the topics below to link directly to that section.
.......................................................
2
2. Introduction to RPC-style Web services
............................
7
3. Java API for XML-based RPC (JAX-RPC)
.........................
8
4. RPC Web service development life cycle
..........................
14
5. Lab 1: Building and deploying a Web service
.....................
17
6. Lab 2: Exchanging complex SOAP objects
........................
26
7. Lab 3: Dynamic Web service client
.................................
30
8. Tutorial wrapup and resources
.......................................
35
Creating a Web service from a Java class
Page 1 of 36
Section 1. About this tutorial
Purpose of this tutorial
This tutorial delves into the subject of RPC-style Web services and how to use them with
IBM's WebSphere SDK for Web services V5.0 (WSDK). We show you how to write Web
service implementations, and how to build and deploy them with the WSDK, as well as
showing you how to create clients to invoke them.
In particular, we will demonstrate the ability of IBM's WSDK to exchange complex SOAP data
types. Although passing text strings and simple arrays is a good way to get you started with
Web services, real world applications typically require that client and service exchange whole
objects and similar complex data structures.
The tutorial begins with a brief examination of RPC-style Web services, followed by a section
on JSR-101, the Java API for XML-based RPC (JAX-RPC). We look at the architecture and
the most important API types for JAX-RPC. We also look at how static and dynamic
invocations work in the context of JAX-RPC.
Finally, a real-world application of these concepts is explored through three labs as a part of
our online DVD e-commerce store case study.
What you need to know for this tutorial
This tutorial assumes you have a working knowledge of Java programming and XML.
Knowledge of J2EE and Ant are helpful but not required. All of the example applications will
be deployed on IBM WebSphere Application Server that ships with the WSDK. Ant build
scripts are provided to make building and deploying the example applications easier and
more reliable. References to introductory material on Ant, Java programming, XML, IBM
WebSphere, and J2EE are provided in
on page 35 at the end of this tutorial.
What this tutorial covers
This tutorial explores the world of RPC-style Web services in depth. The following topics,
tools, and techniques will be covered:
Topics
•
Introduction to RPC-style Web services
•
Java API for XML-based RPC (JAX-RPC)
•
Building and calling a Web service with IBM's WSDK
•
Building a dynamic Web services client with IBM's WSDK
Tools
•
Bean2WebService - Convert standard Java classes into Web services
•
JAX-RPC
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 2 of 36
Creating a Web service from a Java class
Techniques
•
Building and deploying a Web service
•
Working with complex data types
•
Creating a dynamic Web service client
About the labs in this series
All of the tutorials in this series focus on an online DVD rental shop similar to
. The
use case we are addressing, Rental Recommendation, involves allowing users to submit
what category movie they would like to rent and, based on their rental history, the Web
service suggests other movies. In the first tutorial ("Introduction to Web services and the
WSDK"), we simply ran one of the sample Web services and didn't build anything. In this
second tutorial, we expand our exploration of working with Web services using three labs:
•
Lab 1: Building and deploying a Web service -- In this lab, we walk through the process
of building and deploying a simple service, rather than having one handed to you. We also
introduce the Bean2WebService script and demonstrate its use.
•
Lab 2: Working with complex data types -- With this lab, we move a step closer to
fulfilling the Rental Recommendation use case by returning a complex data structure
representing a DVD object.
•
Lab 3: Dynamic client - This client also exchanges complex data types with the service
created in the previous lab. In this case, however, the client uses a dynamic invocation as
opposed to a static stub.
About the authors
Lead author, this tutorial
Rick Hightower -- CTO,
Rick Hightower, Chief Technology Officer at LearningPatterns, is a published author with
multiple achievements, industry awards, and certifications. In addition to writing many
technical articles, Rick is co-author of the book Java Tools to Extreme Programming, an
Amazon.com best seller, that covers applying Extreme Programming to J2EE development
using Ant, JUnit, Cactus, and more. He recently released a book on Java/Python
programming that covers JFC, Swing, JDBC, Java Servlets, Applets, functional
programming, object-oriented programming, regular expressions, and so on.
Rick wrote a series of well-received tutorials on EJB 2.0 CMP CMR for IBM developerWorks.
Rick enjoys coding, development, instructing, mentoring, consulting, and speaking. Rick has
recently spoken at XP Universe, JDJ Edge East, Lone Star Software Symposium, and other
conferences on applying XP to J2EE, XDoclet, and EJB CMP/CMR/EJB QL. While working
at Intel, Rick wrote a chapter for the book Java Distributed Objects, comparing CORBA, RMI,
and DCOM development with Java technology.
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 3 of 36
Prior to working at LearningPatterns, Rick held the position of Director of Development for a
major software development and consulting firm where he was responsible for building a
framework and applications built on top of J2EE. He initiated a study group in XP, Java Cert,
J2EE and Design Patterns, developed the corporate training initiative, and also guided the
career development and education of the entire technical staff. In a previous life, Rick worked
at Intel's Distributed Enterprise Architecture Lab (DEAL) focusing on Enterprise Java (EJB
technology, CORBA, and so on).
Other authors
David Fraser -- Senior Mentor and Instructor,
David Fraser, a Senior Instructor at LearningPatterns, teaches a wide range of courses,
including Java/J2EE technology (EJB technology, Java Servlets/JSP technology, JDBC
technology), XML, XSLT, Advanced XSLT, Web services, and OOAD, and has co-authored
LearningPatterns Java Servlets/JSP technology and Web services courses. He has also
lectured at numerous conferences including speaking on J2EE at CAWorld, and on Java
Performance and Java Enterprise Architecture at Software Development Expo. His main
area of interest is in building distributed Enterprise systems and he is now focusing on Web
services and their related technologies.
David has his Master's of Information Technology Education degree from Dalhousie
University and is a Sun Certified Java Programmer. Previously, David worked for the
American Intercontinental University in Atlanta. While there, he played a principal role in
designing the company's Java technology curriculum for all of its campuses, taught Java
programming, and developed Java technology-based educational tools.
Kyle Gabhart -- Senior Mentor and J2EE and Web Services Specialist,
Kyle Gabhart, Senior Mentor at LearningPatterns, is a highly-regarded advanced Java
programming, XML and Web services subject matter expert and mentor. Kyle is a popular
public speaker recognized for his enthusiasm and dynamic analysis and presentation of
emerging technologies.
In addition to writing two dozen technical articles both online and in print, he has contributed
to two books, Professional Java and XML and Professional EJB Development, both by Wrox
Press. Kyle is the founder of the Web Services Java Users Group based in Dallas, TX, and
he is a Founding Member of the Worldwide Institute of Software Architects where he serves
as the Subject Chair for Architectural Patterns. Kyle also served as the DevX Java Pro at
DevX.com for two years.
Currently Kyle is delivering a Web services mentoring program focused on white board
discussions and practical hands-on work focused on foundational technologies such as XML,
XSL/XSLT, and Xpath, as well as high-level Web services concepts such as SOAP, WSDL,
UDDI, ebXML, and .NET. Kyle works directly with the developers to transfer his real-world
knowledge of Web services application development. All labs are J2EE-centric, but all
solutions are fully interoperable with .NET services.
Kyle is a Sun Certified Java Programmer and an IBM Certified Solution Developer.
Peter Schmitz -- Enterprise Java Consultant and Instructor,
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 4 of 36
Creating a Web service from a Java class
Peter Schmitz is an integral part of the core consulting, mentoring, and course development
team at LearningPatterns. Responsible for the development, testing, and maintenance of
many of the company's technology-centric suite of offerings, Peter combines his practical
programming skills and mentoring excellence to develop the highest quality educational
programs available.
Peter also contributes heavily to the development, maintenance, and delivery of
vendor-specific lines and unique educational offerings, often developed as custom solutions
for third party clients and partners. His technical focus includes developing programs and
projects focused around Java technology, EJB technology, J2EE, Java Servlets, JSP files,
IBM WebSphere 4.0, XML, Web services (SOAP, UDDI, etc.) and more.
Most recently Peter served as a consulting Technical Architect at ING Bank, where he was
responsible for maintaining and expanding the Technical Architecture for a Business
Services Framework based on XML, Java Servlets and EJB technology. In this project, he
used IBM WebSphere, the IBM MQ Series, VisualAge for Java, and a Relational database.
Peter has served as Project Leader, Technical Architect, Analyst, Mentor, and Senior
Software Engineer on a number of prior consulting engagements.
Jacob Weintraub -- Co-founder and Director of Services,
Jacob Weintraub, co-founder and Director of Services at LearningPatterns, has been working
in Object and Advanced Technologies since 1988. He began working with the beta release of
the Java programming language in 1995, and also authored one of the earliest Java
technology courses offered to the public.
Since that time, he has spearheaded LearningPatterns' work at the cutting edge of advanced
enterprise technologies. This has included teaching and mentoring businesses in topics such
as J2EE/EJB technology, Object-Oriented Analysis and Design, XML/XSLT, and now in Web
services. He has also lectured at numerous conferences and written articles for Java Report
and JavaWorld.
Following LearningPatterns' belief that the best teacher is an experienced programmer,
Jacob is a seasoned developer. His experience includes mentoring teams of programmers
on building EJB technology-based systems, the development of OO libraries for financial
systems, development of a CORBA IDL to C++ compiler, and research into the management
of Very Large Computer Networks using layered OO models with the Distributed Computing
and Communications Center at Columbia University.
Tools you will need for this tutorial
At a minimum, you will need a simple text editor, a browser, and a Java SDK 1.3 (included
with the WSDK) or higher to compile the examples. You will also need the IBM WebSphere
SDK for Web Services (WSDK). The WSDK can be found at
. You can also order free CDs, which include the WSDK as well as other IBM Web
services ready products such as WebSphere Studio from the
program. The WSDK ships with its own Java SDK (1.3.1), and batch files and
programs for starting, stopping, and administrating the embedded WebSphere Application
Server that ships with the WSDK.
Although building and deploying applications by hand can be fun, all of the examples include
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 5 of 36
Ant build scripts to build and deploy the Web services we will be creating. Ant can be found
at
.
It is recommended that you use an Interactive Development Environment (IDE) since there
are quite a few JAR files to manage. We used Eclipse, a freely-available IDE, to build the
sample applications. The Eclipse project files are included in the lab exercises zip file (see
on page 35 ). Since the Eclipse workbench is also the foundation for IBM's
WebSphere Studio Application Developer, the projects files are compatible with both Eclipse
and Application Developer. As long as you configure your environment as suggested you can
use the Eclipse project files without any additional work. Eclipse or Application Developer is
not required, but can be found at the following locations:
and
WebSphere Studio Application Developer Web site
, respectively. There is no requirement to
use Eclipse or Application Developer, but they are fully functional IDEs that can make your
life easier in building and working with Web services projects.
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 6 of 36
Creating a Web service from a Java class
Section 2. Introduction to RPC-style Web services
RPC-style or document-style?
Web services represent a tremendous step forward in terms of standards-based distributed
computing. A Web service can be used to do everything from Web-enabling a legacy
application, to deploying an application that can be accessed by clients written in different
programming languages, to establishing an internal corporate repository of components to
reduce maintenance and duplication of code. In any of these contexts, a particular Web
service could be implemented as either an RPC-style Web service or a Document-style
service.
The distinction between RPC services and Document services comes down to a matter of
business model and overall technical architecture. Consider the following descriptions:
•
RPC-style Web services essentially expose your server-side functionality as a remote
object that is typically accessed via a local proxy object on the client side. This type of
service tends to be rather fine-grained, exposing an interface that closely approximates the
actual data structures used internally to represent information.
•
Document-style Web services are considerably less restrictive than RPC-style Web
services. The service consumes the entire body of a Document-style SOAP message and
parses it as a standard XML document. This type of service tends to be more
coarse-grained, exposing a very general interface that accepts any document that adheres
to a specified XML schema. This approach hides the internal representation of data and
business processes from the end user.
It is often easier to understand the distinction between these two service models by
comparing them at a high-level, in a feature-by-feature comparison, as shown in the following
table:
RPC-style
Document-style
Message body
Treated as a collection of
parameters
Processed as an arbitrary
document
Processing model
Parameters mapped to native
data structures
Parse XML based on an external
XML Schema
Invocation
mechanism
Method called on local proxy
object, routed directly to service
interface
Document published to server for
processing
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 7 of 36
Section 3. Java API for XML-based RPC (JAX-RPC)
JSR-101: JAX-RPC
JSR-101 is the Java API for XML-based RPC (JAX-RPC). The objective of this JSR is to
create a specification and API that support the development of simple Web services and
Web service clients in such a way as to shield developers from the underlying complexity of
SOAP communication.
The JAX-RPC Expert Group has the following goals for the specification:
•
Simplicity
•
Interoperability across heterogeneous environments
•
Conformance with any interoperability standards
•
Extensibility and modularity
The WSDK has implemented JSR-101 in the tools, libraries, and supported APIs that ship
with the product. In fact, the sample in the first tutorial ("Introduction to Web services and the
WSDK") relied upon classes and libraries that implement JSR-101. In this tutorial we will
learn more about JAX-RPC, RPC-style Web services, and of course, the WSDK's support for
JSR-101.
Rather than overwhelm you with a lot of detail that you won't need to create simple
RPC-based Web services, we have split the discussion of RPC-style Web services across
three small tutorials (this one, "Creating a Web service from a Stateless Session Bean," and
"Describing Web Services: WSDL"). Once you complete this tutorial and "Creating a Web
service from a Stateless Session Bean", then you will be ready to dig deeper into WSDL and
some of the lower-level tools that come with the WSDK like WSDL2WebService. If you follow
along until then, you will have a deep practical knowledge of RPC-based Web services and a
strong foundation to master the rest of the tutorials in this series.
JAX-RPC architecture basics: Deja vu?
JAX-RPC, the Java API for XML-based RPC, is a specification for building Web service
providers and requesters. A requester is a client of a Web service. The requester can
perform remote method invocation against the client.
Deja vu, you say. Does this sound familiar? On the surface JAX-RPC looks like another
instantiation of RMI. In fact, in a way it is, but geared to Web services with some additional
limitations. Essentially, JAX-RPC allows clients to access a Web service as if the Web
service was a local object mapped into the client's address space even though the Web
service provider could be on the other side of the world.
However instead of IIOP or JRMP, as in the RMI world, in the JAX-RPC world a remote
method invocation (referred to as a remote procedure call) is done via the XML-based
protocol SOAP 1.1, which typically rides on top of HTTP. The SOAP protocol uses an
envelope structure that encodes method invocation data and method responses using XML
Schema and other encoding rules.
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 8 of 36
Creating a Web service from a Java class
Luckily, you do not have to worry about the low-level details and complexity of SOAP to use
Web services. The Web service provider developer can specify the remote procedures by
defining remote methods in a Java interface just like you do in RMI. From this interface you
generate a Web service description language file (WSDL file). From the WSDL file you can
generate a stub just like you would in RMI. Here's a very high view of how it all works
together:
The invocation above works like this:
•
The client invokes a method on a stub, a proxy which invokes routines in the JAX-RPC
runtime.
•
The JAX-RPC runtime converts the invocation into a SOAP message and transmits it
(usually over HTTP).
•
The server side receives it, and its JAX-RPC runtime translates the SOAP message into a
method invocation.
•
The JAX-RPC runtime invokes a method on the tie object, which delegates it to the actual
service implementation.
•
It returns the same way. The service implementation's response is translated into a SOAP
message, sent back to the client, where it gets translated and passed up the chain to the
client.
The Web service provider developer only needs to code one or more classes that implement
those methods just like the server-side RMI developer would create a servant. The rest of the
classes can be generated automagically by the Web service vendor's tools.
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 9 of 36
Here's an example of a Web service interface that looks just like its RMI cousin (which we
will look at next):
package lpc.dvdonline.complexrpc.server;
import lpc.dvdonline.complexrpc.service.DVD;
public interface DVDOnlineStore_SEI extends java.rmi.Remote {
public DVD getDVD() throws java.rmi.RemoteException;
}
JAX-RPC datatypes and interface rules
Web services typically use XML Schema for creating strongly typed services. There are
standard type mappings from XML Schema to Java code. For example, a xsd:string in XML
Schema maps to java.lang.String. Don't worry about all of the details of this now. We will
touch on some of the details in this tutorial; just enough for you to get by. We cover WSDL,
XML Schema, and Java mappings in a lot of detail in the tutorial "Describing Web services:
WSDL." For now, let's cover the allowed types and rules for defining the interface, since
you'll need that to define your Web services properly.
You will recall our previous sample interface:
package lpc.dvdonline.complexrpc.server;
import lpc.dvdonline.complexrpc.service.DVD;
public interface DVDOnlineStore_SEI extends java.rmi.Remote {
public DVD getDVD() throws java.rmi.RemoteException;
}
Just like in RMI, the interface definition in JAX-RPC has to follow certain rules; most of these
rules are from RMI with some additions for JAX-RPC. Here are the rules for defining a
JAX-RPC interface:
1. The interface must extend
java.rmi.Remote
just like RMI.
2. Methods must throw
java.rmi.RemoteException
3. Method parameters must not be remote references (an addition to the regular RMI rules).
4. Method parameters must be one of the following:
•
Primitive Types: boolean, byte, double, float, short, int, and long
•
Object wrappers of primitive types: java.lang.Boolean, java.lang.Byte, java.lang.Double,
java.lang.Float java.lang.Integer, java.lang.Long, java.lang.Short
•
java.lang.String
•
java.lang.BigDecimal
•
java.lang.BigInteger
•
java.lang.Calendar
•
java.lang.Date
5. Methods may take value objects, which consist of a composite of the types mentioned
above plus aggregate value objects.
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 10 of 36
Creating a Web service from a Java class
Value objects are simple Java types that must follows certain rules, which we cover next.
Value objects
A value object is just a bean. It has to have getters and setters that will be mapped to XML
elements and attributes. Unlike plain RMI, the JavaBean does not have to be serializable, but
it does need a no-argument public constructor. The JAX-RPC implementation uses the getter
and setter methods to populate the bean. Here is an example of a value object:
package lpc.dvdonline.complexrpc.service;
public class DVD {
private String title; // unique id (primary key)
private int rank;
private String category;
public DVD() {
title = "no title";
rank = 0;
category = "no category";
} //end DVD()
public DVD(String _title, int _rank, String _category) {
title = _title;
rank = _rank;
category = _category;
} //end DVD( String, int, String )
public String getCategory() {
return category;
} //end getCategory()
public int getRank() {
return rank;
} //end getRank()
public String getTitle() {
return title;
} //end getTitle()
public void setCategory(String category) {
this.category = category;
} //end setCategory( String )
public void setRank(int rank) {
this.rank = rank;
} //end setRank( int )
public void setTitle(String title) {
this.title = title;
} //end setTitle( String )
} //end class DVD
JAX-RPC stubs and clients
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 11 of 36
Let's look at the requester side now (the client code). The requester programs are easy to
build as well. A client creates a stub and invokes methods on it. The stub acts like a proxy for
the Web service. From the client code perspective, it seems like a local method invocation.
However, each method invocation gets marshaled to the remote server. This marshalling
includes encoding the method invocation in XML as prescribed by the SOAP protocol.
But wait! That's not all. In the JAX-RPC world the server does not have to be a Java server.
As long as you have a WSDL file, you can generate a stub and start invoking methods on the
Web service no matter what the platform or language. This is the beauty of Web services
and open standards like HTTP, SOAP, and WSDL. WSDL is an XML file format that
describes a Web service's locations, operations, and supported types. There will be more
detail about WSDL in the tutorial "Describing Web services: WSDL," which focuses on
WSDL.
If someone gives you a WSDL file that describes an RPC style Web service, you can run a
utility against that WSDL file to create a stub. A stub is a proxy object that has methods that
match the operations of the remote interface. Much of the details of WSDL and how it maps
to stub generation is hidden when you use tools like Bean2WebService, which is what we
use in this tutorial. We only talk about stubs and WSDL briefly in this tutorial and then go into
much more detail in the tutorial "Describing Web services: WSDL" when we cover the
WSDL2WebService utility.
Clients use stubs to simplify development of requesters of Web services, but they are not
really needed. You have the option of working with SOAP and JAX- RPC at a much lower
level. In addition to stubs, JAX-RPC provides a dynamic method invocation mechanism.
Static means that the generated code includes everything needed to invoke the service
directly, including interfaces that have the service methods defined as remote methods.
Dynamic means that you create the call dynamically, in a manner similar to reflection. In this
tutorial there are requester labs that use both the dynamic and static stub approaches.
Before we can look at all this though, we'll take a quick look at the JAX-RPC API.
JAX-RPC API classes of note
There are just a few key classes and interfaces that you need to be familiar with to write Web
service clients or service implementations. A good deal of it you don't even use directly.
Some of the important types are:
•
Service
interface: A factory for stubs or dynamic invocation/proxy objects that are used
to actually invoke methods
•
ServiceFactory
class: A factory for
Services
•
Call
interface: Used for dynamic invocation
•
Stub
interface: Base interface for stubs
If you are using a stub to access the Web service provider, then most of the details of the
JAX-RPC API are hidden from you. The client creates a
ServiceFactory
(
javax.xml.rpc.ServiceFactory
). From the
ServiceFactory,
the client instantiates
a
Service
(
javax.xml.rpc.Service
).
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 12 of 36
Creating a Web service from a Java class
The
Service
is a factory object that creates the port. The port is a remote interface
(
java.rmi.Remote
) into the Web service. In the case of dynamic RPC, the
Service
object is used to create
Call
objects, which specify which method to call on the Web
services port.
The tutorial "Creating a Web service from a Stateless Session Bean" has labs that use a
ServiceFactory
with information about how to configure a
ServiceFactory
. The static
client labs in this tutorial cover using the
Service
object generated by the WSDK tools to
create a port object. The dynamic client lab in this tutorial covers using this
Service
class to
create a
Call
object.
The WSDK has utilities that generate all this code for you. This includes stub and service
types. The static examples in this lab use the generated service to create the stub (also
known as the port, or remote reference). The generated service has a factory method based
on the name of the port that returns a remote reference to the interface associated with the
port. Port is a fancy name for a Web service interface (more on this in the tutorial "Describing
Web services: WSDL").
There are two versions of this factory method. One of the versions takes no arguments and
will return the Service port at the URL location of the service (known as an endpoint). The
second version of the port factory method allows you to pass a different URL location for the
service. The first lab has a lab review that shows the generated
Service
for you to look at.
Remember to look for the two different port factory methods. A few lines of code are
sometimes worth a thousand words, and we'll be looking at that soon.
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 13 of 36
Section 4. RPC Web service development life cycle
Introduction
The development life cycle for Web services is similar to that of traditional distributed
computing. Although the description given in this section is common to most Web service
implementations, the ideology and protocols upon which Web services are built allow
industry to continue to evolve the concept of "Web services." In short, what follows describes
the current state of the art and is not definitive. Also, this discussion assumes that there are
tools for the generation of the WSDL and skeletons/stubs. Although these tools are now
extremely common, there might be cases where the developer is responsible for the
stub/skeleton code.
The service
Creating and deploying an RPC-style Web service involves 5 steps:
1. Write the service implementation.
•
This is the class that actually implements the service. Usually the implementation would
already exist as some kind of server-side functionality that you want to expose.
•
Depending on the Web service tools you use, you might also need to create an interface
that defines the procedures of the service implementation that you want to expose. For
instance, the CreditCardProcessor might define 100 methods. How does a tool know
which of the 100 methods it should write supporting skeleton code for? There is probably a
subset of these 100 that are appropriate to expose. Most Web service technologies require
one to either create an interface or some other type of file that lists the methods to expose
or use meta tags in the implementation code to mark those methods that need to be
invocable as a Web service.
2. Generate the WSDL file that describes the service.
•
This is usually accomplished with a tool of some kind, although since it is an XML-based
protocol one can actually write a WSDL file using a simple text editor.
•
This step is not a requirement. However it is usually a good idea to create a WSDL file so
that clients can know how to invoke services. Also your client's Web service tools probably
use WSDL to generate the client's stub code.
•
A link to your service's WSDL file can be included in any description of your organization
or its services that appears in a registry.
3. Generate the support code (skeleton/tie) for the service implementation.
•
This is usually accomplished with a tool of some kind. This enables quicker integration with
existing systems, as the knowledge and time required to write the low-level code that
manages the socket communication and protocol stream generation is not required by the
developer.
•
Depending on the tool, this step might require you to compile the code generated. If you
are using Java code and this is the case, then you'll probably have to modify your
classpath to include whatever classes/interfaces are used in the generated code.
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 14 of 36
Creating a Web service from a Java class
4. Deploy implementation and support code.
•
This might require packaging all of the code, modifying a configuration file, and restarting a
server. Or it might only involve dropping the Web service code in a directory. In all cases
the server that is going to provide the Web service that is deployed needs to know about
your Web service and have access to its code. Different implementations will do this
differently.
5. Optionally, register your service with a registry provider.
•
To make it easier for people and processes to find and invoke your Web service, you might
want to register your Web service with a registry service. Registries, their purpose, and
how to communicate with them will be covered in two later tutorials in the series.
The client
Creating and running an RPC-style Web service client involves 4 steps:
1. Obtain the interface details of the Web service you want to invoke.
•
Usually this is accomplished by getting a WSDL file that describes the Web service that
you are interested in executing. You might acquire it from a registry, a Web site, or
someone giving it to you via e-mail or diskette for that matter.
•
WSDL seems to be the most popular way to pass Web service invocation information
around. However, a WSDL file is not required. If you can get the invocation particulars
(name of procedure, parameters, return type, url, and so on), you can write the code to
invoke a Web service.
2. Optionally generate Web service client invocation code (stubs).
•
Once you know the location (URL) of a Web service's WSDL file you can generate the
client stub code necessary for you to invoke it.
•
Most Web service technologies come with a tool for generating your stubs. Sometimes
they require you to give them generation properties such as target package, generated
class names, and so on.
•
This step is optional as there is usually a dynamic invocation API available where a stub is
not required to invoke a Web service.
3. Write the client.
•
The easiest way to write a client is to create or obtain a reference to a stub object and then
call its Web service-exposed methods.
•
If the stub is not available, or if you do not want to use it, most Web service technologies
come with an API that allows you to invoke the Web service of interest dynamically.
•
Compiling the client code will require that you have all the necessary support code (stub,
dynamic invocation api, and so on) in your classpath.
4. Run the client.
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 15 of 36
•
To run the client, your Web service runtime's client code will need to be in your classpath.
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 16 of 36
Creating a Web service from a Java class
Section 5. Lab 1: Building and deploying a Web service
Lab purpose and overview
The purpose of this lab is to provide you with hands-on experience building, deploying, and
testing a Java Web service using IBM's WSDK. This lab will also demonstrate just how easy
the WSDK makes it to deploy existing Java classes as XML Web services.
The lab has three very simple steps:
1. Create a standard Java class and declare it to be accessible as a remote object
(implement the
Remote
interface, and have each remotely accessible method throw a
RemoteException
).
2. Package the class and deploy it as a Web service using a utility called
Bean2WebService
.
3. Create a client to test the service.
Building the service provider for a simple RPC-based
Web service
In this section you are going to create your first RPC-based Web service. You will create the
Web service implementation class here. It is purposely a very simple class. To create it,
perform the following steps:
1. Before creating the service, create a folder called simpleRPC directly underneath the
%WSDK_HOME%/apps directory.
2. Inside the simpleRPC directory, create a directory called provider.
3. In the provider directory, create a directory called src.
4. In the src directory, create a series of directories representing the package structure --
lpc.dvdonline.simplerpc.server.
5. Inside the lpc\dvdonline\simplerpc\server directory, create a Java source file called
DVDOnlineStore.java. Add the following code to that source file:
package lpc.dvdonline.simplerpc.server;
public class DVDOnlineStore implements java.rmi.Remote {
public String getDVD() throws java.rmi.RemoteException {
return "Fight Club";
}//end getDVD()
}//end DVDOnlineStore
6. Compile the above class, making sure that %WSDK_HOME%\appserver\lib\j2ee.jar is in
your classpath where %WSDK_HOME% is the directory where you installed the WSDK
version 5. Navigate to the src directory and use the standard
javac
command as follows:
javac -d . -classpath %WSDK_HOME%\appserver\lib\j2ee.jar
lpc\dvdonline\simplerpc\server\DVDOnlineStore.java
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 17 of 36
Packaging, deploying, and starting the service
There is a lot that has to happen to turn this simple class into a Web service. Luckily, the
WSDK has tools that do this for you. To package and deploy your service, you need to do
only straightforward things:
1. Start the application server.
•
You can launch the application server from the start menu. The WSDK install created a
shortcut in the WSDK program group called Start Server, and you can use this to start the
server.
•
You can launch the WebSphere Application Server from the command line. It is in the bin
directory %WSDK_HOME%\bin\appserver start.
Start the Application Server. As the Application Server is loading, you'll see a few status
messages. Look for the message "Server server1 open for e-business."
2. Run the Bean2WebService utility.
•
This utility converts standard Java classes into Web services.
•
Note: Prior to invoking the tool, make sure that the WSDK's bin directory,
%WSDK_HOME%\bin, is in your path .
•
To run the utility, open a command prompt, navigate to the simpleRPC\server\src directory
(%WSDK_HOME%\apps\simpleRPC\server\src), and invoke the Bean2WebService utility
(with the command entered all on one line):
Bean2WebService -cp .;%WSDK_HOME%\appserver\lib\j2ee.jar -project
SimpleRPC -deploy lpc.dvdonline.simplerpc.server.DVDOnlineStore
The arguments we are using for Bean2WebService are as follows:
•
The
cp
flag declares a classpath for the utility.
•
The
project
flag defines a name for the EAR file and corresponding Web context.
•
The
deploy
flag declares that the resulting EAR (consisting of class files and deployment
descriptors) should be deployed to the application server and the service immediately
started.
•
Finally, the Java class to be deployed as a service is declared as the final parameter for
the script.
The result of running the tool is that a folder is created in the current directory with the same
name as the Web service project (as specified by the
project
flag on the command line).
The contents of that folder include Java class files and deployment descriptors for deploying
the Java class created earlier as a Web service in IBM's WSDK. All of these files are
contained in and appropriately organized in an EAR bearing the name of the project --
SimpleRPC.ear. You don't need to do anything with this EAR however; because the
deploy
flag was used earlier, it has already deployed the EAR to the server and stored a copy of the
EAR in an expanded format underneath the
appserver
directory. More detail about this
deployment process and deployment result will be provided later in the tutorial.
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 18 of 36
Creating a Web service from a Java class
3. Check your results.
•
Verify that the service was deployed by checking the server log files for the lack of errors
and by using the
appserver appstatus
command. The
appserver appstatus
command lists the installed enterprise application in the WebSphere Application Server,
along with their run status (running or stopped). Invoke
appserver appstatus
as
follows:
appserver appstatus
Look for the SimpleRPC application name in the list of installed enterprise applications.
4. Start the Web service.
•
Start the Web service using the
appserver startapp
command as follows:
appserver startapp SimpleRPC
This tells WebSphere to start the Web service associated with the enterprise application
SimpleRPC.
Creating the service client for SimpleRPC
Now that we have a service, we need a client. Creating a JAX-RPC client is very simple. It
requires just a few lines of code:
1. In the simpleRPC directory (%WSDK_HOME%\apps\simpleRPC), create a directory called
requester. This directory will house the client source.
2. In the requester directory, create a directory called src.
3. In the src directory, create a series of directories representing the package structure --
lpc.dvdonline.simplerpc.client.
4. Inside the package lpc\dvdonline\simplerpc\client directory, create a Java source file called
DVDOnlineStoreClient.java. Add the following code to that source file:
package lpc.dvdonline.simplerpc.client;
import lpc.dvdonline.simplerpc.server.*;
import lpc.dvdonline.simplerpc.server.*;
public class DVDOnlineStoreClient {
public static void main( String[] args ) throws Exception{
DVDOnlineStore_SEIService loc = new DVDOnlineStore_SEIServiceLocator();
DVDOnlineStore_SEI port = (DVDOnlineStore_SEI)loc.getDVDOnlineStore();
System.out.println( port.getDVD() );
} //end main()
} //end DVDOnlineStoreClient
Notice that the client creates a service. It uses an IBM specific type, a ServiceLocator, to
do this. From the service it accesses the port, that is, the interface of our Web service, and
then it invokes the
getDVD()
method. We'll see how to use the ServiceFactoy method of
getting a service in the next tutorial, "Creating a Web service from a Stateless Session
Bean."
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 19 of 36
5. The client needs the stubs, interface, and locator classes that were generated with
Bean2WebService. Copy the files and directories from the SimpleRPC\client-side directory
( %WSDK_HOME%\apps\simpleRPC\provider\src\SimpleRPC\client-side) to the
requester\src directory.
6. At this point you are ready to compile. Compile the above class as before with the
following JAR files under %WSDK_HOME%\appserver\lib on your classpath:
•
j2ee.jar
•
axis.jar
•
qname.jar
•
jaxrpc.jar
•
wsdl4j.jar
•
xerces.jar
•
commons-discovery.jar
•
saaj.jar
•
commons-logging-api.jar
At this point, because there are so many JAR files to manage, we suggest using a Java
IDE like the freely available
.
7. Run the client using the
java
command. Make sure you have the same JAR files on the
classpath that you used for the compile:
java -classpath ...
lpc.dvdonline.simplerpc.client.DVDOnlineStoreClient
8. If you are using the Eclipse IDE, just click the little "running man" icon on the toolbar.
If you see the response message of "Fight Club", then you have tested the service and it is
alive and working. Not too bad for an hour's work. You created, deployed, and started your
first Web service, then you wrote a client to invoke a method on the Web service.
Lab review
Let's review what you have done, and let's review what the Bean2WebService utility did for
you.
You created a Web service using a standard Java class. You did not define an interface and
create a binding or anything like that per se. The Bean2WebService tool took care of most of
the heavy lifting. Bean2WebService deployed your Web service as a J2EE Web application
bundled in a WAR file, bundled in an EAR file. You created a Web service client using a
static, pre-defined stub class.
Although you did not define an interface per se, the Bean2WebService created one for you
as follows:
package lpc.dvdonline.simplerpc.server;
public interface DVDOnlineStore_SEI extends java.rmi.Remote {
public java.lang.String getDVD() throws java.rmi.RemoteException;
}
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 20 of 36
Creating a Web service from a Java class
If you have done RMI development, this interface looks identical to the type of interface you
would have created for your RMI servant.
The Bean2WebService tools also generates a service class, and a stub class. The service
class implements the
javax.xml.rpc.Service
interface.
javax.xml.rpc.Service
is
a factory of the generated stub. You can also create
Call
objects and use dynamic proxies
with this interface, and we will cover these when we cover the dynamic client later in this
tutorial. The
Service
class file that gets generated is the
DVDOnlineStore_SEIServiceLocator.java file listed below:
/**
* DVDOnlineStore_SEIServiceLocator.java
*
* This file was auto-generated from WSDL
* by the Apache Axis WSDL2Java emitter.
*/
package lpc.dvdonline.simplerpc.server;
public class DVDOnlineStore_SEIServiceLocator
extends org.apache.axis.client.Service
implements lpc.dvdonline.simplerpc.server.DVDOnlineStore_SEIService {
// Use to get a proxy class for DVDOnlineStore
private final java.lang.String DVDOnlineStore_address
= "http://localhost:6080/SimpleRPC/services/DVDOnlineStore";
public java.lang.String getDVDOnlineStoreAddress() {
return DVDOnlineStore_address;
}
// The WSDD service name defaults to the port name.
private java.lang.String DVDOnlineStoreWSDDServiceName
= "DVDOnlineStore";
public java.lang.String getDVDOnlineStoreWSDDServiceName() {
return DVDOnlineStoreWSDDServiceName;
}
public void setDVDOnlineStoreWSDDServiceName(java.lang.String name) {
DVDOnlineStoreWSDDServiceName = name;
}
public lpc.dvdonline.simplerpc.server.DVDOnlineStore_SEI
getDVDOnlineStore() throws javax.xml.rpc.ServiceException {
java.net.URL endpoint;
try {
endpoint = new java.net.URL(DVDOnlineStore_address);
}
catch (java.net.MalformedURLException e) {
return null; // unlikely as URL was validated in WSDL2Java
}
return getDVDOnlineStore(endpoint);
}
public lpc.dvdonline.simplerpc.server.DVDOnlineStore_SEI
getDVDOnlineStore(java.net.URL portAddress)
throws javax.xml.rpc.ServiceException {
try {
lpc.dvdonline.simplerpc.server.DVDOnlineStoreSoapBindingStub _stub
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 21 of 36
= new lpc.dvdonline.simplerpc.server.DVDOnlineStoreSoapBindingStub(
portAddress, this);
_stub.setPortName(getDVDOnlineStoreWSDDServiceName());
return _stub;
}
catch (org.apache.axis.AxisFault e) {
return null;
}
}
/**
* For the given interface, get the stub implementation.
* If this service has no port for the given interface,
* then ServiceException is thrown.
*/
public java.rmi.Remote getPort(Class serviceEndpointInterface)
throws javax.xml.rpc.ServiceException {
try {
if
lpc.dvdonline.simplerpc.server.DVDOnlineStore_SEI.class.isAssignableFrom
(serviceEndpointInterface)) {
lpc.dvdonline.simplerpc.server.DVDOnlineStoreSoapBindingStub _stub =
new lpc.dvdonline.simplerpc.server.DVDOnlineStoreSoapBindingStub(
new java.net.URL(DVDOnlineStore_address), this);
_stub.setPortName(getDVDOnlineStoreWSDDServiceName());
return _stub;
}
}
catch (java.lang.Throwable t) {
throw new javax.xml.rpc.ServiceException(t);
}
throw new javax.xml.rpc.ServiceException(
"There is no stub implementation for the interface:
"
+ (serviceEndpointInterface == null ? "null" :
serviceEndpointInterface.getName()));
}
/**
* For the given interface, get the stub implementation.
* If this service has no port for the given interface,
* then ServiceException is thrown.
*/
public java.rmi.Remote getPort(javax.xml.namespace.QName portName,
Class serviceEndpointInterface)
throws javax.xml.rpc.ServiceException {
if (portName == null) {
return getPort(serviceEndpointInterface);
}
String inputPortName = portName.getLocalPart();
if ("DVDOnlineStore".equals(inputPortName)) {
return getDVDOnlineStore();
}
else
{
java.rmi.Remote _stub = getPort(serviceEndpointInterface);
((org.apache.axis.client.Stub) _stub).setPortName(portName);
return _stub;
}
}
public javax.xml.namespace.QName getServiceName() {
return new javax.xml.namespace.QName(
"http://server.simplerpc.dvdonline.lpc", "DVDOnlineStore_SEIService");
}
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 22 of 36
Creating a Web service from a Java class
private java.util.HashSet ports = null;
public java.util.Iterator getPorts() {
if (ports == null) {
ports = new java.util.HashSet();
ports.add(new javax.xml.namespace.QName("DVDOnlineStore"));
}
return ports.iterator();
}
}
The generated Stub class implements the DVDOnlineStore_SEI interface
(lpc.dvdonline.simplerpc.server.DVDOnlineStore_SEI interface). This is what the client uses
to invoke methods on our service's port object. It is listed as follows:
/**
* DVDOnlineStoreSoapBindingStub.java
*
* This file was auto-generated from WSDL
* by the Apache Axis WSDL2Java emitter.
*/
package lpc.dvdonline.simplerpc.server;
public class DVDOnlineStoreSoapBindingStub
extends org.apache.axis.client.Stub
implements lpc.dvdonline.simplerpc.server.DVDOnlineStore_SEI {
private java.util.Vector cachedSerClasses = new java.util.Vector();
private java.util.Vector cachedSerQNames = new java.util.Vector();
private java.util.Vector cachedSerFactories = new java.util.Vector();
private java.util.Vector cachedDeserFactories = new java.util.Vector();
public DVDOnlineStoreSoapBindingStub() throws org.apache.axis.AxisFault {
this(null);
}
public DVDOnlineStoreSoapBindingStub(
java.net.URL endpointURL, javax.xml.rpc.Service service)
throws org.apache.axis.AxisFault {
this(service);
super.cachedEndpoint = endpointURL;
}
public DVDOnlineStoreSoapBindingStub(javax.xml.rpc.Service service)
throws org.apache.axis.AxisFault {
if (service == null) {
super.service = new org.apache.axis.client.Service();
} else {
super.service = service;
}
}
private org.apache.axis.client.Call createCall()
throws java.rmi.RemoteException {
try {
org.apache.axis.client.Call _call =
(org.apache.axis.client.Call) super.service.createCall();
if (super.maintainSessionSet) {
_call.setMaintainSession(super.maintainSession);
}
if (super.cachedUsername != null) {
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 23 of 36
_call.setUsername(super.cachedUsername);
}
if (super.cachedPassword != null) {
_call.setPassword(super.cachedPassword);
}
if (super.cachedEndpoint != null) {
_call.setTargetEndpointAddress(super.cachedEndpoint);
}
if (super.cachedTimeout != null) {
_call.setTimeout(super.cachedTimeout);
}
if (super.cachedPortName != null) {
_call.setPortName(super.cachedPortName);
}
java.util.Enumeration keys = super.cachedProperties.keys();
while (keys.hasMoreElements()) {
java.lang.String key = (java.lang.String) keys.nextElement();
_call.setProperty(key, super.cachedProperties.get(key));
}
return _call;
}
catch (java.lang.Throwable t) {
throw new org.apache.axis.AxisFault(
"Failure trying to get the Call object", t);
}
}
public java.lang.String getDVD() throws java.rmi.RemoteException {
if (super.cachedEndpoint == null) {
throw new org.apache.axis.NoEndPointException();
}
org.apache.axis.client.Call _call = createCall();
_call.setReturnType(new javax.xml.namespace.QName(
"http://www.w3.org/2001/XMLSchema", "string"), java.lang.String.class);
_call.setReturnQName(new javax.xml.namespace.QName("", "getDVDReturn"));
_call.setUseSOAPAction(true);
_call.setSOAPActionURI("");
_call.setEncodingStyle(null);
_call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR,
Boolean.FALSE);
_call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS,
Boolean.FALSE);
_call.setOperationStyle("rpc");
_call.setOperationUse("literal");
_call.setOperationName(new javax.xml.namespace.QName(
"http://server.simplerpc.dvdonline.lpc", "getDVD"));
java.lang.Object _resp = _call.invoke(new java.lang.Object[] {});
if (_resp instanceof java.rmi.RemoteException) {
throw (java.rmi.RemoteException)_resp;
}
else {
try {
return (java.lang.String) _resp;
} catch (java.lang.Exception _exception) {
return (java.lang.String)
org.apache.axis.utils.JavaUtils.convert(_
resp, java.lang.String.class);
}
}
}
}
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 24 of 36
Creating a Web service from a Java class
Note the implementation of the
getDVD()
method. We will use a similar technique when we
create the dynamic client in an upcoming lab. The Bean2WebService also created a WSDL
file. We will leave the coverage of the WSDL file for the WSDL tutorial, "Describing Web
Services: WSDL."
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 25 of 36
Section 6. Lab 2: Exchanging complex SOAP objects
Lab overview
The purpose of this lab is to demonstrate the ability of IBM's WSDK to exchange complex
SOAP data types. Although passing Strings and simple arrays is a good way to get you
started with Web services, real-world applications typically require that client and service
exchange whole objects and similar complex data structures. Complex types are supported
by JAX-RPC and XML Schema.
Define a Java type to represent a DVD object
When SOAP was created, the idea was to provide a neutral mechanism for transporting
objects within a distributed and heterogeneous environment. That's where SOAP got its
name: Simple Object Access Protocol. To accomplish this, each side must have a native
object representation and then agree upon a neutral format to map with their native
representation. In our case, both client and server are Java code-based, so they will both use
the same native format, a Java class.
The
DVD
class is a basic Java bean with three fields: title (
String
), rank (
int
), and category
(
String
), along with the usual getters and setters.
1. Before creating the value object DVD, create a folder called complexRPC directly
underneath the %WSDK_HOME%\apps directory.
2. Inside the complexRPC directory, create a directory called shared. This value object is
going to be used by both the provider (server) and the requester (client).
3. In the shared directory, Create a directory called src.
4. In the src directory create a series of directories representing the package structure --
lpc.dvdonline.complexrpc.service.
5. Create a DVD.java file in the lpc/dvdonline/complexrpc/service package directory as
follows:
package lpc.dvdonline.complexrpc.service;
public class DVD {
private String title; // unique id (primary key)
private int rank;
private String category;
public DVD() {
title = "no title";
rank = 0;
category = "no category";
} //end DVD()
public DVD(String _title, int _rank, String _category) {
title = _title;
rank = _rank;
category = _category;
} //end DVD( String, int, String )
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 26 of 36
Creating a Web service from a Java class
public String getCategory() {
return category;
} //end getCategory()
public int getRank() {
return rank;
} //end getRank()
public String getTitle() {
return title;
} //end getTitle()
public void setCategory(String category) {
this.category = category;
} //end setCategory( String )
public void setRank(int rank) {
this.rank = rank;
} //end setRank( int )
public void setTitle(String title) {
this.title = title;
} //end setTitle( String )
} //end class DVD
Compile the class as you would any other Java class. From the src directory:
javac lpc\dvdonline\complexrpc\service\DVD.java
.
Building the service provider for ComplexRPC
In this section you are going to create a Web service that returns complex types. Perform the
following steps:
1. Inside the complexRPC directory, create a directory called provider.
2. In the provider directory, Create a directory called src.
3. In the src directory create a series of directories representing the package structure --
lpc.dvdonline.complexrpc.server.
4. Inside the package lpc\dvdonline\complex\server package directory, create a Java source
file called DVDOnlineStore.java. Add the following code to that source file:
package lpc.dvdonline.complexrpc.server;
import lpc.dvdonline.complexrpc.service.DVD;
public class DVDOnlineStore implements java.rmi.Remote {
public DVD getDVD() throws java.rmi.RemoteException {
return new DVD("Fight Club", 10, "Weird but good");
}//end getDVD()
}//end DVDOnlineStore
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 27 of 36
Notice how the above source is different than the last provider. The
getDVD()
method
returns an instance of the DVD value object class that we just created instead of a plain
old String.
5. Compile the above class, making sure that %WSDK_HOME%\appserver\libs\J2EE.jar is in
your classpath where %WSDK_HOME% is the directory where you installed the WSDK
version 5. You'll also need the root directory of the
DVD
class on your classpath. Navigate
to the src directory and use the standard
javac
command as follows:
javac -d . -classpath
%WSDK_HOME%\appserver\libs\J2EE.jar;..\..\shared\src
lpc\dvdonline\complexrpc\server\DVDOnlineStore.java
Packaging, deploying, and starting the service
This works exactly the same as it did in the previous lab. We will summarize the steps here,
but if you need more information, look at the previous lab.
1. Start the application server.
Start Server shortcut, or
appserver start
2. Run the Bean2WebService utility.
From the src directory run the following:
Bean2WebService -cp
.;%WSDK_HOME%\appserver\lib\j2ee.jar;..\..\shared\src -project
ComplexRPC -deploy lpc.dvdonline.complexrpc.server.DVDOnlineStore
3. Check your results.
appserver appstatus
4. Start the Web service.
appserver startapp ComplexRPC
Creating the service client for ComplexRPC
Now that we have a service, we need a client.
1. In the complexRPC directory (%WSDK_HOME%/apps/complexRPC), create a directory
called requester. This directory will house the client source.
2. In the requester directory, create a directory called src.
3. In the src directory create a series of directories representing the package structure --
lpc.dvdonline.complexrpc.client.
4. Inside the package lpc\dvdonline\complexrpc\client directory, create a Java source file
called DVDOnlineStoreClient.java. Add the following code to that source file:
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 28 of 36
Creating a Web service from a Java class
package lpc.dvdonline.complexrpc.client;
import lpc.dvdonline.complexrpc.server.*;
import lpc.dvdonline.complexrpc.service.*;
public class DVDOnlineStoreClient {
public static void main( String[] args ) throws Exception{
DVDOnlineStore_SEIService loc = new DVDOnlineStore_SEIServiceLocator();
DVDOnlineStore_SEI port = (DVDOnlineStore_SEI)loc.getDVDOnlineStore();
DVD dvd = port.getDVD();
System.out.println(dvd.getTitle());
}//end main()
}//end DVDOnlineStoreClient
Notice that just as before, the client creates a service. From the service it accesses the
port, that is, the interface of our Web service, and then it invokes the
getDVD()
method.
This time the
getDVD()
method returns a
DVD
object instead of a
String
object.
5. The client needs the stub, interface, and locator classes that were generated with
Bean2WebService. Copy the files and directories from the ComplexRPC\client-side
directory ( %WSDK_HOME%\apps\complexRPC\provider\src\ComplexRPC\client-side) to
the requester\src directory.
6. At this point you are ready to compile. Compile the above class as before with the
following JAR files under %WSDK_HOME%\appserver\lib on your classpath:
•
j2ee.jar
•
axis.jar
•
qname.jar
•
jaxrpc.jar
•
wsdl4j.jar
•
xerces.jar
•
commons-discovery.jar
•
saaj.jar
•
commons-logging-api.jar
Hopefully you are not doing this by hand! Remember the
.
7. Run the client with the
java
command.
If you see the response message of "Fight Club", congratulations!
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 29 of 36
Section 7. Lab 3: Dynamic Web service client
Lab purpose and overview
In a perfect world, you would always be both the service provider and service requester
developer. And, if you were not both the service provider and service requester developer,
the service provider developer would be nice and supply you a WSDL file. Then you could
take this WSDL file and generate client stubs. (Note: there is a whole tutorial on working with
WSDL files to generate provider and requester code. The Bean2WebService has hidden a
lot of details of WSDL.)
However, the world is nowhere near perfect. And, service providers can develop
SOAP-based services without WSDL files. Sad but true. So how do you invoke these
services anyway? You use dynamic SOAP invocation.
There are three JAX-RPC classes you need to worry about for dynamic invocation as follows:
1.
javax.xml.namespace.QName
2.
javax.xml.rpc.Call
3.
javax.xml.rpc.Service
Service
is a factory class for
Call
objects. We use the
Service
to create a
Call
object.
Then we pass the
Call
object its endpoint URL so it knows where the service is located,
and its operation name. The operation name is identified with a
QName
. A
QName
represents
an element name that is within a namespace.
Let's step through this and show the code.
1. Import the needed classes:
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.Service;
2. Create a
Service
factory object as follows:
Service service = (Service)
Class.forName("org.apache.axis.client.Service").newInstance();
3. Use the
Service
to create the
call
object:
Call call = (Call) service.createCall();
4. Set the URL location of the
Service
:
String endpoint =
"http://localhost:6080/SimpleRPC/services/DVDOnlineStore";
call.setTargetEndpointAddress(endpoint);
5. Invoke the
call
object:
Object [] arguments = new Object[0];
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 30 of 36
Creating a Web service from a Java class
String dvdName = (String) call.invoke(arguments);
Creating the dynamic service client for SimpleRPC
Now that you get the idea of how to do it, let's actually write a dynamic client for the
SimpleRPC lab.
1. Inside the package lpc\dvdonline\simplerpc\client directory, create a Java source file called
DynamicDVDOnlineStoreClient.java. Add the following code to that source file:
package lpc.dvdonline.simplerpc.client;
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.Service;
/**
* @author Rick Hightower
*
*/
public class DynamicDVDOnlineStoreClient {
public static void main( String[] args ) throws Exception{
String endpoint =
"http://localhost:6080/SimpleRPC/services/DVDOnlineStore";
String namespaceURI = "http://server.simplerpc.dvdonline.lpc";
Service service = (Service)
Class.forName("org.apache.axis.client.Service").newInstance();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(endpoint);
call.setOperationName(new QName(namespaceURI, "getDVD"));
Object [] arguments = new Object[0];
String dvdName = (String) call.invoke(arguments);
System.out.println("Dynamic " + dvdName);
} //end main()
} // end DynamicDVDOnlineStoreClient
2. Notice that the client does not need the stubs, interface, and locator classes that were
generated with Bean2WebService.
3. At this point you are ready to compile. Compile the above class as before with the
following JAR files under %WSDK_HOME%\appserver\lib on your classpath:
•
j2ee.jar
•
axis.jar
•
qname.jar
•
jaxrpc.jar
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 31 of 36
•
wsdl4j.jar
•
xerces.jar
•
commons-discovery.jar
•
saaj.jar
•
commons-logging-api.jar
4. Run the client with the
java
command. Make sure you have the same JAR files on the
classpath that you used for the compile.
If you see the response message of "Dynamic Fight Club", then you have earned your Web
services Kung Fu brown belt!
What about dynamic clients with complex types?
Fine, you say. Good and well, you can invoke Web services that return simple types and
have simple arguments, but what would happen if the Web service had complex types like
our complex example? Simply put: our dynamic example above would break. So far we have
managed to stick fairly close to doing dynamic things in a somewhat vendor-neutral fashion.
Once you start working with complex types, using the dynamic mechanism becomes more
vendor specific. Future versions of the JAX-RPC API will fix this.
That said, there are only three lines of vendor-specific code needed to register the serializers
and deserializers. With the IBM WSDK, you have to register custom serializer and
deserializers with the
Call
object and tell the
Call
object what its return type is. It is really
quite simple. For completeness, we will create a dynamic client for the complex example.
Creating the dynamic service client for ComplexRPC
1. Inside the package lpc\dvdonline\complexrpc\client directory, create a Java source file
called DynamicDVDOnlineStoreClient.java. Add the following code to that source file:
package lpc.dvdonline.complexrpc.client;
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.Service;
import lpc.dvdonline.complexrpc.service.DVD;
import org.apache.axis.encoding.ser.*;
/**
* @author Rick Hightower
*
*/
public class DynamicDVDOnlineStoreClient {
private static void registerDVDClassWithCallObject(Call call){
QName qName = new javax.xml.namespace.QName
("http://service.complexrpc.dvdonline.lpc", "DVD");
Class clazz = DVD.class;
call.setReturnType(new javax.xml.namespace.QName
("http://service.complexrpc.dvdonline.lpc", "DVD"), DVD.class);
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 32 of 36
Creating a Web service from a Java class
/* These three lines Axis specific */
Class beansf = BeanSerializerFactory.class;
Class beandf = BeanDeserializerFactory.class;
((org.apache.axis.client.Call)call).registerTypeMapping(clazz,
qName, beansf, beandf, false);
}
public static void main( String[] args ) throws Exception{
String endpoint =
"http://localhost:6080/ComplexRPC/services/DVDOnlineStore";
String namespaceURI = "http://server.complexrpc.dvdonline.lpc";
Service service = (Service)
Class.forName("org.apache.axis.client.Service").newInstance();
Call call = (Call) service.createCall();
registerDVDClassWithCallObject(call);
call.setTargetEndpointAddress(endpoint);
call.setOperationName(new QName(namespaceURI, "getDVD"));
Object [] arguments = new Object[0];
DVD dvd = (DVD) call.invoke(arguments);
System.out.println("Dynamic DVD Title " + dvd.getTitle());
} //end main()
} //end DynamicDVDOnlineStoreClient
Notice that, just as before, the client creates a service. From the service it creates the
Call
object and registers the
DVD
class with the
Call
object as well as the custom
serializers and deserializers. Then it functions as before. The only difference is that the
call.invoke
method now returns a
DVD
object instead of a plain old
String
.
2. At this point you are ready to compile. Compile the above class as before with the
following JAR files under %WSDK_HOME%\appserver\lib on your classpath:
•
j2ee.jar
•
axis.jar
•
qname.jar
•
jaxrpc.jar
•
wsdl4j.jar
•
xerces.jar
•
commons-discovery.jar
•
saaj.jar
•
commons-logging-api.jar
3. Run the client with the
java
command.
If you see the response message of "Dynamic DVD Title Fight Club", congratulations! You
are a Web services Kung Fu master!
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 33 of 36
Exercise for the industrious
Do you remember in the first tutorial ("Introduction to Web services and the WSDK") how we
used the TCPMonitor? Setup the TCPMonitor and watch the HTTP/SOAP conversation
between the provider and requester in both the simple and complex RPC examples.
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 34 of 36
Creating a Web service from a Java class
Section 8. Tutorial wrapup and resources
Tutorial review
In this tutorial, we've done the following things:
•
Learned about JSR-101/JAX-RPC
•
Learned how to use the WSDK tools to create RPC-style Web services
•
Created, deployed, and consumed a Web service using simple types
•
Created, deployed, and consumed a Web service using complex types
•
Created dynamic clients that used both simple and complex types
You now have a good start on actually developing with Web services. We've also shown that
it is quite possible to develop with Web services using the specifications and tools available
today. Some businesses are already using these kinds of Web services for integrating their
systems enterprise-wide and between companies. Web services are starting to become a
key technology in Enterprise Application Integration (EAI).
In later tutorials, we will explore more complex topics, such as integrating Web services with
EJB technology, generating Web services code from WSDL, and much more. We hope that
you had as much pleasure in reading this tutorial as we did in writing it.
Resources
Code:
•
Download all the source code in the
.
Specifications:
•
•
JSR-109 -- Implementing Enterprise Web services
•
•
•
•
Tools:
•
developerWorks Speed-start Web services
•
•
IBM WebSphere Developer Domain
•
•
•
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Creating a Web service from a Java class
Page 35 of 36
Resources:
•
developerWorks Open source projects
•
developerWorks Web services zone
•
java.sun.com: The source for Java technology
•
•
The Java Web Services Tutorial: JAX-RPC
•
•
Web Services Interoperability Organization (WS-I)
•
Web Services Security Web site
•
Feedback
Please send us your feedback on this tutorial.
Colophon
This tutorial was written entirely in XML, using the developerWorks Toot-O-Matic tutorial
generator. The open source Toot-O-Matic tool is an XSLT stylesheet and several XSLT
extension functions that convert an XML file into a number of HTML pages, a zip file, JPEG
heading graphics, and two PDF files. Our ability to generate multiple text and binary formats
from a single source file illustrates the power and flexibility of XML. (It also saves our
production team a great deal of time and effort.)
You can get the source code for the Toot-O-Matic at
www6.software.ibm.com/dl/devworks/dw-tootomatic-p
. The tutorial
demonstrates how to use the Toot-O-Matic to create your own tutorials.
developerWorks also hosts a forum devoted to the Toot-O-Matic; it's available at
www-105.ibm.com/developerworks/xml_df.nsf/AllViewTemplate?OpenForm&RestrictToCategory=11
.
We'd love to know what you think about the tool.
ibm.com/developerWorks
Presented by developerWorks, your source for great tutorials
Page 36 of 36
Creating a Web service from a Java class