Tải bản đầy đủ (.pdf) (439 trang)

Building web services with java making sense of xml, soap, wsdl, and uddi (second edition) part 2

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (8.91 MB, 439 trang )

II
Enterprise Web Services
7

Web Services and J2EE

8

Web Services and Stateful Resources

9

Securing Web Services

10

Web Services Reliable Messaging

11

Web Services Transactions

12

Orchestrating Web Services


7
Web Services and J2EE

T



HIS CHAPTER INTRODUCES THE CONCEPTS of using SOAP,WSDL, and the Web services stack with Java 2 Enterprise Edition (J2EE) g. Although a single chapter can’t do
justice to a wide-ranging development platform, we’ll show you how to enable Enterprise
JavaBean g components as Web services using Axis and the JSR109 g JCP proposal.
Continuing our example scenario, the SkatesTown technical team has been working
in Java for a while and recently has been looking at moving some of the Java applications
that run on their server into the J2EE platform.They’ve heard that it’s secure,
transactional, managed, scalable, and robust—all the things they want for their business
applications. But they’re also interested in Web services, and they want to be able to create services easily. So, they’ve decided to build a sample application called SkatesEJB,
which will be a pilot project to determine the value in using J2EE to implement their
Web services.

J2EE Overview
Java 2 Enterprise Edition (J2EE) is the platform for building enterprise applications in
Java. J2EE standardizes the services, programming model, and deployment for applications so that developers can build solutions that can be used on a variety of application
servers. J2EE has a number of application models:
Thin-client/browser-based applications use servlets and JavaServer Pages g (JSPs).
Thick/managed application clients use RMI-IIOP g to communicate with
server-based Enterprise JavaBeans (EJB) components.
Messaging applications use the Java Message Service to act on messages in queues
or from subscriptions.
n
n

n

To this list we can now add service-based applications, which offer services over
SOAP/HTTP to clients.
J2EE provides a framework that supports high quality of service (QoS). In other
words, J2EE lets you build transactional, secure, reliable applications that are available



348

Chapter 7 Web Services and J2EE

across a cluster of highly available servers. A J2EE application server provides a wide variety of capabilities including the following:
Workload and performance management—Thread management, pooling, caching, and
cluster support
n

n

n

n

n

Security management—Password and certificate management and validation, authentication, and access control
Resource management—Access to relational databases, transactional management systems, connectors to Enterprise Resource Planning (ERP) systems, and messaging
systems
Transaction management—Two-phase commit support, transactional access to databases, and distributed transactions
Management, configuration, and administration—Deployment, configuration, and
administration tools

These services are provided through the concept of a container.

Containers
A container is a logical entity in a J2EE server. Containers are entities that have contracts

with the components that are deployed into a server—but they also help you understand
the way a J2EE system works. Components are deployed to a container, and the container manages the execution of those components as needed.The container provides isolation by intercepting calls to the EJBs, allowing the container to manage aspects such as
threads, security, and transactions between components.The container also provides a
useful abstraction between components and the resources they use.
For example, when one component uses a database, the programmer uses a resource reference g (resource ref) to link to the database.Then the deployment engineer can configure the actual database that maps to the reference. So, the code that is written and
compiled isn’t hard-coded to a specific database.
This approach is also used for JMS destinations, URLs and URIs, and other EJB
components in the same or different applications. Later in the chapter, you’ll see an
example of an ejb-ref g that virtualizes access to another EJB.

Enterprise JavaBeans
The core of J2EE is the EJB component.This is the programming model for writing and
deploying business logic into an application server. EJBs provide a component model for
creating business applications. EJB components are mainly focused on aspects such business logic, as well as database and legacy server access, transactions, security, and threading—in other words, how you build core business services in a Java environment.
EJBs initially look complex because they were designed to layer over ordinary Java.
For each component, there are multiple .java files. Ideally, the user has an Integrated
Development Environment (IDE) that shows each component as a whole as well as the


J2EE Overview

individual class files for that component. However, in the examples later in this book, we
simply use a text editor and basic tools for portability.
The EJB component model allows you to structure the business logic into discrete
connected components. EJB applications are loosely coupled, with well-defined interfaces.
EJBs come in a variety of styles:
n

n


n

Session beans g are business logic components that are instantiated on behalf of a
user and last no longer than the time the client program remains active and running (a session).
Entity beans g are components that are mapped into an underlying database or
persistent store (for example, a bank account, purchase order, telephone number, or
email address). Each instance must have a unique key under which it is stored and
retrieved.
Message-driven beans (MDBs) g are executed in response to a message at the server, usually a one-way, asynchronous JMS g message, but also including messages
from other systems such as SAP R/3 or PeopleSoft coming through a connector.

There is another distinction: between local and remote EJBs. Local EJBs can only be
called from within the same container, whereas remote EJBs are callable across a network
over distributed networking protocols (such as RMI-IIOP).
An application can be thought of as having distinct parts—for example:
The part that deals with the long-term storage of data in a database or other persistent backend (local entity beans)
The part that provides business logic (stateless local session beans)
The part that provides the interface with thick clients or a graphical interface layer
(stateless or stateful remote session beans)
The graphical Web interface (servlets and JSPs)
n

n
n

n
n

The part that deals with messaging—sending and receiving messages from other
systems (message-driven beans)


As you can see, the J2EE application model is a component model that provides the
right component types to support solid business applications.
EJB Lifecycle
Another aspect of J2EE that’s very important to Web services is the lifecycle of an EJB.
Components have well-defined lifecycles—they’re instantiated, persisted, and destroyed.
EJBs define a “home” factory for creating and managing the lifecycle of components.
EJBs can be divided into those with no real lifecycle and those with a lifecycle.
Note
The Open Grid Services Infrastructure (OGSI) offers a model of services that have lifecycles. This is a point of
debate around Service-Oriented Architecture—whether services have lifecycles like objects or whether
they’re stateless.

349


350

Chapter 7 Web Services and J2EE

Stateless session beans are session beans with no real lifecycle—the container instantiates a
pool of these as needed. Although there are multiple instances of the component, each
instance is interchangeable with any other, because they have no state that differs from
method call to method call.
Message-driven beans (MDBs) have no lifecycle either.They are instantiated and
pooled by the container—so they are always available.
Stateful session beans (SFSBs) are explicitly created by an application, with parameters
in the create() method (part of the home interface).The instance of an SFSB contains
state information specific to that client, and therefore it must either be explicitly
destroyed or timed out by the container (otherwise the number would grow until the

system’s capacity was used up).
Entity beans are stateful and have attributes that are stored in a database, file system, or
other persistent storage.They must be either created or found using a key. Because
they’re kept in a persistent datastore, the objects have a very extended lifetime—unlike
SFSBs, which last as long as the client code is running, these object instances remain
available until they’re explicitly deleted, surviving reboots, crashes, system migrations, and
so on. Another difference with SFSBs is that many clients can talk to one entity bean
instance.
The lifecycle-free model of services matches the model of stateless session beans and
MDBs. In fact, a common design pattern in EJB programming involves all distributed
interaction with the EJB application taking place through a faỗade of stateless session
beans and MDBs.This model most closely fits today’s services infrastructure.
Initiatives such as WS-Addressing ( />library/specification/ws-add/) and the WS-Resource Framework (WSRF;
allow stateful components to be addressed
as services.There are ways of doing it without these technologies (such as adding a key
to the end of the address URL), but they aren’t standardized. Apache Axis has recently
added support for WS-Addressing, but it isn’t supported in Apache Axis or in the J2EE
specification at the time of this writing.
Note
Apache SOAP supports this approach. See />
As you’ll see when we dive deeper into J2EE support for Web services, the only supported components that can be accessed as Web services are servlets, stateless session
beans, and MDBs. For more information about stateful services, see Chapter 8, “Web
Services and Stateful Resources.”

Roles: Development, Assembly, and Deployment
One of the most useful aspects of J2EE is the way the architecture was designed from
the start with ordinary people in mind. Early Web systems were often created from many
different technologies, so the developer had to be good at programming in multiple



J2EE Overview

languages and systems as well as understand the network, the database connections, system administration, and so on. For example, many of the early dynamic Web technologies mixed HTML with the programming language in a single file.This meant that a
graphic designer couldn’t modify the look and feel without risking breaking the logic—
with the result the programmer frequently did the layout and HTML/Web design, or
spent valuable time cutting and pasting HTML into their code.
The J2EE model clearly separates roles such as Web programmer, business logic programmer, deployment engineer, and administrator.To achieve this separation, there are
clear contracts between the components and the infrastructure. For example, JSPs allow
the HTML and page design to be separate from the business logic.
There are two important roles: the assembler and the deployment engineer. Both are
like systems integrators. Like a brick layer, the assembler pulls together a set of components to create an application.Then the deployment engineer comes and wires and connects everything, like an electrician and plumber rolled into one.The mortar, solder, and
cabling that keep it all together are called deployment descriptors.
Deployment descriptors (DDs) are XML files that capture information about components and applications.They help resolve aspects left undefined by the programmer, such
as resolving references, setting policies, and linking to other components.
The following snippet shows a sample DD for an EJB:
<?xml version=”1.0”?>
<ejb-jar>
<description>Simple Application</description>
<display-name>Simple</display-name>
<enterprise-beans>
<session>
<ejb-name>StockQuote</ejb-name>
<home>com.skatestown.StockQHome</home>
<remote>com.skatestown.StockQ</remote>
<ejb-class>
com.skatestown.StockQHome
</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
</session>

</enterprise-beans>
</ejb-jar>

As you’ll see later, the same approach has been applied to the Web services support in
J2EE 1.4, where a new DD—webservices.xml—has been added.This file is effectively
the Java Standards version of the Axis WSDD file.

Benefits of Using Web Services with J2EE
J2EE is a high-quality, reliable, secure infrastructure for building complex Web and business applications.Web services started more simply with no inherent security, reliability,

351


352

Chapter 7 Web Services and J2EE

or transactions, but these are now being added using the open and flexible model that
SOAP and Web services offer.
Many businesses are using Web services with J2EE to provide simple interoperable
access to existing J2EE applications—for example, creating a C/C++/C# or VB.NET
client to an EJB application. Before SOAP and Web services, this was possible but very
complex. J2EE uses a distributed object model called RMI-IIOP, which bridges the Java
object model and the CORBA (IIOP) protocol. Accessing J2EE components from outside Java used to require either bridge technology or complicated logic to access the
components using IIOP from C or C++.This was typically a painful process. SOAP and
Web services make this scenario much more appealing, and a number of companies are
using the SOAP approach in their systems today.
Why use J2EE with Web services? In other words, why would you write a J2EE
application and EJBs if you could simply deploy Java classes into an Axis server to create
Web services? The answer, as usual, depends on the individual circumstances. Many small

applications will work fine with the Java Axis approach. As the complexity and requirements on the application scale up, having a managed J2EE environment in which to run
components becomes more appropriate. In particular, the benefits increase as you start to
connect to databases, messaging systems, and other enterprise systems.
Security
The first benefit that a J2EE application server brings is security. Because the individual
methods (operations) of an EJB can be secured, and because J2EE has end-to-end security, you can use either HTTPS or WS-Security to authenticate users and then offer
them services and/or operations with fine-grained access control. For example, a single
service may have bid and cancel operations, and a J2EE application server can be
configured with one group of ordinary users who can bid, and then another group of
superusers who can cancel. Because security in J2EE is tightly integrated into the Java
runtime, these security models extend to the Web services space, and so the access controls are applied to incoming SOAP requests as well, based on the configuration and
administration of the EJBs. (For more details, see Chapter 9, “Securing Web Services.”)
Transaction Control Across Distributed Resources
The second benefit a J2EE application server offers is transaction control across distributed resources. Even if you aren’t using WS-AtomicTransaction and WS-Coordination
(see Chapter 11, “Web Services Transactions”), you may wish to ensure that the backend
resources you’re communicating with are kept in sync with each other and are transactional. For example, you may wish to have a database log of Web service transactions
held in an Oracle or DB2 RDB and then use a JMS system to send messages internally
to a legacy system.The J2EE server can make the database log entry and send the message in the same unit of work.That way, even if the HTTP connection fails and the
SOAP response message sent to the client fails, your server has a log of what happened.
Although it doesn’t offer full end-to-end transactionality, this type of architecture has


J2EE Overview

been used extensively in Web-based systems to provide a higher level of robustness at the
application level.
Container Managed Persistence
J2EE offers both a programming model for building business applications—including the
tools and technology to map your objects into databases (entity beans)—and a reliable,
scalable infrastructure for running those applications. As soon as the application moves

beyond the simplicity of a sample or first proof of concept, users find that the learning
curve and extra complexity of a J2EE solution is repaid in the savings in time and effort
that the model offers.
For example, in our sample application, the J2EE application server will automatically
save the state of the objects we create using a feature called Container Managed Persistence
(CMP).This means that instead of having to write database logic and SQL statements,
we can write fairly straightforward Java objects and have the container generate the SQL
and take care of all the database reads, writes, and updates.This approach makes it quick
and easy to build a Web service application with a database at its heart. And, this support
is independent of which database server is used.

J2EE Versions
A word about versions: While J2EE 1.4 has just been released, J2EE 1.3 is still the more
commonly used version in real systems at the time of this writing. J2EE 1.4 includes significant Web services support, especially the standards JAX-RPC, JAX-R, and JSR 109
(“Implementing Enterprise Web Services”), as well as improvements specifically targeted
at producing WS-I Basic Profile g compliance ( />2003-08/BasicProfile-1.0a.html).
As a result, every J2EE application server will support the following:
A UDDI registry
Calling out to external Web services through JAX-RPC
Hosting Web services using EJBs and servlets
Calling out to UDDI servers
n
n
n
n

The rest of this chapter is split into three parts. First, we create the EJBs that form the
core of the application.This isn’t a full tutorial on EJBs, but just a simple EJB application
that allows SkatesTown to get going.
Next, we investigate using Web services with an existing J2EE server by using the

Apache Axis toolkit. In this section, we assume that there is a running J2EE server such
as BEA WebLogic, JBOSS, or IBM WebSphere, and we look at using the Apache Axis
framework to connect to EJBs.We’re doing this because the SkatesTown developers are
familiar with Axis and would like to understand how EJBs fit into the model they
already have; and although this is more difficult than the approach in the last part of the
chapter, not all application servers support that approach yet.
Finally, we look at how this model is simplified and updated when we utilize new
support from J2EE 1.4 to deploy a service directly into an enabled J2EE container.This

353




356

Chapter 7 Web Services and J2EE

Listing 7.1 Continued
public void ejbActivate() {

}

public void ejbPassivate() {}
public void ejbRemove() {}
public void ejbLoad() {}
public void ejbStore() {}
public javax.ejb.EntityContext getEntityContext() {
return entityContext;
}

public void
setEntityContext(javax.ejb.EntityContext entityContext) {
this.entityContext = entityContext;
}
public void unsetEntityContext() {
}
public String
ejbCreate(String pc) throws javax.ejb.CreateException {
this.setProductCode(pc);
this.setDescription(null);
this.setPrice(0.0D);
return null;
}
public void ejbPostCreate(String pc) {}
public abstract void
setProductCode(java.lang.String productCode);
public abstract java.lang.String getProductCode();
public abstract void
setDescription(java.lang.String Description);
public abstract java.lang.String getDescription();
public abstract void setPrice(double Price);
public abstract double getPrice();
}

If you aren’t an EJB programmer, you’re probably wondering at this point—where’s the
actual code? Although this code is effectively performing database lookups and inserts,


Using EJBs from Axis


you might expect that it would include SQL or other database query statements.There is
no database code because the J2EE application server (and the deployment tools that
ship with it) uses the DD and the interface to generate and run the code that implements the database logic.This CMP means the EJB container will manage the mapping
of the properties of the entity bean component into the fields of the database table.
There are different possible mappings:
n
n

n

Bottom-up—The objects are created from a database schema.
Meet-in-the-middle—A set of existing objects is mapped to an existing database
schema.
Top-down—The database tables are created from the object definitions.

In this case, we’ll use top-down to automatically create a table in which to store our
data.
Of equal importance to the classes that make up the EJB is the DD for the bean:
Container</persistence-type>

java.lang.String
</prim-key-class>
productCode</primkey-field>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>
Skates
</abstract-schema-name>
<cmp-field id=”PRICE”>
<field-name>price</field-name>
</cmp-field>

<cmp-field id=”DESC”>
<field-name>description</field-name>
</cmp-field>
<cmp-field id=”PRODCODE”>
<field-name>productCode</field-name>
</cmp-field>

As you’ll see later, the DD will be packaged together with the code into a JAR file,
which the application server will use to configure the component and code.
In this fragment, the first tag, persistence-type Container, says that the programmer will delegate the storage of the object instances to the container.The other type,
Bean Managed, requires the programmer to write logic to store the instance data in
some form of database.The EJB 2.0 specification updated the object to relational mapping style. Generally speaking, new projects should use the new 2.x CMP version as
defined by the <cmp-version> tag.
Each entity bean must specify a primary (or unique) key by which instances will be
known.The rest of the tags identify database names for the schema and the columns of
data.

357


358

Chapter 7 Web Services and J2EE

The session bean won’t have much more business logic in it, but it forms the place
where the service interface is mapped into the data stored in the database.

The Session Bean
The session bean has similar interface and implementation classes (see Listings 7.2
and 7.3).

Listing 7.2 SkatesProducts.java Session Bean Interface
public interface SkatesProducts extends javax.ejb.EJBObject {
public void addProduct(Product prod)
throws java.rmi.RemoteException;
public Product viewProduct(String prodcode)
throws java.rmi.RemoteException;
}

Listing 7.3 SkatesProductsBean.java Session Bean Implementation
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class SkatesProductsBean implements javax.ejb.SessionBean {
private javax.ejb.SessionContext mySessionCtx;
public javax.ejb.SessionContext getSessionContext() {
return mySessionCtx;
}
public void setSessionContext(javax.ejb.SessionContext ctx) {
mySessionCtx = ctx;
}
public void ejbCreate() throws javax.ejb.CreateException {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void ejbRemove() {}
public void addProduct(Product prod) {
try {
InitialContext ic = new InitialContext();
SkatesEntityLocalHome selh =
(SkatesEntityLocalHome)

ic.lookup(“java:comp/env/skateEnt”);
SkatesEntityLocal skent =
selh.create(prod.getProductCode());
skent.setDescription(prod.getDescription());
skent.setPrice(prod.getPrice());
} catch (NamingException ne) { // handle naming


Using EJBs from Axis

Listing 7.3 Continued
} catch (CreateException ce) { // handle create
}
}
// viewProduct goes here
}

Because the entity is simply a view on the persistence layer, it utilizes the underlying
semantics of a data element (create, read, update, delete).The session bean has the interface we wish to offer to the service requestor.We want to expose two “verbs” add and
view to the service requestor. Because the service interface we’re designing is stateless, we
need to map one (or more) of the parameters of the service request into the unique primary key the entity bean needs.
The implementation code shows some standard code—that is, it’s the same in most
EJBs.The ejbXXXXXX() methods, such as ejbCreate(), let you override methods that
are called by the container during the component’s event lifecycle. A more intelligently
designed bean would get a reference to the entity at component creation time, reuse it,
and therefore be more efficient. However, for this simple example it’s easier to get the
reference as needed.
In the addProduct() method shown, the logic gets a reference to the entity bean
using a local ejb-ref (local name for the entity bean) “java:comp/env/skateEnt”.The
“java:comp/env/” piece is predefined (it’s the J2EE way of saying environment).

“skateEnt” is a name we chose to identify the entity bean.This reference is then
defined in the DD to point to the real internal name of the entity bean.This capability
allows EJBs to be wired together, so a different entity bean (perhaps with a different persistence method) that implemented the same interface contract could be used without
recoding our session bean.
The code then calls the create() method on the entity to create a new product
instance, using the product code as the primary key. At this point, if there is already a
product in the database that has the same key, a createException will be thrown, which
will cause a fault in the Web service response.
There is similar code in the viewProduct() method shown here:
public Product viewProduct(String prodcode) {
Product prod = new ProductImpl();
try {
InitialContext ic = new InitialContext();
SkatesEntityHome home =
(SkatesEntityHome)
ic.lookup(“java:comp/env/skatesEntity”);
SkatesEntity skent =
home.findByPrimaryKey(prodcode);
prod.setProductCode(prodcode);
prod.setPrice(skent.getPrice());

359


360

Chapter 7 Web Services and J2EE

prod.setDescription(skent.getDescription());
}

catch (NamingException ne) { /* deal with exc */}
catch (FinderException fe) { /* deal with exc */}
return prod;
}

This code looks up the existing product instance and then returns the information as a
new Product object.

The Deployment Unit
Once the EJBs are written, you should deploy and test them before attempting to Web
service–enable them.Typically, the EJBs might already exist. In some circumstances, the
EJBs may not offer the right service interface, in which case a layer of stateless session
beans can be implemented to offer a clean interface that can then be Web service
enabled.The EJBs are packaged in an EJB JAR, which is then packaged in an Enterprise
Application aRchive (EAR file) g.
The EJBs must have appropriate XML DDs.The tags containing the deployment
information for each bean are shown in the following snippets. Here’s the DD fragment
for the entity bean:
<entity id=”SkatesEntity”>
<ejb-name>SkatesEntity</ejb-name>
<local-home>
com.skatestown.ejb.SkatesEntityLocalHome
</local-home>
<local>com.skatestown.ejb.SkatesEntityLocal</local>
<ejb-class>
com.skatestown.ejb.SkatesEntityBean
</ejb-class>
Container</persistence-type>
java.lang.String</prim-key-class>
<reentrant>False</reentrant>

<cmp-version>2.x</cmp-version>
<abstract-schema-name>SKATES</abstract-schema-name>
<cmp-field id=”pc”>
<field-name>productCode</field-name>
</cmp-field>
<cmp-field id=”desc”>
<field-name>description</field-name>
</cmp-field>
<cmp-field id=”prc”>
<field-name>price</field-name>
</cmp-field>
productCode</primkey-field>
</entity>


Using EJBs from Axis

And here’s the session bean fragment from the DD:
<session id=”SkatesService”>
<ejb-name>SkatesService</ejb-name>
<home>com.skatestown.ejb.SkatesServiceHome</home>
<remote>com.skatestown.ejb.SkatesService</remote>
<ejb-class>
com.skatestown.ejb.SkatesServiceBean
</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-local-ref id=”entref”>
<description>
Reference to SkatesEntity

</description>
<ejb-ref-name>skateEnt</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<local-home>
com.skatestown.ejb.SkatesEntityLocalHome
</local-home>
<local>com.skatestown.ejb.SkatesEntityLocal</local>
<ejb-link>SkatesEntity</ejb-link>
</ejb-local-ref>
</session>

As you’ll see from looking at the session bean DD, it includes a reference from the session bean to the entity bean.This is the point at which the “java:comp/env/skateEnt”
is defined.
The EJBs are now packaged into a JAR file together with the DD.The JAR contents
are as follows:
>jar tf skatesejb.jar
META-INF/ejb-jar.xml
com/skatestown/ejb/Product.class
com/skatestown/ejb/SkatesEntityBean.class
com/skatestown/ejb/SkatesEntityLocal.class
com/skatestown/ejb/SkatesEntityLocalHome.class
com/skatestown/ejb/SkatesService.class
com/skatestown/ejb/SkatesServiceBean.class
com/skatestown/ejb/SkatesServiceHome.class
META-INF/MANIFEST.MF

Exposing the EJBs via Axis
This EJB JAR can now be packaged together with Axis into an EAR application.Then
the whole can be deployed and the resulting application will let you access these EJBs
using SOAP/HTTP via Axis.


361


362

Chapter 7 Web Services and J2EE

The first task is to package the Axis Web application as a WAR file:
cd axis11\webapps
<java_home>\bin\jar cf axis.war *.*

Doing so creates a Web Application aRchive (WAR) file containing the Axis code.
The next step is to create an application DD that packages Axis.WAR and the
SkatesEJB.jar together into a single application, as shown here:
<?xml version=”1.0” encoding=”UTF-8”?>
➥ “-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN”
➥ “ /><application id=”SkatesTownEJBWS”>
<display-name>Skates</display-name>
<module id=”EjbModule_skates”>
<ejb>skatesejb.jar</ejb>
</module>
<module id=”WebModule_Axis”>
<web>
<web-uri>axis.war</web-uri>
<context-root>axis</context-root>
</web>
</module>
</application>


Usually you’d use a tool from the application server to do this and package the resulting
EAR file.The EAR file now contains the following:
n

skates.ear

n

axis.war

n

skatesejb.jar

n

META-INF/MANIFEST.MF

n

META-INF/application.xml

At this point we move away from pure interoperable J2EE and into the realm of a specific application server.The deployment tooling will augment skates.ear with serverspecific files. For example,WebSphere Application Server will generate a number of
additional classes and XML files that bind the EJBs we’ve written into the container. For
the examples in this book, we used the latest available WebSphere Application Server—
version 5.1, which is available for trial download on the Web (http://www-106.
ibm.com/developerworks/websphere/downloads/WASsupport.html).
WebSphere allows you to do this outside the runtime using the application assembly
tool, and also from the administration console. Other application servers have appropriate

methods (for example, BEA WebLogic server has an ejbdeploy tool).


Using EJBs from Axis

WebSphere Deployment Process
In order to deploy this as an EJB application, you need to go through a server-specific
deployment process that configures the application to run on a given server. As an example, we’ll show you how to deploy this EAR file into WebSphere Application Server.
However, the sample code is pure J2EE and so will deploy in any EJB2.0 server.
The process followed in this book is simple; we use command-line tools and the Web
console. However, as of this version of WebSphere, a new tool called the Application
Server Toolkit (ASTK) is available, which makes the procedure considerably easier.
If you have a different J2EE application server, then follow the guidelines appropriate
to that server.The deployment options should be standard and easily managed. For more
information, you may wish to see the settings that were configured in WebSphere to
deploy the application.
A Simple View of the Deployment Process
The next stages may seem complicated, so here’s a heads-up of what we’re about to do. You can think of
this process as wiring everything together:
1. Create a database.
2. Wire that to your application server.
3. Wire the entity bean to the database.
4. Wire the session bean to the entity bean.
5. Switch to Axis and create a WSDL file.
6. Wire the Axis service to the session bean.
Once you’ve completed these steps, everything should work!

In order to deploy into WebSphere, the Axis application must be modified to be a
Servlet 2.3 application (the default was 2.2). Doing so involves changing the !DOCTYPE
line of the web.xml file as follows:

➥ “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN”
➥” />
This is the only change required to convert it into a Servlet 2.3 Web application.

EJB Deployment
The major item that’s completely server specific for this application is the database that
backs up the CMP entity bean. In order to enable it, you need to configure a new database in your database server and create a new datasource in your application server to
manage connections to it.

363


364

Chapter 7 Web Services and J2EE

WebSphere comes with a lightweight database system called Cloudscape.The first
step is to create a new Cloudscape database in which to store the data from the CMP
entity bean in. Follow these steps:
1. Make a directory to store the database in:
>mkdir \db2j\databases\

2. Create a database.The easiest way to do so is to use the supplied ij utility. It’s in
the <websphere>\cloudscape\bin\embedded directory. Start it with the ij command line:
C:\as51\cloudscape\bin\embedded>echo off
ij version 5.1 (c) 2001 IBM Corp.
ij>

3. Type the following line:

connect ‘jdbc:db2j:c:\db2j\databases\skatesdb;create=true’;

Then type
exit;

to quit

ij.You’ll

need to come back to

ij

later to create the table.

You should now have a local database.The next step is to link it to WebSphere by creating a datasource: the virtualization of the database that allows your code to be linked to
the database without your having coded any DB-specific commands in the application.
To create a new datasource in WebSphere, you must first create a JDBC Provider.This
is a configuration that tells WebSphere about a given JDBC database and classes. Luckily,
Cloudscape is preconfigured into WebSphere, so you don’t need to do much (see
Figure 7.3).
Creating a default Cloudscape provider works just fine:
1. In the left-hand pane, select Resources and then, under it, JDBC Providers. Click
New.
2. Select Cloudscape JDBC Provider.
Now that you have a JDBC Provider, you can add a datasource.This tells WebSphere
about the newly created SKATESDB database. Follow these steps:
1. Go into the new Cloudscape entry and select Data Sources. Click New.
2. Give the datasource the name SkatesDataSource, which automatically gives it a
JNDI name: jdbc/SkatesDataSource.

3. Check the box that says Use This Data Source In Container Managed Persistence
(CMP). If you don’t, it won’t work.
4. Go into Custom Properties at the bottom of the configuration page for
SkatesDataSource. In the custom entry databaseName, change the value to
match the new directory you created earlier: c:/db2j/databases/SkatesDB.


Using EJBs from Axis

5. Save your configuration. (For more information, see the WebSphere docs:
/>com.ibm.websphere.nd.doc/info/ae/ae/tdat_ccrtpds.html.)

Figure 7.3 The WebSphere Admin console

Now that your database resource is defined, you can configure and deploy the
application:
1. From the console, choose Applications and then choose Install New Application.
2. Browse to the Skates.ear file.
3. The wizard will take you through a number of steps; in most of them, you can
accept the default values.The ones you need to change are listed here:
In Deploy EJBs Option, the Database Type is CLOUDSCAPE_V5 and the
Database Schema is SKATES.
In JNDI Names for Beans, the value for SkatesEntity is
ejb/skates/SkatesEntityHome and the value for SkatesProduct is
ejb/skates/SkatesProductHome.
In Provide Default Datasource Mapping For Modules Containing 2.0 Entity
Beans, the value for Skatesejb.jar is jdbc/SkatesDataSource.
In Map EJB References To Beans, the value for SkatesProduct and
SkatesEntity is ejb/skates/SkatesEntityHome.
n


n

n

n

365


366

Chapter 7 Web Services and J2EE

4. Click Finish.You should see the following output:
ADMA5016I: Installation of Skates started.
ADMA5018I: Starting EJBDeploy on ear
➥ c:\as51\wstemp\3433544\upload\skates4.ear..
Starting workbench.
Creating the project.
Building: /skatesejb.
Deploying jar skatesejb
Creating Top Down Map
Generating deployment code
Refreshing: /skatesejb/ejbModule.
Building: /skatesejb.
Invoking RMIC.
Generating DDL
Generating DDL
Writing output file

Shutting down workbench.
0 Errors, 0 Warnings, 0 Informational Messages
ADMA5007I: EJBDeploy completed on
➥C:\DOCUME~1\paul\LOCALS~1\Temp\app_fa7b3c6751\dpl\dpl_Skates.ear
ADMA5005I: Application Skates configured in WebSphere repository
ADMA5001I: Application binaries saved in
➥c:\as51\wstemp\3433544\workspace\cells
➥\ZAK-T40\applications\Skates.ear\Skates.ear
ADMA5011I: Cleanup of temp dir for app Skates done.


Using EJBs from Axis

ADMA5013I: Application Skates installed successfully.
Application Skates installed successfully.

5. Choose Save To The Master Configuration and restart the server.
This process creates the DDL database table definition SQL, which you’ll use to create
the Cloudscape tables:
1. In the Enterprise Applications pane, select the Skates application and click the
Export DDL button.
2. Save the file as skates.ddl in a temporary directory.
3. Back to

ij—follow

the bold steps shown here:

ij version 5.1 (c) 2001 IBM Corp.
ij> connect ‘jdbc:db2j:c:\db2j\databases\skatesdb’;

ij> run ‘\temp\skates.ddl’;
ij> -- Generated by Relational Schema Center on
➥Tue Feb 03 13:47:07 GMT 2004

CREATE SCHEMA SKATES;
0 rows inserted/updated/deleted
ij> CREATE TABLE SKATES.SKATESENTITY
(PRICE DOUBLE PRECISION NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
PRODUCTCODE VARCHAR(250) NOT NULL);
0 rows inserted/updated/deleted
ij> ALTER TABLE SKATES.SKATESENTITY
ADD CONSTRAINT PK_SKATESENTITY PRIMARY KEY (PRODUCTCODE);
0 rows inserted/updated/deleted
ij>

Once you have Axis and SkatesEJB deployed and running in a server, you need to test
that Axis is running in the new server.You can use the Enterprise Applications panel to
test by browsing http://server:port/axis and seeing whether you get an Axis Web
page (see Figure 7.4).
Click the Validate link and receive Axis happiness, as shown in Figure 7.5.
If both of those steps work, then the next task is to create a DD and deploy the
SkatesService service.

Configuring Axis to Invoke the SkatesService Session Bean
In this section, we describe how to configure the Axis server to enable Web service
access to your application. Having deployed the application, you need to set up the EJB
provider to be able to invoke the SkatesService bean.This means creating a WSDD
that contains the relevant information.


367


368

Chapter 7 Web Services and J2EE

Figure 7.4 Apache Axis homepage

Figure 7.5 Axis Happiness page


Using EJBs from Axis

If Axis was running on a separate server, you would also need to ensure that the
J2EE.JAR library and the client stubs for the SkatesService bean were in the Axis
classpath.The client stubs are produced as part of the deployment process; usually, the
deployed EJB JAR file will contain them. However, by deploying Axis and the EJBs as
part of the same enterprise application, the J2EE application server ensures that the EJB
client code is available to the Axis Web application.This makes life much easier.
Before running the following commands, create and move to a new directory.The
first aim is to create a WSDL file from the SkatesService remote interface. In order to
do this, you must run the Apache Java2WSDL tool. It needs both the EJB-JAR file
(skatesejb.jar) and the J2EE class library (j2ee.jar):
>set classpath=%axiscp%;.\skatesejb.jar;<appserv>\lib\j2ee.jar
>java org.apache.axis.wsdl.Java2WSDL
–lhttp://server:port/axis/services/SkatesService
com.skatestown.ejb.SkatesProducts

For this to work, you first need to set the right Axis classpath into the environment variable axiscp. In particular, you need the following files in your classpath:

n

axis.jar

n

commons-discovery.jar

n

commons-logging.jar

n

jaxrpc.jar

n

saaj.jar

n

wsdl4j.jar

You also need to find the J2EE.JAR library, which will be in your J2EE app server’s
classpath.You should also set the correct servername and port for your server in
the URL.
If this works, you now have a SkatesService.wsdl file, as shown in Listing 7.4.
Listing 7.4 SkatesService.wsdl
<?xml version=”1.0” encoding=”UTF-8”?>

targetNamespace=””
xmlns=” />xmlns:apachesoap=” />xmlns:impl=””
xmlns:intf=””
xmlns:soapenc=” />xmlns:wsdl=” />xmlns:wsdlsoap=” />xmlns:xsd=” /><wsdl:types>
xmlns=” />
369


370

Chapter 7 Web Services and J2EE

Listing 7.4 Continued
<import namespace=” /><complexType name=”Product”>
<sequence>
<element name=”description” nillable=”true” type=”xsd:string”/>
<element name=”price” type=”xsd:double”/>
<element name=”productCode” nillable=”true” type=”xsd:string”/>
</sequence>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name=”addProductResponse”>
</wsdl:message>
<wsdl:message name=”viewProductRequest”>
<wsdl:part name=”in0” type=”xsd:string”/>
</wsdl:message>
<wsdl:message name=”viewProductResponse”>

<wsdl:part name=”viewProductReturn” type=”impl:Product”/>
</wsdl:message>
<wsdl:message name=”addProductRequest”>
<wsdl:part name=”in0” type=”impl:Product”/>
</wsdl:message>
<wsdl:portType name=”SkatesProducts”>
<wsdl:operation name=”addProduct” parameterOrder=”in0”>
<wsdl:input message=”impl:addProductRequest” name=”addProductRequest”/>
name=”addProductResponse”/>
</wsdl:operation>
<wsdl:operation name=”viewProduct” parameterOrder=”in0”>
<wsdl:input message=”impl:viewProductRequest” name=”viewProductRequest”/>
name=”viewProductResponse”/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name=”SkatesServiceSoapBinding” type=”impl:SkatesProducts”>
transport=” /><wsdl:operation name=”addProduct”>
<wsdlsoap:operation soapAction=””/>
<wsdl:input name=”addProductRequest”>
encodingStyle=” />namespace=”” use=”encoded”/>
</wsdl:input>
<wsdl:output name=”addProductResponse”>



×