You are on page 1of 157

6

Version 6.3.0
J2EE Development and
Deployment Guide
ATG
25 First Street
Cambridge, MA 02141
www.atg.com

Document Version
Doc6.3.0 J2EEDEVv1 3/22/04

Copyright
Copyright 1998-2004 Art Technology Group, Inc.
This publication may not, in whole or in part, be copied, photocopied, translated, or reduced to any electronic medium or machine-readable
form for commercial use without prior consent, in writing, from Art Technology Group (ATG), Inc. ATG does authorize you to copy
documents published by ATG on the World Wide Web for non-commercial uses within your organization only. In consideration of this
authorization, you agree that any copy of these documents which you make shall retain all copyright and other proprietary notices
contained herein.

Trademarks
Dynamo is a registered trademark of Art Technology Group, Inc.
ATG Dynamo Application Server, ATG Relationship Management Platform, ATG Scenario Personalization, ATG Portal, ATG Commerce, ATG
Publishing, ATG Data Anywhere Architecture, and ATG Control Center are trademarks of Art Technology Group, Inc.
Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and
other countries.
This product includes software developed by the Apache Software Foundation (http://www.apache.org/).
All other company and product names are the trademarks or registered trademarks of their respective companies.

No Warranty
This documentation is provided as is without warranty of any kind, either expressed or implied, including, but not limited to, the implied
warranties of merchantability, fitness for a particular purpose, or non-infringement.
The contents of this publication could include technical inaccuracies or typographical errors. Changes are periodically added to the
information herein; these changes will be incorporated in the new editions of the publication. ATG may make improvements and/or changes
in the publication and/or product(s) described in the publication at any time without notice.

Limitation of Liability
In no event will ATG be liable for direct, indirect, special, incidental, economic, cover, or consequential damages arising out of the use of or
inability to use this documentation even if advised of the possibility of such damages. Some states do not allow the exclusion or limitation of
implied warranties or limitation of liability for incidental or consequential damages, so the above limitation or exclusion may not apply to
you.

Contact
ATG
25 First Street
Cambridge, MA 02141
617.386.1000 phone
617.386.1111 fax
www.atg.com

ATG 6 J2EE Development and Deployment Guide

Contents

Introduction

Dynamo and J2EE

Accessing Dynamo Services


Nucleus
Repositories
Mapping Resource References
Global Resources
Application Resources
Mapping Applications to Repositories
Deploying an Existing J2EE Application in Dynamo
Unpacking the EAR File
Filling in the Dynamo J2EE Specifier File
Creating a DAR File
Running the Application
Summary of the Deployment Process
Developing a New J2EE Application in Dynamo
Loading and Running the Application
Using the J2EE Default Application
J2EE Demo Applications
Running Dynamo Meeting Manager

Creating a Sample J2EE Application


Structure of the Application
J2EE Project
J2EE Application
Building and Running the Application
Using Darina to Build and Deploy the Application
Precompiling JavaServer Pages
Running the Deployed Application
Running the Application Client
Monitoring a Deployed Application
Rebuilding an Application
Reloading an Application
Suggested Development/Deployment Approach
Variations on the Build/Deploy Process
External Source Tree

3
3
4
6
6
6
7
9
10
11
12
13
13
14
15
15
16
16

19
19
20
21
22
22
25
26
27
27
27
28
30
31
31

iii
Contents

ATG 6 J2EE Development and Deployment Guide

External Build Tree


Internal Source Tree
Specifying Another Java Compiler

Web Applications
Overview of Web Applications
web.xml File
Standalone WAR Files
Web Services
How Dynamo Processes a JSP Request
Resources in web.xml
Optional Resources
Adding New Resources to web.xml
Creating Filters and Servlets
Specifying Session Timeouts
Enabling Session Failover
Additional Configuration for Web Applications
Specifying Web Mappings
Enabling Listing of Directories
Configuring Servlet Pooling
Specifying the Ordering of Filters

33
35
36

37
37
38
38
38
38
40
40
41
41
43
44
44
44
45
46
47

Using the Dynamo Deployment Editor

49

Overview of the Deployment Editor


Deploying an Application
Installing an Application on the Server
Specifying the J2EE Version
Adding Elements to the Application
Validating the Application
Building the Application
Running the Application
Deploying a Standalone Module
Installing an Existing Module
Creating a New Module
Resolving Resource References
JDBC Service
GSA Repository Service
JMS Connection Service
JavaMail Service
URL Service
Resolving References to J2EE Connectors
Resolving Security Roles
Resolving Environment Entries

49
53
53
55
55
60
61
61
61
62
62
62
63
65
66
66
66
67
68
68

Enterprise JavaBeans
EJB Examples

71
72

iv
Contents

ATG 6 J2EE Development and Deployment Guide

Configuring EJBs and the EJB Container


Resolving References to EJBs
Resolving Environment Entries for EJBs
Communications Protocols
EJBs and Transactions
EJBs and Security
Timing of ejbLoad and ejbStore
Instance Pooling and Management
Session EJB Passivation and Expiration
Accessing EJBs from Nucleus Components
Container-Managed Persistence
EJB Field Types for CMP
Configuring CMP
CMP Automatic Mapping
EJB Clustering
EJB Clustering Overview
Dynamo EJB Clustering Architecture
Cluster Manager Configuration and Administration
Cluster Node Configuration
Configuring Session Backup

Application Clients
Application Client Overview
Deploying Application Clients
Resolving JDBC Resource References
Resolving JavaMail Resource References
Running Application Clients
Application Clients and EJB Clustering
Running an Application Client Remotely
Lightweight Application Clients
Lightweight Application Clients and EJB Clustering

J2EE Security
Dynamo J2EE Security Architecture
Configuring Dynamo Security for J2EE
Single Login
J2EE Security Example
Deploying the J2EE Security Example
Running the J2EE Security Example
The J2EE Security Example Explained
SQL Repository Configuration Example
Hashing Passwords
Administrative Users

73
73
75
77
78
80
81
83
85
87
87
88
89
93
95
96
99
100
104
107

109
109
110
110
113
114
114
115
116
120

123
123
125
129
129
130
131
132
137
138
141

v
Contents

ATG 6 J2EE Development and Deployment Guide

Appendix A: Darina Command Options

143

Appendix B: Sun JMS Reference Implementation

145

Configuration and Administration


Database Tables

Index

145
146

149

vi
Contents

ATG 6 J2EE Development and Deployment Guide

1 Introduction

Java 2 Enterprise Edition (J2EE) is a standard platform for writing enterprise applications in Java. It is
defined by a set of specifications that is maintained and extended by Sun through the Java Community
Process (JCP). It dictates the way server-side applications should be written and packaged in order to be
portable across J2EE implementations, and also mandates what services a J2EE application server must
provide to the applications it hosts.
Dynamo supports the J2EE 1.3 standard. You can create J2EE applications in Dynamo and deploy them on
any J2EE-compliant application server (including, of course, Dynamo itself), and you can deploy and run
J2EE applications on Dynamo that were developed on other J2EE application servers.
This book discusses all aspects of developing and deploying J2EE applications in Dynamo. It includes the
following chapters:
Dynamo and J2EE
Creating a Sample J2EE Application
Web Applications
Using the Dynamo Deployment Editor
Enterprise JavaBeans
Application Clients
J2EE Security
Appendix A: Darina Command Options
Appendix B: Sun JMS Reference Implementation

1
1 - Introduction

ATG 6 J2EE Development and Deployment Guide

2
1 - Introduction

ATG 6 J2EE Development and Deployment Guide

2 Dynamo and J2EE

One of the key advantages of J2EE applications is portability. To ensure that they are portable between
application servers, J2EE applications make only generic references to system resources. For example, an
application may require a JDBC connection, but the application code does not directly create or refer to
this connection. Instead, the application refers to the resources generically, and when the application is
deployed, the deployment descriptors map these generic references to specific resources on the
application server.
Therefore, to develop and run J2EE applications on a specific application server, you need to understand
the unique features of that application server. This chapter discusses key features of Dynamo Application
Server (DAS) that the J2EE developer and deployer must be familiar with. It includes the following topics:
Accessing Dynamo Services
Mapping Resource References
Mapping Applications to Repositories
Deploying an Existing J2EE Application in Dynamo
Developing a New J2EE Application in Dynamo
J2EE Demo Applications

Accessing Dynamo Services


This section discusses key Dynamo concepts that you should be familiar with to develop and deploy J2EE
applications in Dynamo:

Nucleus, which is the application framework through which you access Dynamo
services

Repositories, which are the mechanism Dynamo uses to provide container-managed


persistence (CMP) for entity EJBs

Nucleus
Dynamo includes an application framework called Nucleus. In Nucleus, each service is packaged as a
JavaBean or set of JavaBeans. These JavaBeans are configured individually and mounted into a
namespace. The beans then interconnect with the beans representing other services. Nucleus is
responsible for interpreting the component configurations and the management of the component
namespace.

3
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

Dynamo uses the Nucleus framework to organize components into a hierarchical structure (similar to a
directory structure). Each Nucleus service has a unique Nucleus name. For example, the default
javax.sql.DataSource component is located at /atg/dynamo/service/jdbc/JTDataSource.
Developers and deployers can change the configurations of individual components, inspect components
at runtime, and add new components to the namespace. You can create these components from existing
ATG classes, or from classes you write yourself. The details of Nucleus configuration, and the services
maintained by Dynamo, are explained in the ATG 6 Dynamo Programming Guide.
There are two distinct ways you can use Nucleus components with J2EE-based applications:

Most DAS services (servers, database connections, EJB and Web containers, schedulers,
loggers, etc.) are implemented as Nucleus components. As part of deploying a J2EE
application in Dynamo, you may need to map resources required by the application to
Nucleus components. The Mapping Resource References section (below) discusses
mapping the resources used by J2EE applications to Nucleus services.

You can incorporate Nucleus components in your applications directly, and access
them in JavaServer Pages using the DSP tag libraries. Using Nucleus enables you to
incorporate the personalization, commerce, and publishing features of ATG 6 in your
J2EE applications. The ATG 6 Page Developers Guide provides information about the
DSP tag libraries.

Repositories
ATG 6 has several features that require persistent storage. The security manager, for example, requires a
mechanism to store usernames, passwords, and user/group associations.
Unlike some application servers, Dynamo does not handle persistence directly through a SQL database.
Instead, Dynamo uses an intermediate data access layer called the Repository API. Whenever Dynamo
needs to load, store, or query a data source, it makes the appropriate calls through this API. The repository
translates the API calls into whatever calls are needed to access that particular data source.
Dynamo provides implementations of the Repository API for various data sources. Perhaps the most
powerful implementation is the SQL repository, which interfaces the Repository API to an SQL database.
However, the Repository API can access other data sources such as LDAP or content management
systems.
Because of this approach, applications that use only the Repository API to access data can interface to any
number of back-end data sources solely through configuration. For example, the security system can be
directed to maintain its list of usernames and passwords in an SQL database by pointing the security
system at the SQL repository. Later, the security system can be changed to use LDAP by reconfiguring it to
point to the LDAP repository.
Dynamos container-managed persistence (CMP) for entity EJBs is based on the SQL repository; other
repository implementations cannot be used for CMP. As is always the case for CMP, the mapping of CMP
fields to the data source is handled through configuration files. The code within the EJB implementation
classes does not need to be aware of repositories or persistence.

4
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

Key Repository Concepts


To make the best use of Dynamos persistence features, J2EE developers and deployers should be familiar
with the basic repository concepts and terms.
A repository is a collection of repository items. Each repository item is made of properties, which store
the actual data of the item. Each property has a name, such as id, firstName, or lastName. In the SQL
repository, these properties correspond roughly to columns of a table.
Each repository item must belong to one of several item types, where each type is defined by a
repository item descriptor (also called a repository view). The item descriptor gives a name to the type,
and also describes the properties for that type. The name of each property is defined here, as well as the
Java object used to represent that property (Integer, String, etc.).
The item descriptors exposed by a repository depend on a combination of the underlying data source and
the Repository API implementation for that data source. Conceptually, it is useful to think of an item type
as represented by a table, with the rows being the individual items and the columns being the properties.
In actual practice, an item descriptor may comprise multiple tables.
Each repository item must have an identifier, called a repository ID, that uniquely identifies the item from
all other items of the same type. The repository is typically configured to find the repository ID from some
element of the underlying data. In the SQL repository, for instance, each item descriptor must specify
which of the columns acts as the repository ID. This will typically be the same as the tables primary key.
Depending on the repositorys configuration, the repository ID may or may not be exposed as a property
of the repository item.
All repositories support simple property types such as Strings and Integers. Some repositories also
support collections or arrays of those properties; for example, a Person item descriptor might have an
interests property of type String[]. Finally, some repositories support complex property types, in
which the value of the property is itself another repository item or collection of repository items. For
example, a repository might have item descriptors for types Person and Address. The Person item
descriptor might have an addresses property that exposes the list of Addresses that a Person might
have. This property might be of type RepositoryItem[], and the items in that array will use the
Address item descriptor. This allows repositories to represent one-to-one, one-to-many, or many-tomany relationships.
The combination of item descriptors, properties, identifiers, and items enables a repository to read
application data from the underlying data source, and to write application data back to the data source.
Some repositories allow certain properties or even entire item descriptors to be exposed as read-only.
Sometimes properties can even act as translators between the underlying data source and the Java
application. For example, an repository might allow a property called firstNameUpperCase to take
mixed-case names from a database and expose them as all upper-case.
More detail about the Repository API system and the various repository implementations that come with
Dynamo can be found in the ATG 6 Repository Guide.

5
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

Mapping Resource References


To run a J2EE application on a specific application server, you must map the applications resource
requirements to specific services running on the application server. In Dynamo, this mapping is handled
through the Dynamo J2EE specifier file (dynamoJ2EESpecifier.xml). This is an XML file containing all of
necessary Dynamo-specific information, formatted according to a Document Type Definition.
When you resolve resource references in the J2EE specifier, you have two main options:

You can resolve the resource globally to a resource factory shared by all applications
running on the server.

You can resolve the resource reference to a resource factory used only by the specific
application.

Global Resources
Mapping a resource on the global (server) level involves setting the resource reference to the JNDI form of
a Nucleus name. A Nucleus services JNDI name is formed by prepending dynamo: to the Nucleus name;
so, for example, the default component for JDBC connection pooling is
dynamo:/atg/dynamo/service/jdbc/JTDataSource. A resource reference to this component would
look something like this:
<resource-ref>
<res-ref-name>
jdbc/db
</res-ref-name>
<resource-name>
dynamo:/atg/dynamo/service/jdbc/JTDataSource
</resource-name>
</resource-ref>

Nucleus components referenced this way must be configured through properties files. In the case of the
JTDataSource component, properties files are used to set values such as the minimum and maximum
pool size. The values in these files are read by Dynamo when it starts up. This means that if you change
any of these values, you must restart Dynamo before the change takes effect.
Note that application clients cannot use global resources, because they do not have access to Nucleus
components.

Application Resources
Mapping a resource on the application level involves setting the resource reference to a resource link, as
in this example:
<resource-ref>
<res-ref-name>
jdbc/db
</res-ref-name>
<resource-link>

6
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

jdbc1
</resource-link>
</resource-ref>

The resource factory is then configured directly in the Dynamo J2EE specifier file. For example, you might
configure a JDBC connection pool like this:
<jdbc-service>
<resource-service-name>
jdbc1
</resource-service-name>
<jdbc-lookup>
DriverManager
</jdbc-lookup>
<jdbc-url>
jdbc:solid://localhost:1313
</jdbc-url>
<jdbc-driver-class>
solid.jdbc.SolidDriver
</jdbc-driver-class>
<min-pool-size>
10
</min-pool-size>
<max-pool-size>
10
</max-pool-size>
<max-pool-free>
10
</max-pool-free>
<resource-username>
admin
</resource-username>
<resource-password>
admin
</resource-password>
</jdbc-service>

Dynamos J2EE container automatically handles the startup and shutdown of application services. As a
result, you can shut down the application, make changes to the configuration, and restart the application
with the new settings without needing to restart Dynamo.

Mapping Applications to Repositories


As mentioned above, Dynamo handles persistent storage through repositories. For J2EE applications,
persistent storage is used for security information and for entity EJBs that use container managed
persistence (CMP). Therefore, if your application uses either security or CMP, you must know how to map
these resource references to a repository.

7
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

Repositories can be configured either as global or application resources. To map a system to a repository,
there are typically several settings you need to configure.
First, you need to specify which repository the system should use. Next, you specify the name of the item
descriptor or repository view the system should use to access its data. Some systems will need to use
several item descriptors. In addition, you specify which properties of these item descriptors to use. For
example, if you map the Dynamo security system to an item descriptor in a repository, you must specify
which property of that item descriptor represents the login name, and which property represents the
password. The process of configuring the security system is discussed in the J2EE Security chapter.
For a container-managed entity EJB, the fields of the EJB must be mapped to properties of a repositorys
item descriptor. Each entity EJB with CMP must be configured with a reference to the repository its data is
stored in, and the name of the item descriptor that will represent the EJB. Each persistent field must then
be mapped to a property of that item descriptor. Finally, applications that use CMP may need to execute
specific queries at certain times. These queries are specified using Dynamos Repository Query Language
(RQL) for EJB 1.1 CMP, or using the J2EE-standard EJB query language (EJB-QL) for EJB 2.0 CMP. This
process is discussed in more detail in the Enterprise JavaBeans chapter of this manual.
The J2EE deployer must become familiar with the repository system to use it effectively, and to debug
applications when things go wrong. The use of repositories gives Dynamo a great deal of flexibility, but
also introduces some complexity. For CMP, for example, there are three layers of naming: columns of a
table in a SQL database map to properties of an item descriptor in a repository, which in turn map to fields
of an EJB. This means that you need to organize your data carefully to keep this complexity under control.

Typical Repository Setup


As discussed above, Dynamo supports a wide variety of repository setups, and a single application can
use multiple repositories of different types. For example, an application might use a SQL repository for
CMP and an LDAP repository for the security system. Typically, though, an application will use a single
SQL repository for all of its persistent storage.
To set up Dynamo to use a SQL repository, begin by setting up JDBC access to the database. The details of
this process are described in the ATG 6 Installation and Configuration Guide for Dynamo Application Server.
The basic setup involves configuring the /atg/dynamo/service/jdbc/JTDataSource service to point
to a JDBC 2.0 driver. If a JDBC 2.0 driver is not available, the
/atg/dynamo/service/jdbc/FakeXADataSource is used to translate a JDBC 1.0 driver into a JDBC
2.0-like driver, which the JTDataSource can use.
Once the appropriate DataSource has been configured, a single instance of the SQL repository
(atg.adapter.gsa.GSARepository) is configured to use that DataSource. That SQL repository is also
configured to map the various tables in the database to item descriptors, properties, one-to-one and oneto-many mappings, etc. The SQL repository does not need to immediately describe every table in the
database - as applications and application features are added, the appropriate mappings can be added to
the SQL repository.
Once the SQL repository has been set up, all of the higher-level application systems can use that same
SQL repository instance. Entity EJBs with CMP can point to that SQL repository service and persist to item
descriptors and properties defined in that SQL repository. If a new Entity EJB is added, that may require
adding a new table to the database, adding the corresponding entries in the SQL repositorys
configuration, and adding the appropriate repository mappings in the EJBs configuration.

8
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

The security system can be configured to use the same SQL repository instance. Of course, the
appropriate tables must exist in the database and the SQL repository must be configured to map item
descriptors to those tables. The security system can then be configured to map its repository
requirements to those item descriptors and properties.

Entity EJB

GSA instance

JTDataSource

JDBC driver

Database

Security

In addition to using a common repository, the security system and the entity EJBs can even use the same
item descriptors. For example, there may be a Person entity EJB that maps to a Person item descriptor in
the SQL repository, which maps to a PERSON table in the database. At the same time, the security system
might also map to the same Person item descriptor in the SQL repository, using properties of that item
descriptor to represent the login name and password. Because the Person EJB maps to the same data
source as the security system, the database of users authenticated by the security system can be
managed by using Person EJBs. This is just one example of how powerful features follow from the
flexibility of the repository system.

Finder Methods and the Repository Query Language


When using entity EJBs with EJB 1.1 container-managed persistence, the finder methods defined by the
EJBs home interface must be mapped to queries in the underlying persistence engine. These queries are
expressed in Dynamos RQL. The individual repositories are responsible for translating those queries into
the query syntax expected by the underlying data store.
The details of RQL syntax and structure are described in the ATG 6 Repository Guide. Rather than mastering
the syntax now, it might make more sense to use that section as reference material to be consulted when
trying to implement a particular sort of query.
The details of using RQL when mapping EJB finder methods are described in the Enterprise JavaBeans
chapter of this manual. Note that EJB 2.0 CMP uses the EJB-QL query language rather than RQL.

Deploying an Existing J2EE Application in Dynamo


A J2EE application must be deployed on the application server before the application can be run. The
deployment process is different for each application server, but the general requirements for the
deployment process are the same across application servers.

9
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

An existing application is typically packaged as an enterprise archive (EAR) file. An EAR file contains all of
the application code, and the deployment process largely consists of supplying the necessary mappings
between the application and Dynamo resources.
Dynamo includes a command-line tool called Darina, which automates portions of the deployment
process, such as unpacking the EAR file, compiling the source files, and creating deployment descriptor
files. In addition, the ATG Control Center includes a J2EE Deployment Editor that provides a menu- and
dialog-based environment for deploying applications. Darina and the Deployment Editor call the same
underlying code for building and validating the application, so they produce similar results. Typically, you
will want to use the Deployment Editor most of the time. However, this section, and the following
chapter, describe the deployment process using Darina. Its important for you to be familiar with this tool,
both to understand what happens when you deploy an application, and in case you need to use any of
the options available only through the command line.
To deploy an EAR file, the deployer must specify information that links the application to the services in
Dynamo. This Dynamo-specific configuration is placed in a Dynamo J2EE Specifier file,
dynamoJ2EESpecifier.xml. In addition, the deployer can use this file to override settings in other
deployment descriptors. For example, if the web.xml file declares an env-entry, the
dynamoJ2EESpecifier.xml file can specify the value of this env-entry (if the value is not set in
web.xml), or override the existing value (if it is set in web.xml). After filling in all of the necessary
information in the dynamoJ2EESpecifier.xml file, the deployer then runs Darina to deploy the
application.
Creating the Dynamo J2EE Specifier file can be a complex process, but Darina can alleviate some of this
complexity by creating a template Dynamo J2EE Specifier file. The process of deploying the application
works like this:
1.

Call Darina, passing it the name of the EAR file.


Darina unpacks the EAR file and generates a Dynamo J2EE Specifier template file.
Darina determines the tags to include based on the contents of the EAR file, but not all
values are filled in. The file contains comments indicating where values need to be
entered.

2.

Go through the Dynamo J2EE Specifier file and enter the appropriate values.

3.

Run Darina again, this time passing it the name of the directory containing the
unpacked application, to create a DAR (Dynamo Archive) file.

4.

Add the DAR file to the list of applications managed by Dynamos J2EE container, and
restart Dynamo to start up the application.

Each of these steps is described in more detail below.

Unpacking the EAR File


When you first run Darina on an EAR file, it unpacks the contents of the EAR file (and the contents of the
JAR and WAR files it contains) into a staging directory, and creates a template Dynamo J2EE Specifier file.
The staging directorys structure is similar to the structure of the EAR file, with the JAR and WAR files
becoming subdirectories of the application directory. The staging directorys structure looks similar to
this:

10
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

myApp/
web-app.war/
(JSP pages and content resources)
WEB-INF/
web.xml (deployment descriptor)
classes/
(java files, classes and resources)
lib/
(class and resource .jar files)
ejbs.jar/
(java files, classes and resources)
META-INF/
ejb-jar.xml (deployment descriptor)
META-INF/
application.xml (deployment descriptor)
DYNAMO-INF/
dynamoJ2EESpecifier.xml

(Dynamo J2EE Specifier file)

Filling in the Dynamo J2EE Specifier File


After running Darina the first time to unpack the EAR file and generate the template Dynamo J2EE
Specifier file, you must fill in the values for various tags:

Specify the values of any env-entry values that have not yet been filled in. You can
also supply env-entry values that override the values specified in development or
assembly.

Resolve all resource references by mapping them to either global or application


resources.

Resolve all EJB references. You can resolve local EJB references (references to EJBs in
the same application) in the assembly stage or in the deployment stage. You must
resolve remote EJB references in the deployment stage.

Map each entity EJB that uses container-managed persistence (CMP) to a repository
view in a SQL repository, and each container-managed field to a property in the
repository view.

Map each security role to a persona defined in a UserAuthority. The persona is the
name of an entry in the UserAuthority that represents a J2EE role.

Map Web applications to URLs. Multiple Web applications can run simultaneously on a
single application server, so the overall URL space must be divided among the
applications.

Configure pool sizes for various components. Certain components (single-threaded


servlets, stateless session beans, and entity beans) require the use of pools for
efficiency. These pools have default settings, but you can modify these settings at this
stage.

11
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

Configure the behavior of entity EJBs. There are several settings for entity beans to
control when their data is synchronized with the backing store. You can modify these
settings to make tradeoffs between performance and distributed data integrity.

Note that the tags available in the Dynamo J2EE Specifier file are all described in the DTD for the file,
which you can view at:
http://www.atg.com/j2ee/dtds/dynamoJ2EESpecifier_1_3.dtd

Creating a DAR File


After creating the Dynamo J2EE Specifier file and filling in all the necessary values, the deployer must run
Darina again to create a Dynamo Archive (DAR) file, which has the extension .dar. A DAR file is similar to
an EAR file, but includes some additional files used only by DAS.
Darina analyzes the application files and the J2EE Specifier file, making sure that the application is valid
and that all the necessary information is supplied in the deployment descriptors and the Dynamo
specifier. Once Darina determines that the application is valid, it compiles any source files that have
changed, generates the implementation classes of the EJB interfaces and the corresponding RMI or IIOP
files, and packages the application as a DAR file that is ready to be run on the Dynamo server.

dynamoJ2EE.xml File
As mentioned above, the dynamoJ2EESpecifier.xml file can contain a mix of Dynamo-specific tags and
tags that override entries in the standard deployment descriptors, such as web.xml and ejb-jar.xml.
When Darina generates a DAR file, it extracts all of the Dynamo-specific tags and puts them in a file
named dynamoJ2EE.xml.
The remaining tags are merged into the deployment descriptors that they apply to. Darina does not
actually modify the original deployment descriptors, however. Instead, it creates a copy of each file being
overridden, modifies the copy, and adds an alt-dd tag to the application.xml file to point to the
modified copy. This mechanism ensures that you can easily revert to the original descriptors.
For example, suppose the web.xml file declares an env-entry named defaultValue, and sets its value
to 10; in the dynamoJ2EESpecifier.xml file, you override this value, setting it to 15. When you generate
a DAR file, Darina creates a copy of the web.xml file that includes the new setting, names the file based
on the name of the WAR file, and places the file at the top level of the DAR file (rather than within the WAR
file, where the web.xml file is found). The application.xml file then declares the Web module like this:

<module>
<web>
<web-uri>web-app.war</web-uri>
<context-root>myApp</context-root>
</web>
<alt-dd>web-app_altdd.xml</alt-dd>
</module>

To revert to the original settings, remove the alt-dd tag. The application will then use the original
web.xml file.

12
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

ejb-client-jar File
If the application includes EJBs, Darina generates an ejb-client-jar file for each EJB module and
includes it in the DAR file. The ejb-client-jar contains the classes that clients need in order to access
the EJBs. These files include, at a minimum, the home and remote interfaces, and any classes referenced
by those interfaces.

Running the Application


Once the application has been fully validated and Darina has created a DAR file, the application can be
run on a Dynamo server. The Nucleus component /atg/dynamo/service/j2ee/J2EEContainer is the
main service that manages J2EE applications. It has a property called applications, which is a list of the
J2EE applications it manages. To add a new J2EE application to the list of applications, add the name of
the applications DAR file to the applications property, as described in the following chapter. After
Dynamo is restarted, the J2EE application will be up and running.

Monitoring the Application


Once a deployed J2EE application is running, the status of the application can be monitored through the
HTML Administration UI, which is typically accessed through the 8830 port. To view the applications
running in the J2EE container, click on the J2EE Container link on the main page of the Administration UI.
This link takes you to a page where you can view the applications and their individual modules, as well as
the components they access. For example, you can look at the TransactionManager component to get
statistics about transactions, or look at the JTDataSource component to see what JDBC connections are
currently in use and what connections are still in the pool.

Debugging the Application


To diagnose problems with an application, a good first step is to enable logging of debugging messages.
For many Nucleus services, you can do this by setting a components loggingDebug property to true.
For example, setting loggingDebug to true on the /atg/dynamo/transaction/TransactionManager
component causes it to log information about the start and end of each transaction.
You can set loggingSQLInfo to true on the DataSource component used by your application (typically
/atg/dynamo/service/jdbc/JTDataSource) to log all of the SQL statements written to the database.
Setting loggingSQLDebug to true produces additional output, including the parameters set in each
statement and the result set values returned. For applications that use Enterprise JavaBeans, you can set
loggingDebug to true on Dynamos EJB container (/atg/dynamo/service/j2ee/EJBContainer).

For more information about debugging options in Dynamo, see the ATG 6 Dynamo Programming Guide.
For more information about logging SQL messages, see the ATG 6 Installation and Configuration Guide for
Dynamo Application Server.

Summary of the Deployment Process


The following is a diagram of the deployment process, starting with an assembled EAR file:

13
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

assembled EAR file

(processing by Dynamo J2EE deployment tool)

Dynamo J2EE Specifier template file

(deployer fills in values)


assembled EAR file

Complete Dynamo J2EE Specifier file

(processing by Dynamo J2EE deployment tool)

deployed DAR file

(copy to server)

(add to J2EEContainer.applications)

(restart server)

Developing a New J2EE Application in Dynamo


When you develop a J2EE application in Dynamo, you need to be able to make changes to the
application, build and deploy the new version, and then run it. For a complex application, you may need
to repeat these steps many times.
To simplify this process, Dynamo supports an iterative development mode that does not require you to
package up your application as an archive file. In this mode of development, directories are not placed
into JAR format before they are used. The application must still adhere to the file structures of the various
J2EE module types (such as the EJB JAR and WAR file formats), but the file structures remain in their
original form on the disk, so you can work directly on the applications files.
To support this incremental mode, Darina can work within a staging directory, without producing a DAR
file. In this mode, Darina still validates the application and generates and compiles the necessary classes,
so the resulting application can be run directly from the staging directory.

14
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

Finally, to streamline the development process as much as possible, Darina can handle incremental
compilation of changed Java files. If the source Java files are included in the directory structure, Darina
can determine which files have changed, and can compile just those files into their appropriate .class
files. For EJB interfaces, Darina also regenerates the associated implementation and RMI or IIOP classes.
This incremental model enables you to concentrate on writing and modifying Java and JSP source files. To
make a change to your application, you modify the source files, run Darina, and restart the application. If
you change or add only JSPs, you do not need to do anything to make the changes available; Dynamo
automatically compiles a new or modified page when it is accessed.
Note, however, that if you want to deploy the application on another instance of Dynamo, the application
must still be packaged as a DAR file. To run the application on another Dynamo instance, you need to
create a Dynamo module, copy the DAR file into that modules directory, and add the DAR file to the
applications property of the J2EEContainer.

Loading and Running the Application


The last stage of application deployment is to restart Dynamo so that it starts up the new application.
Once the application is running, you may need to make further changes and then restart the application
again. You can restart the application each time by restarting Dynamo, but this is inconvenient, since
restarting the server can take some time.
In most cases, however, it is possible to hot-swap a running application, replacing it with a revised version
of the application. This allows changes to be seen immediately. An application is always swapped in its
entirety; individual classes or J2EE modules cannot be hot-swapped.
When an application is hot-swapped, there may be a period of time when both the old and new versions
of the application are running. This depends on whether the application is being run from a DAR file or a
staging directory. If the application is run from a staging directory, only the new version will run when you
restart the application. If the application is run from a DAR file, however, the old version continues to run
after the new version starts up. The old version will finish handling any existing requests and threads, but
all new ones will be directed to the new version. Once the old version has finished with the requests and
threads it is handling, it can be removed from the system.
Keep in mind that, depending on the differences between the two versions, hot-swapping an application
can lead to errors. For example, if the HTTP session data contains objects whose classes were loaded from
the web application, you may see exceptions of class java.lang.ClassCastException when those
objects are accessed by the new version.
Note that if the application uses global (server-wide) resources that are configured through properties
files, changes to the configuration of these resources do not take effect unless you restart Dynamo.
For more information about hot-swapping applications, see Reloading an Application.

Using the J2EE Default Application


The J2EE Default application starts up automatically when you run Dynamo, and provides a convenient
location for developing J2EE components such as JSPs. The J2EE Default application can be found in the
following location in a Dynamo installation:

15
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

<DAS6dir>/J2EE-Default

You can access the application at the URL:


http://{hostname}:8840/default

Adding a New JSP


To a new JSP to the J2EE Default application, just create or place the file in the following location:
<DAS6dir>/J2EE-Default/j2ee-apps/j2eeDefault/web-app

You do not need to restart the application to access the new JSP. Dynamo automatically compiles a new
or modified JSP the first time it is accessed.

J2EE Demo Applications


Dynamo includes many applications that demonstrate specific aspects of J2EE, such as security or
Enterprise JavaBeans. These applications are discussed in detail in the chapters of this manual dedicated
to those features. In addition, Dynamo includes Dynamo Meeting Manager, which is a more complete
application that allows users to schedule meetings and invite other users to those meetings. It uses
sophisticated RQL queries to make sure that the chosen meetings do not conflict with meetings already
scheduled for invited users.

Running Dynamo Meeting Manager


You do not need to deploy Dynamo Meeting Manager in order to run it. The application is already in
deployed form when it is installed.
Dynamo Meeting Manager is packaged as a Dynamo module. You can run it by starting Dynamo with the
-m flag:
bin/startDynamo -m J2EE-Examples.DMM

Once started, the demonstration can be viewed by accessing the URL


http://{hostname}:8840/meeting.
It is assumed that the demo will be running on SOLID, the evaluation database included with Dynamo.
This database comes pre-initialized with the schema needed to run the demo. If for some reason the
schema does not exist, it can be created using the commands found in
<DAS6dir>/DAS/sql/db_components/solid/create_j2ee_demos_ddl.sql.
The demo will run without further configuration if you access it using Serverina at
http://{hostname}:8840/meeting/. However, if you want to access the demo using a third-party
Web server, you need to configure your Connection Modules DynamoPath entry to include /meeting,
the context root of the Dynamo Meeting Manager module. For example, in an Apache Connection
Module, the httpd.conf file could have a line like this:

16
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

DynamoPath "/meeting"

See the ATG 6 Installation and Configuration Guide for Dynamo Application Server for information about
configuring Apache, IIS, and Sun ONE Connection Modules.

17
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

18
2 - Dynamo and J2EE

ATG 6 J2EE Development and Deployment Guide

3 Creating a Sample J2EE Application

Developing a J2EE application is a much more rigorous task than developing a J2SE application. The Java
coding itself isnt much more difficult; in fact, the Java coding is often much simpler. What makes the task
more complex is the requirement that the classes must be packaged in a specific way, with deployment
descriptors filled out in a specific format.
This chapter presents a sample application, simpleJ2EE, that developers can use as a starting template
for building their own applications. This application uses one each of several different J2EE component
types: Servlet, JSP, JSP Tag, EJB, and application client. These components all perform trivial tasks.
However, the point of the application is to illustrate the form of a J2EE application, rather than
demonstrating J2EE functionality. Once developers have mastered the form, experimenting with complex
J2EE features becomes much easier.
This chapter also uses the simpleJ2EE sample application to demonstrate Dynamos J2EE build and
deployment tools, along with many of the options these tools have for working in different kinds of
development environments. This chapter discusses the following topics:
Structure of the Application
Building and Running the Application
Variations on the Build/Deploy Process

Structure of the Application


The simpleJ2EE application demonstrates how various J2EE component types (Servlet, JSP, JSP Tag, EJB,
and application client) are packaged into a full J2EE application. The operation of the final application is
extremely simple:

A single JSP (index.jsp) contains a reference to a JSP Tag. The Tag adds two numbers
together by connecting to a stateless session EJB and having that EJB perform the
calculation. The result is then printed in the JSP.

The JSP also contains a link to a Servlet in the same application, whose only function is
to print out a simple HTML page.

An application client is also included which just invokes the EJB to add two numbers
from the command line.

19
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

J2EE Project

Dynamo organizes J2EE applications into projects. A J2EE project includes one or more J2EE applications,
stored in a specific directory structure. Typically, all of the applications in a single project are related.
Dynamo manages a J2EE project as a Dynamo application module. A Dynamo module is the smallest unit
that Dynamo can run. If you store multiple J2EE applications in a J2EE project, running the project will run
all of the applications in the project.
A Dynamo module is a directory found under either the <DAS6dir> directory, which corresponds to the
system property atg.j2eeserver.root, or the <ATG6dir> directory, which corresponds to the system
property atg.dynamo.root. A module is named by its position relative to one of these directories, using
the dot character (.) to separate directory levels. The module that includes the simpleJ2EE application is
in the directory J2EE-Examples/SimpleJ2EE under <DAS6dir>. This module is therefore named J2EEExamples.SimpleJ2EE. To start up Dynamo and run the applications in this module, the command
would be:
startDynamo m J2EE-Examples.SimpleJ2ee

The top-level directory of a Dynamo module containing a J2EE project typically looks like this:
META-INF/
config/
j2ee-apps/

The META-INF directory stores the manifest file (named MANIFEST.MF) that specifies configuration
information about the module. The manifest file for a J2EE project typically looks like this:
Manifest-Version: 1.0
ATG-Config-Path: config/
ATG-Required: DAS

This file adds the config directory at the top level of the module to Dynamos CONFIGPATH , and it
specifies that this module requires the DAS module. Every J2EE project requires the DAS module, which
includes the J2EE container functionality.
The j2ee-apps directory contains one or more subdirectories, each representing an individual J2EE
application. The SimpleJ2EE project includes only one application, so j2ee-apps contains only one
subdirectory, named simpleJ2EE. This subdirectory is located at <DAS6dir>/J2EEExamples/SimpleJ2EE/j2ee-apps/simpleJ2EE.
Note that the j2ee-apps directory is not strictly required. The application directories can be in the toplevel directory of the Dynamo module, rather than being subdirectories of j2ee-apps. The main
advantage of having a j2ee-apps directory is that it provides a clearer separation between the top-level
directories of the Dynamo module, which contain configuration that applies to the entire project, and the
subdirectories that contain the individual applications.
The config directory stores properties files for global services that the J2EE project uses. Each J2EE
project must have a config directory, and use it to configure Dynamos J2EE Container to add the
projects applications to the list of applications it can run. This is done in the file

20
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

config/atg/dynamo/service/j2ee/J2EEContainer.properties. For example, in the SimpleJ2EE

Dynamo module, this file contains:


applications+=\
{atg.j2eeserver.root}/J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE

This names the location of the staging directory that contains the compiled and deployed J2EE
application. If the project includes more than one application, the line above is a comma-separated list,
such as:
applications+=\
{atg.j2eeserver.root}/J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE,\
{atg.j2eeserver.root}/J2EE-Examples/SimpleJ2EE/j2ee-apps/anotherJ2EE

More complex J2EE projects may include other configuration files. For example, if a J2EE project includes
an application that uses container-managed persistence (CMP), configuration files may be needed to map
the SQL repository used for CMP to the underlying database.
For more information about application modules in Dynamo, see the ATG 6 Installation and Configuration
Guide for Dynamo Application Server.

J2EE Application
As mentioned above, the j2ee-apps directory of the SimpleJ2EE project contains a single subdirectory
called simpleJ2EE. The complete simpleJ2EE application is stored in this directory, which serves as the
staging directory for developing and deploying the application.
The simpleJ2EE directory looks like this:
META-INF/
web-app/
ejbs/
appclient/

The META-INF directory contains the application.xml deployment descriptor. The other directories
contain the various J2EE modules that make up the application. (Note that J2EE modules are not the same
thing as Dynamo modules. A single Dynamo module can contain multiple J2EE applications, each of
which may be made up of multiple J2EE modules.)
There are several different types of J2EE modules, corresponding to various types of J2EE components.
For example, an EJB module contains EJBs, while a Web application module contains JSPs, JSP Tags, and
Servlets. In the simpleJ2EE application, there is a Web application module at web-app, an EJB module at
ejbs, and an application client module at appclient.

21
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

Building and Running the Application


In its starting form, the simpleJ2EE example contains only Java source code. Before it can be deployed, the
various source files must be compiled into class files. Additional deployment information must be
supplied in a dynamoJ2EESpecifier.xml file. Finally, the entire structure can optionally be packaged
into a Dynamo Archive (DAR) file, which means that each J2EE module is packaged in the appropriate
archive format, and then these module archives plus supporting files are packaged in a single archive file.
The resulting file has an extension of .dar.
Dynamos deployment tool, called Darina, can perform all of these functions. Darina is a combination
build and deploy tool. Darina can take a J2EE application in source form, such as the above example, and
produce a fully deployed, runnable application, either in the staging directory, or packaged as a DAR file.
You then add either the staging directory or the DAR file to the list of applications managed by the J2EE
container and restart Dynamo. Dynamo then runs the new J2EE application along with any other J2EE
applications it has been configured to run.
You can use Darina to build and deploy an application incrementally. You make changes to the
applications source files, then re-run Darina in incremental build mode. Darina examines the J2EE
application directory and recompiles only those files that have changed. If the application is in a DAR file,
Darina optionally overwrites the old DAR file with the new DAR file containing the modifications.

Using Darina to Build and Deploy the Application


To begin building the application, you run Darina. From the <DAS6dir>/home directory, Darina can be
run like this:
bin/runDarina ../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE -build

Note that Darina does not have to be run from the <DAS6dir>/home directory, but the examples in this
document assume that to be the case.
The -build flag indicates that Darina should compile any necessary source files. In the simpleJ2EE
example, all of the source files are contained in the applications directory hierarchy.
If all of the necessary configuration information has been supplied, the command above produces a DAR
file. The name of the file is the name of the staging directory, plus the .dar extension. For example:
../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE.dar

Note that if a DAR file by that name already exists, it is replaced by the newly created DAR file. If you want
to keep the older DAR file, move it to a different location before running Darina.
If you are iteratively modifying, building, and testing the application, you can use the no-dar flag to
instruct Darina not to create a DAR file. You can then run the application directly from the staging
directory. The command to run Darina would be:
bin/runDarina ../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE
build no-dar

22
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

The first time Darina is run against a new J2EE application, it creates a new dynamoJ2EESpecifier.xml
file, marking out the portions that need to be filled in, and stores it in the META-INF/DYNAMO-INF/
directory. You must modify this file and to supply the Dynamo-specific information needed to deploy the
application, such as mappings of resource references, and mappings of container-managed entity beans
to repositories.
In the case of the simpleJ2EE example, the first time Darina is run, it creates a
dynamoJ2EESpecifier.xml file that looks like this:

<?xml version="1.0"?>
<!DOCTYPE dynamo-j2ee-specifier SYSTEM
"http://www.atg.com/j2ee/dtds/dynamoJ2EESpecifier_1_3.dtd">
<dynamo-j2ee-specifier>
<application-name>
simpleJ2EE
</application-name>
<ejb-jar>
<module-uri>
ejbs
</module-uri>
<enterprise-beans>
<session>
<ejb-name>
AddNumbers
</ejb-name>
</session>
</enterprise-beans>
</ejb-jar>
<war>
<module-uri>
web-app
</module-uri>
</war>
<app-client>
<module-uri>
appclient
</module-uri>
</app-client>
</dynamo-j2ee-specifier>

The application-name gives the application a name that is used by Dynamo in the administrative
interfaces, and is also used to form the remote JNDI names for EJB homes. Two applications running in
Dynamo cannot have the same application-name.
Each J2EE module then has an entry identified by the modules URI. Within each ejb-jar module, each
EJB is listed, identified by its ejb-name.

23
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

At this point, you typically need to fill in additional Dynamo-specific deployment information. However,
simpleJ2EE doesnt have any resource references, references to external EJBs, or entity EJBs, so it doesnt
require any additional deployment information. The dynamoJ2EESpecifier.xml file is complete as it
stands, without any additional blanks to fill in.
Therefore, you can now run Darina again to complete the deployment process. The second time Darina is
run, it validates the application directory hierarchy, compiles any necessary files, and optionally creates
the file simpleJ2EE.dar.
Notice that any generated files, such as .class files, are placed in the same directories as the
corresponding source files. Darina does not modify any source files, but it does create new files in the
applications directory hierarchy. This can cause problems if these directories are under source control.
For information about how to use Darina with applications that are under source control, see Variations
on the Build/Deploy Process.
Typically, while developing an application, you need to make incremental changes to the source code,
update the dynamoJ2EESpecifier.xml file, and rebuild the application. You may need to perform these
steps many times. Running Darina with the no-dar flag and then running the application from the
staging directory simplifies this process greatly.
When your application is complete, however, it is a good idea to create a DAR file. The DAR file contains
the complete, deployed J2EE application that can be run on a Dynamo server. The DAR file can be moved
to a different location, distributed to multiple Dynamo instances, or archived for later use.

ejb-client-jar Files
The classes in a J2EE module can reference each other, but they cannot reference classes in other
modules. For example, classes in a Web application do not have free access to classes in an EJB module, or
even in another Web application module in the same application. This means that the namespaces of the
modules are separated - two Web application modules might have classes with the exact same name, but
they will be treated as separate classes. This allows modules to be combined without danger of
namespace collisions.
Of course, this presents an immediate problem since the classes in a Web application may need to access
the home and remote interfaces in an EJB module. In the case of simpleJ2EE, the AddNumbersTag in the
Web application makes reference to the AddNumbersHome and AddNumbers EJB interfaces.
To address this problem, J2EE includes the notion of an ejb-client-jar. This is a JAR file, stored at the top
level of the application, that contains just the class files needed by clients of an EJB module. For example,
clients will need access to the home and remote interfaces (such as AddNumbersHome and AddNumbers),
but do not need access to the EJB implementation classes (such as AddNumbersEJB). So the ejbclient-jar will contain a subset of the classes in the EJB module.
Application developers can create ejb-client-jar files manually. However, this can be a tedious task
that is best left to Darina. If an application does not supply its own ejb-client-jar, Darina will
automatically construct the ejb-client-jar, taking its best guess as to what classes need to go into
that JAR file. Darina does this by compiling each home and remote interface and implementation class,
and seeing what class files the home and remote interfaces depend on. The result should be class files
corresponding to the home and remote interfaces, as well as any classes referenced by those interfaces,

24
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

any classes referenced by those classes, etc. Those class files are put into a JAR file and used as the ejbclient-jar.
These ejb-client-jars are then added to the CLASSPATH of any other modules that have ejb-links
to that modules EJBs. For example, when simpleJ2EEs Web application is compiled, the ejb-clientjar from the EJB module is included in the CLASSPATH, thereby allowing the AddNumbersTag to
reference the AddNumbersHome and AddNumbers interfaces at compile and run time.

Precompiling JavaServer Pages


When you run Darina with the build flag, it compiles Java source files (e.g., for servlets or EJBs) into the
.class files that are executed when the application is run. By default, however, Darina does not compile
JSPs. Instead, each JSP is compiled the first time it is accessed by a user. As a result, some users may
experience significant waits for pages to render and display.
To avoid these delays, you can have Darina precompile the JSPs when you build the application. To
precompile the JSPs, invoke Darina with the jsp-compile flag. For example:
bin/runDarina ../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE
build jsp-compile

Compiling a JSP is a two-step process. First, the JSP is translated into a Java source file, and then the Java
file is compiled into a .class file. The .class file is a servlet that is executed when a user accesses the
page.
The compiled .class files are stored in the WEB-INF/DYNAMO-INF/jspbuild subdirectory of the Web
application (in both the staging directory and the DAR file). Note that each time an JSP file is modified, it
must be recompiled to pick up the changes. Darina compiles JSPs incrementally; i.e., if a JSP file has a
corresponding .class file that was created more recently than the modification date on the JSP, Darina
does not compile the JSP, because its .class file is assumed to be up to date.
By default, Darina precompiles only files with the extension .jsp. If you have any page fragments that
cannot be compiled on their own, give these files a different extension (such as .jspf), so Darina will not
attempt to compile them.

Configuring the Batch Compiler


When you run Darina with the jsp-compile flag, it starts up a lightweight web container running the
/atg/dynamo/service/JspBatchCompiler component, which controls the compilation of the JSPs. By
default, JspBatchCompiler uses a reduced CONFIGPATH (consisting of the DAS CONFIGPATH plus a
special directory used only for batch compilation). You can use Darinas jsp-compile-config-path
flag to specify a different CONFIGPATH, but this should generally be unnecessary.
You can also modify the behavior of the batch compiler by changing the JspBatchCompiler
components property values. In particular, you may want to use the following properties to control which
files Darina precompiles:
includeFiles
A regular expression pattern to determine which files to compile. If a files name
matches the includeFiles pattern, Darina compiles the file. Darina does not compile

25
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

any files whose names dont match this pattern. By default, matches files with the
extension .jsp.
excludeFiles
A regular expression pattern to determine which files to exclude from compilation. If a
files name matches the excludeFiles pattern, Darina does not compile the file,
regardless of whether its name also matches the includeFiles pattern. Default is
null.
The JspBatchCompiler component calls the /atg/dynamo/servlet/pagecompile/PageProcessor
component, which performs the actual compilation. For more information about the PageProcessor
component, see the ATG 6 Installation and Configuration Guide for Dynamo Application Server.

Running the Deployed Application


Once an application has been deployed, you can run it by adding it to the list of applications maintained
by the /atg/dynamo/service/j2ee/J2EEContainer component. You specify the list through this
components applications property, which can include DAR files, staging directories, or a combination
of each.
Typically, an application is added to the list by creating a J2EEContainer.properties file that appends
the application to the value of the applications property. The J2EEContainer.properties file is
located in the config/atg/dynamo/service/j2ee/ directory within the Dynamo module that the
application is part of. To run the simpleJ2EE application, add the following line to the
J2EEContainer.properties file for the J2EE-Examples.SimpleJ2EE module:
applications+=\
{atg.j2eeserver.root}/J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE

This line adds the simpleJ2EE staging directory to the list of applications that run in the J2EE container. If
the application were in a DAR file, the entry would be:
applications+=\
{atg.j2eeserver.root}/J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE.dar

To run the module, start up Dynamo and specify the module using the m switch:
bin/startDynamo -m J2EE-Examples.SimpleJ2EE

You can specify multiple modules using this switch. For example:
bin/startDynamo -m J2EE-Examples.SimpleJ2EE DSSJ2EEDemo

Once Dynamo has completed its startup, the simpleJ2EE application should be running. Verify this by
accessing the following URL:
http://{hostname}:8840/simpleJ2EE/

26
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

This URL displays the applications index.jsp page, which calculates the sum of 17 and 49 and prints the
result. The page also contains a link to a servlet named SimpleServlet. Clicking this link executes the
servlet, which displays a page containing the text This page was generated by a servlet.

Running the Application Client


The simpleJ2EE application includes an application client that remotely accesses the AddNumbers EJB and
prints the result of adding two numbers. The application client and EJB do not need to be on the same
machine. The application client is invoked through a Dynamo script called runAppClient, which takes a
DAR file as one of its arguments. An application client must be run from a DAR file; it cannot be run from a
staging directory.
Dynamo should be started up and running, so that it is hosting the EJB. You can then run the application
client (from the <DAS6dir>/home directory) with the command:
bin/runAppClient ../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE.dar
-module-name default orb-host localhost orb-port 8820

This command runs the application client, which prints the sum of 18 and 95, and then exits.
Note that the runAppClient command can only run an application client if it is part of a J2EE application.
It is also possible to write clients that are not part of any J2EE application, but still communicate with EJBs
in a J2EE application. For information about running this type of application client, see the Lightweight
Application Clients section of the Application Clients chapter.

Monitoring a Deployed Application


Once a J2EE application is deployed and running in Dynamo, you can monitor it through the Dynamo
Administration UI. To monitor a J2EE application, click the J2EE Container link on the top-level page of
the Administration UI. This link takes you to a page with has links to each J2EE application running in the
J2EE container. Each application has links to each of its modules, and each module has links to the
individual components (EJBs, Servlets, JSPs) in that module. These pages display selected statistics and
other information about the application, module, or component, and they include runtime controls, such
as links that start, stop, and reload applications.

Rebuilding an Application
Once you have built and deployed an application, you may need to modify it to fix bugs or add features.
After you make changes, you must rebuild the application for the changes to take effect. Darina makes
this simple through its incremental build feature, available through the build command-line flag. When
you rebuild an application that has already been deployed, Darina determines which files have changed
and recompiles only those files.
For example, modify the SimpleServlet.java source code found in the web-app/WEBINF/classes/atg/simpleJ2EE directory of the simpleJ2EE application. Find this line:
out.println ("<p>This page was generated by a servlet");

Change it to this:

27
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

out.println ("<p>This page was generated at " +


System.currentTimeMillis ());

Then, from the <DAS6dir>/home directory, re-run Darina using the build flag:
bin/runDarina ../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE
build no-dar

Darina will detect that SimpleServlet.java is the only file that has changed, and will recompile it.
If you shut down Dynamo and restart it, it will run the new version of the application. You can also run the
new version of the application without restarting Dynamo, as described in the Reloading an Application
section.
There are some instances when an incremental build will not work correctly. If an interface changes, for
example, that affects not only the interface class, but also those classes that implement the interface.
Darina cannot detect all of these dependencies, so it will recompile only the interface class, because it is
the only source file that changed. The same situation arises for classes that resolve other classes
dynamically by name, or for classes that act as superclasses for other classes, etc.
In these situations, you should rebuild the entire application. To do that, run Darina with the -buildall
flag. Darina will recompile all source files, regardless of whether they have changed. For example:
bin/runDarina ../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE
-buildall no-dar

A complete rebuild takes longer than an incremental rebuild, but it ensures that all of the compiled
classes are up to date. In a typical development cycle, incremental rebuilds should generally be sufficient.
A complete rebuild is necessary only if you see problems, such as class loading errors, that indicate that
some classes are not up to date.
When creating a final build for release onto a live site, however, you should always do a complete (rather
than incremental) build. In addition, you should run Darina without the no-dar flag, so that Darina
creates a DAR file that you can then copy to the site.

Reloading an Application
As mentioned in the previous section, if you modify an application and then restart Dynamo, it will run
the new version of the application. However, Dynamo can also reload a J2EE application on the fly,
without restarting the server. This is very convenient at development time, when you may need to modify
and restart the application frequently.
During the development process, you can run Darina with the no-dar flag, and then run the application
from the staging directory. This approach is much faster than creating a DAR file each time you make
changes to the application, because it avoids both the packaging and unpacking of the DAR file:
1.

On the J2EE Container page of the Dynamo Administration UI, click on the link for the
application. This takes you to a page with information about the application.

2.

Click the Stop Application link to shut down the application.

28
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

3.

Make changes to the application.

4.

Run Darina with the no-dar flag.

5.

Click the Reload Application link to run the new version of the application.

Note that the previous version of the application is no longer available at this point. If you need to keep
an older version of the application, you should create a DAR file from that version before making any
changes.

Reloading an Application in a DAR File


An alternate approach is to create and load a new DAR file after each time you modify the application.
Builds take longer if you use this approach, but it allows you to start the new version of the application
while the old version is still running.
When Dynamo starts up, it starts all of the J2EE applications listed in the applications property of the
J2EEContainer component. If an application is stored in a DAR file, Dynamo unpacks the DAR file itself,
and then unpacks the module archives contained in the DAR file. Dynamo unpacks application the
application into <ATG6dir>/home/j2ee/runtime. Multiple DAR files can be running in a single instance
of Dynamo, each unpacked into its own subdirectory within runtime.
If a DAR file has already been unpacked into the runtime directory and has not changed since then,
Dynamo skips the potentially time-consuming process of unpacking the application. If a DAR file has
changed since the last time it was unpacked, Dynamo removes the older unpacked version and unpacks
the new DAR file.
To load a new version of an application without shutting down the old one:
1.

Make changes to the application.

2.

Run Darina (without the no-dar flag) to create a new DAR file.

3.

Replace the DAR file in the Dynamo module with the new DAR file.

4.

On the J2EE Container page of the Dynamo Administration UI, click on the link for the
application. This takes you to a page with information about the application.

5.

Click the Reload Application link.

The new DAR file is unpacked into the <ATG6dir>/home/j2ee/runtime directory, but under a different
name from the old unpacked DAR file. After unpacking the new DAR file, Dynamo starts up the new
version of the application. The old version will finish handling any existing requests and threads, but all
new ones will be directed to the new version.
Note that depending on the differences between the two versions, this switchover can result in errors; for
example, a session that started in the old version might be missing some data that the new version
requires. Also, if an external client has references to EJBs in the old version, these references will become
invalid and the client will need to acquire references to EJBs in the new version. Therefore this approach is
not recommended on production systems.

29
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

Using Command-Line Tools


Dynamo includes a set of command-line tools that you can use for loading, reloading, and stopping
applications in DAR files: loadDarFile, reloadDarFile, and stopDarFileApps. These tools may be
preferable to the Administration UI in some cases. For example, to automate the process of loading and
deploying applications, you can write a script that makes the appropriate calls to these commands and to
the runDarina command.
These commands are found in <DAS6dir>/home/bin. Their syntax is:
commandname [servername] -user username -password password darFilePath

So, for example, to reload the simpleJ2EE DAR file (assuming the current directory is <DAS6dir>/home
and you are using the default admin account), the command would be:
bin/reloadDarFile user admin password admin
../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE.dar

Maintaining the Runtime Directory


If an instance of Dynamo is running a large number of J2EE applications, there may be a buildup of
unpacked applications in the runtime directory. As long as the DAR files are still present in their Dynamo
modules, you can safely remove the unpacked applications; the next time it starts up, Dynamo will
unpack the DAR files that it needs. Note that you should shut down Dynamo before removing
applications from the runtime directory, to ensure that there are no users trying to access the
application.

Suggested Development/Deployment Approach


As discussed above, there are two main approaches you can use when developing and deploying a new
J2EE application:

Create a new DAR file each time you make changes to the application, and then run
the application from the DAR file.

Skip the creation of the DAR file, and run the application from the staging directory

Having both of these options gives you a great deal of flexibility, but there is a potential pitfall. You must
make sure that the applications property of the J2EEContainer component is set properly, or you
may inadvertently run the wrong version of the application.
For example, suppose you have the applications property set to run the application from a DAR file. If
you make subsequent changes to the application, you must be sure to generate a new DAR file.
Otherwise, the version of the application in the DAR file will be older than the version in the staging
directory, but Dynamo will still run the DAR version, since thats what the applications property points
to.
In practice, though, this situation is easy to avoid. On development machines, it is a good idea to run the
application directly out the staging directory, since this is fastest and easiest, and simplifies the iterative
modify/build/test process. On the live site, however, it is generally easiest to run the application from a
DAR file, since you will typically be deploying applications built on development machines, and it is much

30
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

easier to copy over a single DAR file than a set of directories. In addition, Darina validates the application
when you build the DAR file, so it does not have to be validated when it is loaded.
The recommended development/deployment approach, then, is as follows:
1.

On your development machine, set the applications property of the


J2EEContainer component to run the application from the staging directory.

2.

Iteratively modify, build, and test your application. Each time you build the
application, run Darina with the no-dar flag.

3.

When you are satisfied that the application is complete, run Darina again, this time
without the no-dar flag, so that Darina generates a DAR file. For this build, it is also a
good idea to use the buildall flag, so Darina recompiles all of the source files.

4.

On the live site, create a Dynamo module for the application. Set the applications
property of the J2EEContainer to run the application from the DAR file.

5.

Copy the DAR file from the development machine to the appropriate location on the
live site, and restart Dynamo.

If you follow this approach, you never need to switch the J2EEContainer.applications property
between running the application from the staging directory and running it from a DAR file. Even when
you generate a DAR file on the development machine, the version of the application in the staging
directory will always be up to date, because the application is always built in the staging directory first,
regardless of whether it is subsequently packaged as a DAR file. And since the builds are never actually
done on the live site, the live site has only the DAR file available to run.
Note that this approach works even if you need to make further changes to the application once it is on
the live site. Just make the changes on the development machine (once again iteratively modifying,
building, and testing), and when you are finished, generate a DAR file. Then copy the DAR file to the live
site (overwriting the existing DAR file), and restart Dynamo.

Variations on the Build/Deploy Process


The previous sections outlined the build and deploy process that is supported most strongly by Dynamos
tools. However, some development organizations may not be able to adapt their development processes
to the above procedures. The following sections describe some variations on the build and deploy
process that are supported by Darina.

External Source Tree


The incremental build process described previously makes the assumption that the Java source files will
be stored in the application directory. The resulting class files end up in the same directory, next to the
original source files.
The development processes in some organizations may mandate that source files be kept in a separate
tree, probably managed under source control. That tree might contain all of the organizations source
code, a portion of which would be used to generate the application. For example, a developers local copy
of the source tree might look something like this:

31
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

/sources/Java/

/sources/Java/atg/
/sources/Java/atg/simpleJ2EE/
/sources/Java/atg/simpleJ2EE/AddNumbers.java
/sources/Java/atg/simpleJ2EE/AddNumbersEJB.java
/sources/Java/atg/simpleJ2EE/AddNumbersHome.java
/sources/Java/atg/simpleJ2EE/AddNumbersLocal.java
/sources/Java/atg/simpleJ2EE/AddNumbersLocalHome.java
/sources/Java/atg/simpleJ2EE/AddNumbersTEI.java
/sources/Java/atg/simpleJ2EE/AddNumbersTag.java
/sources/Java/atg/simpleJ2EE/SimpleServlet.java
/sources/Java/atg/personalizationDemo/...
/sources/Java/atg/website/...
...

In this setup, the source files are no longer located in the J2EE-Examples/SimpleJ2EE/j2eeapps/simpleJ2EE directory, and are instead drawn from this external directory tree. The J2EE
application directory is still required, containing all of the deployment descriptors and Dynamo J2EE
Specifier file.
Darinas incremental build process can still work in this environment. Darina just needs to be told that the
source files are not in the application directory, but are instead located in an external directory. This is
done in the Dynamo J2EE Specifier file, on a per-module basis. For example:

<dynamo-j2ee-specifier>
<ejb-jar>
<module-uri>
ejbs
</module-uri>
<build>
<source>
<source-type>
ExternalJavaSource
</source-type>
<base-dir>
/source/Java
</base-dir>
<sub-dir>
atg/simpleJ2EE
</sub-dir>
</source>
</build>
...
</ejb-jar>
<war>
<module-uri>
web-app

32
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

</module-uri>
<build>
<source>
<source-type>
ExternalJavaSource
</source-type>
<base-dir>
/source/Java
</base-dir>
<sub-dir>
atg/simpleJ2EE
</sub-dir>
</source>
</build>
...
</war>
</dynamo-j2ee-specifier>

Notice that a build tag must be specified for each module, thereby allowing different modules to draw
upon different source trees. Also notice that both the root of the source tree (/source/Java) and the
actual subdirectory to be compiled (atg/simpleJ2EE) must be specified. Multiple subdirectories may be
specified. Multiple source tags may also be specified, in which case they will be built in the order they
appear in the file.
If Darina is run with the -build flag, it will run in an incremental build mode, compiling source files from
the specified directories into class files within the application directory. The compilation occurs
recursively - if a source directory has subdirectories, then those subdirectories will also be compiled.
The advantage of this development model is that it keeps all of an organizations Java source files in a
single place. The disadvantage is that it does not take advantage of the namespace separation offered by
J2EE modules. For example, the ejbs module might contain a class called atg.simpleJ2EE.Constants,
while the web-app module might also contain a completely different class with the same name. This is
legal in a J2EE application, but if all source files are in the same directory tree, then this cannot be done.
Modules must instead be separated into different subpackages - for example, atg.simpleJ2EE.ejb and
atg.simpleJ2EE.web. This is, in fact, not a bad way to organize application source files.

External Build Tree


Some development organizations may not only have a separate source tree, but might also have a
compilation process that automatically compiles those sources into a separate build tree. For example:

/build/
/build/atg/
/build/atg/simpleJ2EE/
/build/atg/simpleJ2EE/AddNumbers.class
/build/atg/simpleJ2EE/AddNumbersEJB.class
/build/atg/simpleJ2EE/AddNumbersHome.class

33
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

/build/atg/simpleJ2EE/AddNumbersLocal.class
/build/atg/simpleJ2EE/AddNumbersLocalHome.class
/build/atg/simpleJ2EE/AddNumbersTEI.class
/build/atg/simpleJ2EE/AddNumbersTag.class
/build/atg/simpleJ2EE/SimpleServlet.class
/build/atg/personalizationDemo/...
/build/atg/website/...
...

In this case, Darina does not need to know where the source files are. Darina just needs to be told where
the class files are so they can be copied into the DAR file. Once again this is done by using a build tag,
but using a source-type of ExternalClassSource:

<dynamo-j2ee-specifier>
<ejb-jar>
<module-uri>
ejbs
</module-uri>
<build>
<source>
<source-type>
ExternalClassSource
</source-type>
<base-dir>
/build
</base-dir>
<sub-dir>
atg/simpleJ2EE
</sub-dir>
</source>
</build>
...
</ejb-jar>
<war>
<module-uri>
web-app
</module-uri>
<build>
<source>
<source-type>
ExternalClassSource
</source-type>
<base-dir>
/build
</base-dir>
<sub-dir>

34
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

atg/simpleJ2EE
</sub-dir>
</source>
</build>
...
</war>
</dynamo-j2ee-specifier>

A major drawback of this approach is that the ejb-client-jar files may not be created properly, since
Darina does not have access to the Java source files. Unless a development organization is prepared to
create the client-jar files itself, it should avoid this approach.

Internal Source Tree


The default mode for Darinas incremental build process is to look for source files in the application
directory itself. This can be specified explicitly using a source-type of JavaSource. Specifying this
explicitly is most useful when combined with external source files. This allows Darina to read and compile
source files from both the application directory and an external directory:

<build>
<source>
<source-type>
JavaSource
</source-type>
<base-dir>
/users/rsmith/Java
</base-dir>
</source>
<source>
<source-type>
ExternalClassSource
</source-type>
<base-dir>
/build
</base-dir>
<sub-dir>
atg/simpleJ2EE
</sub-dir>
</source>
</build>

The base-dir tag is required, and must specify a directory relative to the modules root. The sub-dir tag
is optional; there can be any number of sub-dir tags that specify directories relative to the base-dir.

35
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

Specifying Another Java Compiler


By default, Darina will use javac to compile its source files. Darina can be directed to use another
compiler - perhaps one that is faster, or does more error checking. This is specified in a source tag:

<build>
<source>
<source-type>
JavaSource
</source-type>
<compile-command>
javac -classpath {1} -d {2} {0}
</compile-command>
</source>
...
</build>

This specifies that source files will be found in the application directory (the default), and they will be
compiled using the command javac -classpath {1} -d {2} {0} (also the default). The {?}
expressions are placeholders for the actual values that will be supplied by Darina at runtime:

{0} - the name of the Java source file

{1} - the classpath

{2} - the destination directory

Another compile command may be specified using this format. A different compile command can be
specified for each source tag
You can also specify a compiler using the DAR_COMPILER environment variable in your environment.sh
or environment.bat file. For example, you might include an environment setting like this:
DAR_COMPILER="/usr/local/bin/jikes +E -classpath {1} -d {2} {0}"

Note that if the compile command is specified both in the dynamoJ2EESpecifier.xml file and in the
environment.sh or environment.bat file, Darina uses the command specified in the
dynamoJ2EESpecifier.xml file.

36
3 - Creating a Sample J2EE Application

ATG 6 J2EE Development and Deployment Guide

4 Web Applications

This chapter discusses key aspects of building, configuring, and deploying web applications in Dynamo. It
includes the following topics:
Overview of Web Applications
How Dynamo Processes a JSP Request
Resources in web.xml
Adding New Resources to web.xml

Overview of Web Applications


The J2EE platform encompasses a wide range of technologies for building enterprise applications. Some
of these technologies, such as JMS and JDBC, provide underlying infrastructure, handling tasks such as
communication between components of an application, or communication between the application and
the database.
Other technologies provide the core building blocks for applications. These include servlets, JSPs, EJBs,
resource adapters, and application clients. Using all of these technologies together, you can build multitiered enterprise applications that run in distributed environments and interoperate with legacy systems.
This flexibility makes the J2EE platform extremely powerful, but comes at the cost of significant
complexity.
Fortunately, although a J2EE compliant application server is required to support all of the various J2EE
technologies, individual applications do not need to use them all. J2EE includes the concept of a Web
application, in which the building blocks are servlets and JSPs. A Web application can be a module in a
larger application that may use EJBs, resource adapters, or application clients, or it can be a standalone
application.
As the name implies, standalone Web applications are ideally suited for Web sites. In a standalone Web
application, servlets and JSPs on the server render HTML pages that users interact with through Web
browsers. The application communicates with a database via JDBC, rather than using EJBs to manage data
persistence. Standalone Web applications are conceptually quite similar to JHTML-based Dynamo
applications, with the primary difference being the use of JSP rather than JHTML as the dynamic page
language. You can incorporate ATG 6 personalization, commerce, and publishing features in your Web
applications by using the DSP tag libraries in your JSPs. These tag libraries allow you to embed Nucleus
components (such as servlet beans and form handlers) in JSPs, much as you would in JHTML pages.

37
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

web.xml File

The main deployment descriptor for a web application is the web.xml file. This file, which is stored in the
WEB-INF directory of the WAR file, contains configuration information for the web application and its
components (servlets, tag libraries, and JSPs).

Standalone WAR Files


A standalone Web application is typically packaged in a WAR file that is not part of an EAR file. The
application can be deployed directly from the WAR file.
Standalone WAR files are very similar structurally to other WAR files, but there are some minor differences
due to the lack of an EAR file:

There is a META-INF directory at the top level of the WAR file that is similar to the
META-INF directory of an EAR or DAR file. Dynamo puts the DYNAMO-INF directory,
which contains the dynamoJ2EESpecifier.xml file, in this META-INF directory.

There is no application.xml deployment descriptor, so the context root for the web
application is declared in the web.xml file. You do this by declaring a context
parameter named context-root, and setting its value to the context root.

Also, because there is no application.xml file, there is no alt-dd mechanism for


specifying an alternate web.xml file. Therefore, when Darina creates the WAR file, if
there are any tags in the dynamoJ2EESpecifier.xml file that override web.xml
settings, Darina modifies the web.xml file to include those tags. (If you want to keep
the previous version of the web.xml file, make a copy with a different name before
generating the WAR file.)

Web Services
Most of the information in this chapter concerns web applications that end users interact with through a
web browser client. However, there is another type of web application, in which the client is a remote
application that interacts with ATG 6 through Web services. The web application contains one or more
Web services, which are implemented based on the JAX-RPC (Java API for XML-based RPC) specification.
The web.xml file defines how calls these Web services are dispatched. For more information about Web
services in ATG 6, see the ATG 6 Web Services and Integration Framework Guide.

How Dynamo Processes a JSP Request


When a user requests a JSP page, that request is sent to the Web server as a stream of information that
the Web server parses and holds in an HTTPServletRequest object.

38
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

Requested page
displays

User clicks a link

DAS Servlet Pipeline

DAS

Dynamo
Handler

Final DAS Servlet Pipeline servlets

Web
Application
Dispatcher

Web
Application

Custom
servlets
(JSPs
included)

Custom
filters

The Web server passes the HTTPServletRequest to DAS, which initiates the DAS servlet pipeline by
calling the first servlet. That servlet, DynamoHandler, creates an instance of a
DynamoHTTPServletRequest (referred to as the request) that wraps the HTTPServletRequest so that
servlets are not only able to read information on the request (standard functionality provided by
HTTPServletRequest), they can also modify the request itself (added benefit provided by
DynamoHTTPServletRequest).
The request is passed on to a series of pipeline servlets that are designed to insert themselves in the
pipeline when the information they process is included in the request. Although some servlets process
standard information thats common to all requests, the ordering and variety of the servlets in the
pipeline depends on the request contents. For more information about request handling, see Request
Handling and the DAS Servlet Pipeline chapter of the ATG 6 Installation and Configuration Guide for Dynamo
Application Server.
All requests to J2EE applications encounter the ContextPathServlet pipeline servlet, which takes the
context path supplied by the request and matches it to the context root/Web application pair in the
application.xml deployment descriptor. ContextPathServlet appends the Web application name
to the request so that WebApplicationDisplatcherServlet asserts itself next in the pipeline and
passes the request to the J2EE container.
Once the Web container receives the request, it passes the request to the Web application named in the
request, which then invokes the resources defined in web.xml in the manner outlined by the Servlet 2.3
specification.

39
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

Resources in web.xml

Each Web application comes with a deployment descriptor called web.xml that includes information that
the J2EE application requires to run the module. This section describes how the application server
accesses web.xml and the resources it contains. For general information about web.xml, see the Servlet
2.3 Specification.
The Web application deployment descriptor specifies a series of resources that are instantiated and
configured based on the settings specified here. You are required to include the DTD declaration and the
Web application name in your web.xml just as you would for any other J2EE application. Remember to
use the same name for the Web application in web.xml and the J2EE deployment descriptor
(application.xml). There are no additional ATG-specific resources that you need to include here,
although you may want to browse the list of optional resources provided by ATG 6. Most applications will
require site-specific resources.

Optional Resources
Although these resources are not required, they are provided with your ATG 6 installation because they
may be of use to you.

Context Parameters
The context-root context parameter is a mechanism for making a Web application context root visible
to the Scenario engine when a change is made to the context root defined for a live site. See the Setting
the Web Application Context Root for Scenarios section of the Configuring Scenarios chapter of the ATG 6
Personalization Programming Guide.

Tag Libraries
There are two ways to make a tag library available to a Web application. The first way is to put the tag
library class files and TLD in the Web application WEB-INF directory and specify the URI value, which
matches the value in the JSPs that use the tag library, in the TLD itself. All ATG tag libraries are
implemented in this fashion. The second way uses web.xml to define the tag library URI and TLD location.
Again, the URI indicated here must match the one used in JSPs. It makes no difference which method you
use.
One benefit to having two ways to implement a tag library is that, if you find it more convenient to use
two URIs for one tag library, you can do so by declaring the tag library in web.xml with one URI and
keeping the tag library files, including the TLD that defines a second URI, in WEB-INF.
Heres how you would declare the DSP tag library declaration in web.xml:

<taglib>
<taglib-uri>/dspTaglib</taglib-uri>
<taglib-location>/WEB-INF/taglibs/dspjspTaglib1_0.tld</taglib-location>
</taglib>

For more information about the DSP tag libraries, see the ATG 6 Page Developers Guide.

40
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

Web Services
The Web services that are made available by your Web application need to be described here. It is
recommended that you designate a separate J2EE application for some or all of your Web services so Web
services and application code are kept in distinct packages. Also, keeping your Web services in a
dedicated J2EE application means that each Web application (perhaps some Web services are kept in one
application, some are kept in another) is started as a distinct module in ATG 6.
ATG 6 includes several Web services, which are packaged in one of three J2EE applications. See the
chapter for a particular Web service to find out the J2EE and Web applications that contain it. Any new
Web services that you create using the ATG Web Service Creation wizard will automatically come with
fully-configured web.xml files.
For more information about Web services and ATG 6, see ATG 6 Web Services and Integration Framework
Guide.

Adding New Resources to web.xml


Its likely that you will want to include resources in your Web application that allow you to pass dynamic
information to Nucleus components through the Dynamo request. These resources (context parameters,
filters, servlets, web services, tag libraries, etc.) you create need to be consistent with the J2EE (or W3C as
is the case with Web services) standards described in their respective specifications. Then, you need
register the custom resources with the Web application by adding them to web.xml in accordance with
the J2EE 1.3 Specification.

Creating Filters and Servlets


Its likely that the filters and servlets you create will need to access the Dynamo request and response
objects in order to make modifications to data they retrieve during the pipeline-processing. To do so,
code your filters and servlets as follows:
1.

Import atg.servlet.DynamoHttpServletRequest,
atg.servlet.DynamoHttpServletRequest, and atg.servletServletUtil.

2.

Call ServletUtil.getDynamoRequest(request). This method returns a reference to


the DynamoHttpServletRequest.

Add filters and servlets to web.xml by following the J2EE 1.3 instructions.
The example described in the Filter Example section accesses the request and response in this manner. It
also resolves a component in Nucleus, which is another common operation that could be handled by a
filter. Any resource that makes calls to a Nucleus component must also provide a means for discerning
that components Nucleus address. For instructions on how to do this, see the Basic Nucleus Operation
section of the Nucleus: Organizing JavaBean Components chapter of the ATG 6 Dynamo Programming
Guide.

41
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

Filter Example

This filter accesses the Dynamo request and response objects and retrieves the Profile object attached
to the request. Next, the filter finds the Profile ID on the Profile object and saves is an attribute of the
request. Finally, the filter passes control to the filter chain so it will determine the next resource to call.
Keep in mind that this code sample may not provide the most efficient means for obtaining the Profile
object, but rather it demonstrates an easy to follow method that illustrates how a filter operates in the
context of a filter chain.

import atg.servlet.ServletUtil;
import atg.servlet.DynamoHttpServletRequest;
import atg.servlet.DynamoHttpServletResponse;
import atg.userprofiling.Profile;
import javax.servlet.*;
import javax.servlet.http.*;
/*
* An example filter that demonstrates how
* to get the DynamoHttpServletRequest
* in a Filter.
*/
public class MyFilter
implements Filter {
/*
* Called when MyFilter is started
* by the application server.
*/
public void init(FilterConfig pConfig) {
// Initialize MyFilter here.
}
/*
* Called when MyFilter is about to
* be destroyed by the application server.
*/
public void destroy() {
// Cleanup MyFilter here
}
/*
* Called by the application server
* when this filter is involved in a request.
* Resolves the Profile nucleus component
* and adds the Profile id as a request
* attribute.
*/
public void doFilter(ServletRequest request,

42
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

ServletResponse response,
FilterChain chain)
throws IOException, ServletException
{
// Get the Dynamo Request/Response Pair
DynamoHttpServletRequest dRequest =
ServletUtil.getDynamoRequest(request);
DynamoHttpServletResponse = dRequest.getResponse();
// Resolve the Profile object
Profile profile =
(Profile)dRequest.resolveName("/atg/userprofiling/Profile");
// Add the Profile id as a request attribute
request.setAttribute("PROFILE_ID",
profile.getRepositoryId());
// Pass control on to the next filter
chain.doFilter(request,response);
return;
}
}

Specifying Session Timeouts


For each web application, you can specify how long a session can remain idle before it automatically
times out. You do this using the session-timeout tag in the web.xml file. The value of this tag is the
timeout value in minutes. For example, to set the timeout to an hour:

<web-app>
...
<session-config>
<session-timeout>60</session-timeout>
</session-config>
...
</web-app>

Note that each web application session is the child of a Dynamo session. By default, the Dynamo session
manager ignores web application timeouts, and just uses the session timeout of the parent Dynamo
session. To enable web application timeouts, create a SessionManager.properties file in
<ATG6dir>/home/localconfig/atg/dynamo/servlet/sessiontracking that contains this line:
observeWebAppTimeouts=true

A Dynamo session can have multiple child sessions, each representing a different web application that
the same user is accessing. The Dynamo session has its own timeout value, set (in milliseconds) by the
sessionInvalidationTime property of the SessionManager component. However, if
observeWebAppTimeouts is set to true, the Dynamo session will not time out before any of the web

43
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

application sessions. For example, if sessionInvalidationTime is set to 30 minutes (18000000


milliseconds), and a Dynamo session has a child session with a timeout of 60 minutes, the Dynamo
session will not actually time out after 30 minutes, because the child session has not yet timed out. The
Dynamo session waits to time out until all of its child sessions have timed out.

Enabling Session Failover


J2EE Web applications can use Dynamos mechanism for session backup and failover. This allows any
session-scoped attributes to be backed up to an external storage service, so that if one Dynamo goes
down, another Dynamo can take over its requests and sessions.
In order for a Web application to use session backup and failover, its web.xml file must include the
distributable element. For example, the web.xml file for Dynamo Meeting Manager includes:

<web-app>
<display-name>DynamoMeetingManager</display-name>
<description>A sample Dynamo J2EE Application</description>
<distributable/>
...
</web-app>

Note that including the distributable element makes it possible for a Web application to use session
backup and failover if they are enabled, but does not itself enable these features. For information about
enabling session backup and failover in Dynamo, see the ATG 6 Installation and Configuration Guide for
Dynamo Application Server.

Additional Configuration for Web Applications


This section provides information about DAS-specific configuration for web applications.

Specifying Web Mappings


The application.xml deployment descriptor has tags for mapping a Web application to a context path,
in order to separate applications from each other within the same URL space. Dynamo provides additional
mappings not encompassed by the context path. The web-application-mapping tag specifies what
form a URL must follow in order for it to be dispatched to the specified web application. The mapping can
specify the following parameters:

scheme - The protocol of the URL, which can be http or https. If the scheme tag is
omitted, the protocol is not considered when dispatching URLs.

host-pattern - The hostname, which can be a specific name or can contain wildcard
characters. The host-pattern tag is particularly useful if a server has more than one
virtual hostname, and you want to direct requests for different virtual hosts to

44
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

different Web applications. If the host-pattern tag is omitted, the hostname is not
considered when dispatching URLs.

uri-prefix The beginning of the pathname portion of the URL. This parameter is
required for all web-application-mapping tags.

For example, the following tags specify that any requests arriving over HTTPS, using any hostname
ending with .atg.com, with a URI starting with /purchase should be directed to this Web application:

<dynamo-j2ee-specifier>
...
<war>
<module-uri>
web-app
</module-uri>
<web-application-mapping>
<scheme>
https
</scheme>
<host-pattern>
*.atg.com
</host-pattern>
<uri-prefix>
/purchase
</uri-prefix>
</web-application-mapping>
...
</war>
...
</dynamo-j2ee-specifier>

There can be only one instance of each of these tags within a web-application-mapping tag; you
cannot, for example, specify multiple host-pattern values in a single mapping tag. However, you can
have multiple web-application-mapping entries for a single web application, and use them to specify
mappings for different schemes, hostnames, and URI prefixes.
Note: If you are using a third-party Web server, you must configure your Connection Module to recognize
context root mappings and web application mappings, so that the Connection Module can route requests
with these values to Dynamo. By default, Connection Modules are configured to route requests with the
.jsp MIME type extension to Dynamo. You can use the DynamoPath feature in the Connection Module to
specify the context root mappings and web application mappings that indicate J2EE requests should be
routed to Dynamo. See the ATG 6 Installation and Configuration Guide for Dynamo Application Server for
information about configuring Apache, IIS, and Sun ONE Connection Modules.

Enabling Listing of Directories


Dynamo provides a list-directories tag that you can use to enable listing of directories. If this tag is
set to True, a Web request for a directory (such as /products/) that is not satisfied by a welcome file

45
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

(e.g., index.jsp) will return a listing of the files in the directory. Listing of directories is generally not used
in production applications, so list-directories is False by default. You can override this setting:

<dynamo-j2ee-specifier>
...
<war>
<module-uri>
web-app
</module-uri>
...
<list-directories>
True
</list-directories>
...
</war>
...
</dynamo-j2ee-specifier>

Configuring Servlet Pooling


The servlet specification allows servlets to follow a single-threaded model, which means that they behave
correctly only if they are used by one thread at a time. A servlet declares that it follows this model by
implementing the javax.servlet.SingleThreadModel interface, a marker interface that contains no
methods.
Using a single-threaded model simplifies coding, but potentially introduces a performance bottleneck. If
there is only one instance of a single-threaded servlet, all requests for this servlet are processed
sequentially. If there are many simultaneous requests, the application may perform poorly. Therefore,
Dynamo uses instance pooling with single-threaded servlets to ensure high throughput.
Dynamo creates multiple instances of a single-threaded servlet and keeps those instances in a pool. When
a request arrives for that servlet, an instance is checked out from the pool to handle the request. When
the servlet finishes processing the request, it is returned to the pool, making it available for a new request.
If multiple requests arrive simultaneously, each request is handled by its own servlet instance from the
pool.
Single-threaded servlets are pooled using the same mechanism used to pool stateless session EJBs. The
pool starts with a minimum of instances and creates more instances as they are needed, up to a maximum
number. After a spike in usage, Dynamo periodically removes some of the instances remaining in the pool
to reclaim memory. By default, the minimum number of instances is 0, and there is no maximum. You can
override these defaults by explicitly specifying minimum and maximum values. For example:

<dynamo-j2ee-specifier>
...
<war>
...
<servlet>

46
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

<servlet-name>
SomeServlet
</servlet-name>
<max-pool-size>
40
</max-pool-size>
<min-pool-size>
10
</min-pool-size>
</servlet>
...
</war>
...
</dynamo-j2ee-specifier>

Specifying the Ordering of Filters


If a requests URI matches the mappings of two or more filters, the web container must determine the
order in which to execute the filters. By default, Dynamos web container bases this order on the
precedence rules for mapping servlets to URIs, as defined in the Servlet 2.3 specification. However, the
specification does not explicitly require this order, so other application servers may use different
conventions.
If you want to explicitly specify the order, you can override Dynamos default behavior by setting the
ignorePrecedenceForFilterMatching property of the
/atg/dynamo/service/j2ee/WebContainer component to true. If this property is set to true,
Dynamo ignores the precedence rules and executes the filters in the order that they appear in the
web.xml file.
For example, suppose a requests URI matches the mappings of both of the filters declared in this
web.xml file:

<web-app>
...
<filter>
<filter-name>Filter1</filter-name>
<filter-class>Filter1</filter-class>
</filter>
<filter>
<filter-name>Filter2</filter-name>
<filter-class>Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>

47
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

<filter-name>Filter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>

By default, the Dynamo web container executes Filter2 first, then Filter1, because the URI mapping
for Filter2 has higher precedence. If you set ignorePrecedenceForFilterMatching to true,
however, Filter1 is executed first, because it is declared first in the web.xml file.

48
4 - Web Applications

ATG 6 J2EE Development and Deployment Guide

5 Using the Dynamo Deployment


Editor

The previous chapters illustrated the process of developing and deploying a J2EE application in Dynamo
using Darina from the command line. Its important to understand this process and be familiar with the
files that you must create and fill in.
For a complex application, though, this can be a very tedious process. A large J2EE application may
require hundreds of tags in its deployment descriptor files.
To simplify the development and deployment process, the ATG Control Center includes a J2EE
Deployment Editor. This editor guides you through the task of filling in the fields through a series of
dialogs. You enter values in these dialogs, and the editor handles the saving of these values to the
appropriate deployment descriptor files. It also provides options that call the same underlying code used
by Darina for validating the application, identifying errors, and building and running the application.
This chapter includes the following sections:
Overview of the Deployment Editor
Deploying an Application
Deploying a Standalone Module
Resolving Resource References
Resolving Security Roles

Overview of the Deployment Editor


The Dynamo J2EE Deployment Editor provides a structured environment for developing and deploying
J2EE applications. The editor provides a framework that handles many otherwise time-consuming
mechanical tasks, including:

creating the directory structure for J2EE projects and applications

creating the necessary manifest files, deployment descriptor files, and properties files

creating new J2EE modules, JSPs, and resources

filling in the deployment descriptors

validating the application and the deployment descriptors

49
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

building the class files and stubs

Note that using the deployment editor does not preclude performing some of these functions manually
as well. For example, you can still edit the dynamoJ2EESpecifier.xml directly, manually create
directories for new J2EE modules, or build the application by calling Darina from the command line. The
deployment editor works by calling the same code as Darina for building, validating, and deploying
applications, so changes you make outside the editor will be reflected in the editor the next time you
open the application in it.
If you have an existing J2EE application in a J2EE project, you can open the application in the deployment
editor. The application can be in a DAR file, EAR file, or staging directory, and must be part of a J2EE
project. If the application is structured properly, it will appear in the deployment editors list of J2EE
applications installed on the server. (See the J2EE Project section of the Creating a Sample J2EE
Application chapter for information about the structure of a J2EE project.) If the application is in an EAR or
DAR file, the application appears with the name of the file, minus the extension.
When ATG 6 is first installed, it includes several J2EE projects. To see the list of projects, start up the ACC,
and select the Utilities > J2EE Deployment screen. Your screen should look something like this:

The screen contains a browser that lists all of the J2EE projects installed on the server, and the
applications each project contains. You can open any application in the list by double-clicking on the
name of the application, which is the name of the staging directory or archive file (minus the extension). If
the application is in a staging directory, it will open in the editor. If the application is in an EAR or DAR file,
the editor will unpack the application before opening it. (You can determine whether an application is in
an archive file or a staging directory by placing your cursor over the name of the application and viewing
the resulting tool tip.) Note that if the project contains a staging directory and an EAR or DAR file with the
same name (not including the extension), the editor will open the version in the staging directory, not the
archive file.
Double-click on the j2eeDefault application and it will open in the editor. The screen should now look
similar to this:

50
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

The editor screen consists of three panes. The left pane is a browser that displays the application as a treelike structure of nodes. When you select a node in this pane, the top right pane displays a dialog box for
editing the data associated with that node. The lower right pane is used to display validation errors
associated with the selected node.
Now choose View > Expand All, and the browser shows an expanded view that includes all of the nodes.
Then select the web-app node in the left pane. A tabbed dialog box displays in the data pane (the upper
right). The screen should now look similar to this:

51
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

The browser in the left pane uses three icons to differentiate the nodes. The following table explains these
icons:

Icon

Description
Can have any number of children (including zero). Node itself has no data associated with it.
Has data associated with it but cannot have children.
Has a predefined set of children. Node itself has data associated with it.

The content of the data pane differs depending on the type of icon selected. If you select a folder icon, the
data pane displays a dialog for creating a new child node. If you select an icon that has data associated
with it, the data pane displays a dialog box for editing the data.

52
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

Deploying an Application
The deployment editor provides all of the tools necessary for deploying an existing J2EE application in
Dynamo. Using the editor, you can install an application stored in a EAR or DAR file, create a J2EE project,
fill in the deployment descriptors, and validate and start up the application.
In addition, the deployment editor is flexible enough to support Dynamos incremental development and
deployment mode. Using the deployment editor, you can create a new application from scratch, or by
starting with an existing application as a template. In this mode, you may need to add various elements to
the application (such as a tag library or an EJB), and iteratively modify and build the application.
This section describes the complete process of using the deployment editor to create and deploy a J2EE
application, including:

installing an application on the server

specifying the J2EE version of the application

adding elements to the application

validating the application

building the application

running the application

Subsequent sections include detailed information about filling in deployment descriptors.

Installing an Application on the Server


Before you can modify or deploy an J2EE application, you must first install it on the server. You can do this
manually, but its much easier to use the deployment editor. The editor automatically creates the
necessary directory structure, the manifest file for the J2EE project, and the Dynamo J2EE Specifier file.
Once you install an application, it appears in the list of applications on the initial screen of the
deployment editor. You can then open the application in the editor by double-clicking on its name.

Installing an Application from an Archive File


You can deploy a J2EE application developed on another application server by starting with an assembled
EAR file. You can also use the deployment editor to install a DAR file and create a J2EE project for it.
To install an application in an EAR file or DAR file:
1.

In the ACC, select the Utilities > J2EE Deployment screen.

2.

From the File menu, select Install J2EE Application from Local Archive.

3.

In the dialog box, fill in the name for the J2EE project and the J2EE application.
If a J2EE project with the name you specify already exists, Dynamo adds the new
application to that project. If a J2EE project by that name does not exist, Dynamo
creates a new project by that name and places the application in it.

4.

Click the ... button, and use the file browser to select the EAR file or DAR file.

53
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

5.

Click OK.

Dynamo creates the application and, if it doesnt already exist, the J2EE project (including the top-level
directory structure and the manifest file for the project). The archive file is unpacked into a staging
directory. For example, if the project is called MyProject and the application is called myApp, the staging
directory will be <ATG6dir>/MyProject/j2ee-apps/myApp. This directory will have subdirectories for
each of the J2EE modules in the application. Dynamo also creates a dynamoJ2EESpecifier.xml file that
you can fill out by using the fields in the editor.

Creating a New Application


You can use the deployment editor to create a new J2EE application, either starting from scratch or by
using an existing application as a template. See Developing a New J2EE Application in Dynamo for a
discussion of developing a J2EE application.
To create a new application from scratch:
1.

In the ACC, select the Utilities > J2EE Deployment screen.

2.

From the File menu, select Create New J2EE Application.

3.

In the dialog box, fill in the name for the J2EE project and for the J2EE application.
If a J2EE project with the name you specify already exists, Dynamo adds the new
application to that project. If a J2EE project by that name does not exist, Dynamo
creates a new project by that name and places the application in it.

4.

Click OK.

Dynamo creates the application and, if it doesnt already exist, the J2EE project (including the top-level
directory structure and the manifest file for the project). It also creates the application staging directory
and its META-INF subdirectory. It does not create directories for any J2EE modules unless you
subsequently create these modules through the editor.

Creating a J2EE Project from a Template


Creating a new J2EE project from scratch can be a time-consuming process. The deployment editor
handles many of the mechanical issues (creating directories, manifest files, etc.), but still requires you to
specify the J2EE modules, Java classes, JSPs, and so on.
To simplify the process of creating a new project, the deployment editor enables you to copy a sample
project and use it as a template. The SimpleJ2EE project is an especially useful template, as the simpleJ2EE
application contains most of the J2EE module types.
To create a J2EE project from a template:
1.

In the ACC, select the Utilities > J2EE Deployment screen.

2.

From the File menu, select Create New J2EE Project from Template.

3.

In the dialog box, fill in the name for the J2EE project.

4.

From the drop-down menus, select the template group and the template to use.

5.

Click OK.

54
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

Dynamo creates the new J2EE project by copying the project template you selected. The new project
contains the same applications that are in the template.

Creating New Templates


Your Dynamo installation includes a number of J2EE project templates in the J2EE-Examples template
group. You can create additional templates by adding a new template group to Dynamo. To add a new
template group:
1.

Create a new directory inside your Dynamo root directory.


The name you give this directory will be the name of the template group.

2.

Move the J2EE projects that you want to use as templates into the directory.

3.

Go to the screen Pages and Components > Components by path.

4.

Open the component /atg/devtools/ContainerAppDirectoryAgent.

5.

Edit the templateModuleRoots property, adding the template group directory to the
list of directories.

6.

Save the changes to the component.

You must shut down and restart the ACC before the new template group and the templates in it are
available.

Specifying the J2EE Version


The J2EE 1.3 specification requires the application server to support deployment of J2EE 1.2 applications
without any changes to the code. In addition, a J2EE 1.3 application can include J2EE 1.2 modules; so, for
example, it is possible for a J2EE 1.3 application to include one or more EJB 1.1 modules.
To specify the J2EE version of an application, select the top-level node in the browser, and then select the
J2EE version from the Spec Version drop-down in the data pane. To specify the version of a module, select
the node for that module, and then select the version from the Spec Version drop-down in the data pane.
Note that although it is possible to include J2EE 1.2 modules in a J2EE 1.3 application, the reverse is not
true. The deployment editor indicates invalid combinations of application and module versions through
validation errors and build failures, but you should be careful to specify the versions correctly. Depending
on the application and module versions, certain fields in the editor may change or be disabled. For
example, if the Spec Version of an EJB module is 1.1, EJB 2.0 style container-managed persistence options
are disabled.

Adding Elements to the Application


You can use the deployment editor to add items to the application. For example, you can import a tag
library, add a new EJB or filter, or even create a new J2EE module from within the editor. The editor
automatically takes care of creating the appropriate directories and deployment descriptor files.
To add a new element, select the folder icon for the node that the new element will be a child of. For
example, to add a servlet to a web application module, select the Servlet folder, as in this figure:

55
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

In the data pane, enter the name of the new servlet, and click Add. The servlet appears in the editor:

56
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

Using the File Transfer Tool


When you create a new element as described above, the editor makes the necessary entries in
deployment descriptor files and creates any necessary directories. The editor does not create any Java
source files or class files. For example, if you add a servlet to the application through the editor, you must
have either a corresponding .java or .class file in the web application module.
If you have existing files you want to include in the application, you can use the file transfer tool to copy
them into the appropriate directory. Select Tools > File Transfer Tool, and Dynamo displays the following
dialog box:

57
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

The file transfer tool displays your local file system on the left and the directories of the application you
are editing on the right. To copy files into the application:
1.

In the file browser on the left side of the dialog box, navigate to the directory
containing the files to transfer, and select the files.
You can select any number of files and directories by holding down the Control key
and clicking. If you select a directory, Dynamo will copy the directory and all of its
contents, including any files or directories it contains.

2.

In the file browser on the right side of the dialog box, navigate to the application
directory you want to copy the files into.

3.

On the left side, click the Transfer Files button.

Dynamo copies the selected files into the application. Note that the transfer works in either direction; you
can copy files from a J2EE application to your local file system by selecting them in the right pane and
then clicking Transfer Files.
After you transfer any .java or .class files, save your configuration and then select either Tools > Build
Application or File > Reload Configuration. This will ensure that the deployment editor has up-to-date
information about these classes.

Adding a Tag Library


To use a tag library in a Web application, the TLD file and the Java classes for the tags must be copied into
the web application module. The standard location for the TLD is in the WEB-INF directory, and the
corresponding JAR file containing the tag classes goes in the WEB-INF/lib directory.
To include the Dynamo Core tag library, DSP tag libraries, or JSTL in an application:
1.

Select View > Module Components, and then select the Tag Libraries node in the
browser.

58
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

2.

From the New Standard Tag Library drop-down list, select the tag library you want
copied into your Web application.
Note: For the DSPEL tag libraries, choose the DSP option even though it will
automatically use the dspTaglib URI. The appropriate URI is defined in the tag librarys
TLD, which is included in the DSP tag library JAR file.

3.

Click the second Add button.


The Deployment editor inserts the URI and path to the tag librarys parent directory
into dynamoJ2EESpecifier.xml between enclosing <atg-taglib-src-dir> tags.
Once you rebuild your application, Dynamo copies the tag library TLD and class files
from that directory into your Web application. Regardless of the number of TLD files
you have for a tag library (there are 8 for JSTL), you need only add the tag library to
your Web application once.

Note that the files are not actually copied until you build the application.
The resultant XML for the DSP tag libraries looks like the following:

<taglib>
<taglib-uri>/dspTaglib</taglib-uri>
<atg-taglib-src-dir>/DAS/taglib/dspjspTaglib/1.0</atg-taglib-src-dir>
</taglib>

When copying JSTL in this manner, a URI will not be specified in dynamoJ2EESpecifier.xml.
To include any other tag library in an application:
1.

Copy the TLD file into the web application module, placing it in the directory WEB-INF.

2.

Copy the JAR file into the directory WEB-INF.

3.

Select View > Module Components, and then select the Tag Libraries node in the
browser.

4.

In the data pane, enter the URI for the tag library, and click the first Add button.
The URI you specify is the URI used in the page directive in your JSPs and the URI
defined in the tag librarys TLD file.

5.

Click the ... button next to the TLD File Location field, and use the file browser to select
the TLD file.

Note that the files are not actually copied until you build the application.

Using the Text Editor


The deployment editor includes a text editor that you can use to create new files on the serve and modify
existing files, such as JSPs and Java source files. To open a text editor, select Edit > Edit Remote File.

59
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

Validating the Application


The deployment editor includes a validation tool that you can use to find any deployment errors. When
you select Tools > Validate, Dynamo evaluates the application, reporting any required descriptor
elements that are empty or contain erroneous values. You can then correct these values and run the
validation tool again, repeating this process until there are no errors. At this point, select File > Save
Current Configuration. Dynamo will save all the deployment information to the appropriate deployment
descriptor files.
When you run the validation tool, the deployment editor indicates errors in two ways:

Nodes that produce errors appear in red in the browser.

When you select a node in the browser, the labels for the fields that produced errors
appear in red in the data pane, and validation error messages are displayed in the
validation pane.

For example, if you add a servlet to the application, but no .java or .class file for the servlet exists, the
screen might look like this after running the validation tool:

It is a good idea to select View > Expand All before or immediately after running the validation tool. When
the browser is fully expanded, the actual nodes that produced the errors appear in red. When the browser

60
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

is collapsed, if a node that produced an error is not visible, its parent node will appear in red until you
expand it. Note that if you select a validation error message in the lower right pane, the cursor will
automatically be placed in the field in the data pane that produced the error.
Even if all of the deployment descriptors are filled in properly, you may see class not found validation
errors if any Java source files have not been compiled. If this happens, choose Tools > Build Application
(described in the next section). When Dynamo builds the application, it will compile each .java file
whose corresponding .class file is either older than it or does not exist.

Building the Application


Once the application is validated (and there are no longer any invalid fields), you can build it by selecting
Tools > Build Application. Dynamo builds the application in the staging directory, compiling the class
files, generating stubs, etc. If the build succeeds, you can then run the application by selecting Tools >
Start J2EE Application.
When you are ready to deploy the application on a live site, you should create a DAR file by selecting
Tools > Save to Local DAR File. Dynamo builds the application on the server, packages it as a DAR file, and
copies the file to your local file system. You can then copy the DAR file into a J2EE project on the live site.
Note that the DAR file includes only the contents of the application directory, so you must recreate the
projects manifest file, as well as any properties files in the config directory.

Running the Application


After youve deployed and built the application, you can start it up from within the deployment editor by
selecting Tools > Start J2EE Application. If you then make further changes, you can start the new version
by selecting this option again.
Note that starting up a J2EE application on a running Dynamo server may not work properly under certain
circumstances. For example, the deployment editor cannot start up any global (server-wide) resources, so
if the application relies on any global resources, these services must already be running before you start
up the application. To start up global resources that are not currently running, you must restart Dynamo.
For more information about the differences between global and application resources, see Mapping
Resource References.

Deploying a Standalone Module


In addition to deploying complete J2EE applications, the deployment editor supports deploying
standalone J2EE modules. For example, many web applications do not require any other J2EE modules to
run; such a web application can be packaged in a WAR file that is not part of an EAR file. Other J2EE
modules, such as EJB modules and connectors, may run on a server and be accessed remotely by a web
application or an application client.

61
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

Installing an Existing Module


You can deploy an existing standalone J2EE module by starting with an assembled WAR, EJB JAR, or RAR
(connector) file:
1.

In the ACC, select the Utilities > J2EE Deployment screen.

2.

From the File menu, select Install J2EE Application from Local Archive.

3.

In the dialog box, fill in the name for the J2EE project and the J2EE module.
If a J2EE project with the name you specify already exists, Dynamo adds the new
application to that project. If a J2EE project by that name does not exist, Dynamo
creates a new project by that name and places the module in it.

4.

Click the ... button, and use the file browser to select the file.

5.

Click OK.

Dynamo creates the module and, if it doesnt already exist, the J2EE project (including the top-level
directory structure and the manifest file for the project). The archive file is unpacked into a staging
directory. Dynamo also creates a dynamoJ2EESpecifier.xml file that you can fill out by using the fields
in the editor.

Creating a New Module


You can use the deployment editor to create a new standalone J2EE module from scratch:
1.

In the ACC, select the Utilities > J2EE Deployment screen.

2.

From the File menu, select Create New J2EE Application.

3.

In the dialog box, fill in the name for the J2EE project and for the J2EE module.
If a J2EE project with the name you specify already exists, Dynamo adds the new
application to that project. If a J2EE project by that name does not exist, Dynamo
creates a new project by that name and places the application in it.

4.

From the Application drop-down, select the type of module to create.

5.

Click OK.

Dynamo creates the module and, if it doesnt already exist, the J2EE project (including the top-level
directory structure and the manifest file for the project). It also creates the module staging directory and
its META-INF subdirectory.

Resolving Resource References


In a J2EE application, the code refers to system resources using abstract resource references. One of the
main tasks of deploying an application consists of setting up system resources in the application server,
and then mapping the resource references in the code to these system resources.
As mentioned in the Dynamo and J2EE chapter, Dynamo resources can be either global or applicationspecific. The chief advantage of a global resource is that it can be shared by multiple applications, while

62
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

the chief advantage of an application resource is that it can be started up without restarting Dynamo. This
section describes how to resolve resource references using either approach.
Note: Application clients cannot use global resources, because they dont have access to Nucleus
components. This is explained more fully in the Application Clients chapter.
Multiple resource references can be resolved to the same application or global resource. For an
application resource, all the references to it must be in the same application. For a global resource,
multiple applications can use the same resource. If multiple references require different configurations,
the deployer must either configure separate application resources, or create multiple Nucleus
components to use as global resources.
Mapping a resource reference to a global resource can be done in two ways. You can either map the
resource reference directly to the JNDI name of a Nucleus component, or you can create a separate
resource definition and then resolve the resource reference through a resource link that maps the name
used in the code to the name of the service definition. For application resources, you must create a
separate resource definition and then link to it. Even for global resources, this approach is often
preferable, because it allows you to define the resource only once and then link to it as many times as
necessary. In addition, it enables you to link to resources in the same way regardless of whether they are
global or application-specific.
For example, suppose you create one or more JDBC connection pools as either global or application
services (or a combination of each). You can then link to these services from multiple places in your
application. For example, to specify the JDBC service used by an EJB:
1.

In the browser, select the EJB.

2.

In the data pane, select the Resource References tab.

3.

Specify a new resource reference by clicking Add, filling in the Name field in the dialog
box, and then clicking OK.

4.

In the Resource Type field, select the Link radio button.

5.

From the Resource Class drop-down, select javax.sql.DataSource.

6.

From the Resource Type drop-down, select JDBC Resource Factory Service Definitions.

7.

In the Link field, select the resource to link the reference to.

JDBC Service
Creating a Global Resource
To create a global resource, you create one or more Nucleus components and configure them through
properties files. For example, a commonly used resource is a DataSource, which is a factory for
producing JDBC connections. A DataSource resource reference should be satisfied by a Nucleus
component of class atg.service.jdbc.MonitoredDataSource. Dynamo comes preconfigured with
such a component, /atg/dynamo/service/jdbc/JTDataSource. You can override the components
default configuration by creating the appropriate .properties file in the applications config/
directory. For example, configurations to the JTDataSource object would appear in
<ProjectDir>/config/atg/dynamo/service/jdbc/JTDataSource.properties.

63
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

DataSource components are a bit more complex than other resources since they are actually made up of
multiple components. The JTDataSource component handles pooling and monitoring of connections,
but the actual connections are supplied by another DataSource. This DataSource may be a JDBC 2
DataSource supplied by a JDBC driver vendor, or it may be a JDBC 1 driver. Dynamos default

configuration (using the SOLID database included with Dynamo for evaluation purposes) has the
JTDataSource pointing to /atg/dynamo/service/jdbc/FakeXADataSource, a DataSource which

adapts a JDBC 1 driver to Dynamos JDBC 2 expectations.


The FakeXADataSource configures the required JDBC 2 properties and might be configured like this:
driver=solid.jdbc.SolidDriver
URL=jdbc:solid://localhost:1313
user=admin
password=admin

The JTDataSource configures the pooling and monitoring behavior of the underlying connections. For
example, the JTDataSource might have these properties:
min=10
max=20
maxFree=15

This defines the minimum and maximum number of connections to keep in the pool, and also specifies
the maximum number of free connections at any time.
Once you have configured the Nucleus components, you can create a resource definition in the
deployment editor:
1.

In the browser, select the JDBC Resource Factory Service Definitions folder.

2.

In the data pane, enter a name for the new resource, and click Add.
The new resource appears in the browser, under the folder.

3.

Select the resource you just created.

4.

In the Resource Type radio buttons, select URL.

5.

In the Resource Name field, enter the JNDI form of the Nucleus component name (e.g.,
dynamo:/atg/dynamo/service/jdbc/JTDataSource).

Creating an Application Resource


To create a JDBC connection service as an application resource, you do not configure any Nucleus
components. Instead, you specify the configuration of the JDBC service in the
dynamoJ2EESpecifier.xml file, either manually or by using the deployment editor.
To configure a JDBC service in the deployment editor:
1.

In the browser, select the JDBC Resource Factory Service Definitions folder.

2.

In the data pane, enter a name for the new resource, and click Add.
The new resource appears in the browser, under the folder.

64
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

3.

Select the resource you just created.

4.

In the Resource Type radio buttons, select JDBC Lookup.

5.

Fill in the class name and URL for the driver, the minimum and maximum pool sizes,
and so on.

You can optionally specify values for properties of the resource by adding rows to the Properties table
and filling in the properties and their values.

GSA Repository Service


You can configure a GSA repository service as either a global or application resource. If your application
uses an existing Dynamo repository, you can access this as a global resource:
1.

In the browser, select the GSA Repository Services Definitions folder.

2.

In the data pane, enter a name for the new resource, and click Add.
The new resource appears in the browser, under the folder.

3.

Select the resource you just created.

4.

In the Service Type radio buttons, select URL.

5.

In the Name field, enter the JNDI form of the Nucleus component name (e.g.,
dynamo:/atg/dynamo/service/jdbc/SQLRepository).

To create an application resource:


1.

Follow the steps for creating a GSA repository service as a global resource, but in the
Service Type radio buttons, select Immediate.

2.

In the Repository Name field, fill in a name for the repository.

3.

Specify one or more initialization files for the repository by clicking the Add button
and using the Open dialog box to select the files.

4.

Specify the JDBC resource for the repository to use. If a JDBC resource has already
been defined, you can select Link as the JDBC Resource Type, and then select the link
from the drop-down. Otherwise, you can select Name and fill in the JNDI name of a
JDBC data source.

You can optionally specify values for properties of the resource by adding rows to the Properties table
and filling in the properties and their values.
Note that if you are using container-managed persistence (CMP) for EJBs, the initialization file list must
include the file that defines the repository views used by the EJBs. If you are using CMP automatic
mapping, the file may not have been created yet when you create the GSA service. However, you can still
specify this file by typing its name (_cmpRepository.xml) in the File Name field of the Open dialog box.
See the Container-Managed Persistence section of the Enterprise JavaBeans chapter for more
information.

65
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

JMS Connection Service


Dynamo includes several different JMS providers: SQL JMS, Local JMS, and the Sun JMS Reference
Implementation. The Sun JMS Reference Implementation is preconfigured, so you can use its connection
services in your applications directly. If you are using SQL JMS or Local JMS, however, you must explicitly
define a connection service that links to the corresponding Nucleus component:
1.

In the browser, select the JMS Connection Service Definitions folder.

2.

In the data pane, enter a name for the new resource, and click Add.
The new resource appears in the browser, under the folder.

3.

Select the resource you just created.

4.

In the JMS Connection Type radio buttons, select either Queue or Topic.

5.

In the name field, enter the JNDI form of the Nucleus name. For SQL JMS, this
component is dynamo:/atg/dynamo/messaging/SqlJmsProvider. For Local JMS,
this component is dynamo:/atg/dynamo/messaging/MessagingManager.

For information about the Sun JMS Reference Implementation, see Appendix B: Sun JMS Reference
Implementation. For information about SQL JMS and Local JMS, see the ATG 6 Dynamo Programming
Guide.

JavaMail Service
If a J2EE component needs to send or receive e-mail, it should do so using JavaMail facilities. You can
create a global JavaMail service by mapping the service name to the JNDI name
dynamo:/atg/dynamo/service/j2ee/MailSessionContext/DefaultSession. Application
resources that use this service can be resolved by linking to this service.
The actual Nucleus component that configures the mail system is found at
/atg/dynamo/service/j2ee/MailSessionContext. You can configure this component by setting the

basic properties such as mailHost. For example:


mailHost=mail.ourcompany.com

URL Service
The URL resource provides a mechanism for gaining access to resources not covered by the various other
resource types. In its code, the component obtains a pointer to a java.net.URL object. From the URL
object, the component may call methods that give the component access to content or objects
represented by the URL. Thus, a URL resource can be used as a way to pass arbitrary content or objects to
a J2EE component.
You can resolve a URL resource reference directly like this:
<resource-ref>
<res-ref-name>
atgIndex
</res-ref-name>
<resource-name>

66
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

http://www.atg.com/index.html
</resource-name>
</resource-ref>

To create a URL service in the deployment editor, just supply the name of the service and the URL it maps
to. You can then link to this service to resolve references in web modules, EJBs, etc.

Resolving References to J2EE Connectors


J2EE 1.3 includes a module type called an enterprise resource adapter. An enterprise resource adapter
(commonly referred to as a connector, because it implements the Java Connector Architecture), is a set of
resource factories for obtaining connections to enterprise applications such as transaction processing (TP)
or enterprise resource planning (ERP) systems.
A connector is packaged in a resource adapter archive (RAR) file, which is packaged inside an EAR file. A
connector can be a standalone module (in which case the RAR archive is the only module in the EAR file),
or be part of larger application (in which case the EAR file contains other modules that link to the
connector). Note that for Dynamo to run a connector as a standalone module, it must be packaged either
in a DAR file or a staging directory created from a DAR file.
To create a resource reference to a connector, you add a resource-ref element to the configuration file
of the module (the web.xml, ejb-jar.xml, or application-client.xml). The reference should look
similar to this:

<resource-ref>
<res-ref-name>erp/myErp</res-ref-name>
<res-type>com.mycompany.erp.erpResource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

The res-type is the name of the main class of the connector. The res-auth must be Container or
Application, depending on how authentication is managed for the connector.
You then resolve the resource-ref in the dynamoJ2EESpecifier.xml file. For example, to look up the
connector from a web application:

<war>
<module-uri>my-web-app</module-uri>
...
<resource-ref>
<res-ref-name>erp/myErp</res-ref-name>
<connector-link>erp.rar</connector-link>
<default-resource-user>admin</default-resource-user>
<default-resource-password>rsxqz445</default-resource-password>
</resource-ref>
...
</war>

67
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

If you are running the connector from a staging directory, the connector-link is the name of the
subdirectory containing the unpacked RAR file; if the connector is running from a DAR file, it is the name
of the nested RAR archive. The default-resource-user is the name of the principal to use for
authentication, and the default-resource-password is the password for that principal.

Resolving Security Roles


J2EE components can make reference to security roles. For example, a Web application might specify
that certain pages are to be accessed only by users associated with a particular role. Or an EJB might
declare that its methods are only to be called by users associated with a particular role.
In application code or Web/EJB deployment descriptors, a security role is referenced by an applicationspecific role name. Like env-entry, resource-ref, or ejb-ref names, these names are meaningful only
within the application. Before deploying the application in Dynamo, those role names must be mapped to
roles in Dynamos security system.
In Dynamos security system, a UserAuthority is used to map users, passwords, and role names to an
underlying repository. The UserAuthority must be told which Item descriptor in the repository
represents a user, and which properties of that view represent the users login, password, and role
memberships. Because any repository implementation can be used to supply the UserAuthority with
its required data, the UserAuthority can read its data from a database, an LDAP source, or a content
management system.
For a full description of Dynamos J2EE security system, including how to create security resources and
resolve security roles, see the J2EE Security chapter.

Resolving Environment Entries


A J2EE application may declare env-entry references that must be resolved with actual values before the
application may be deployed. Each individual EJB in an ejb-jar.xml file can declare env-entry
references that apply to just that EJB, or a web.xml file can declare env-entry references that apply to all
Servlets, JSPs, and Tags in that Web module. An application-client.xml module may also declare
references that apply to that modules application client code.
The appropriate deployment descriptor file, ejb-jar.xml, web.xml, or application-client.xml, can
declare the value for an env-entry reference, but is not required to do so. If a value has not been
resolved in the deployment descriptor, then it must be resolved in the dynamoJ2EESpecifier.xml file.
In addition, values supplied in dynamoJ2EESpecifier.xml can be used to override any values supplied
in the appropriate deployment descriptor.
For EJBs, env-entry values must be resolved at the level of a single EJB. For Web applications and
application clients, env-entry values must be resolved at the level of a complete Web application or
application client:

68
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

<dynamo-j2ee-specifier>
...
<war>
<module-uri>
web-app
</module-uri>
<env-entry>
<env-entry-name>
someOtherValue
</env-entry-name>
<env-entry-value>
2242
</env-entry-value>
</env-entry>
</war>
...
</dynamo-j2ee-specifier>

To specify an environment entry for a web application in the deployment editor:


1.

In the browser, select the web module.

2.

In the data pane, select the Environment tab.

3.

Click the Add button, and in the dialog box, specify a name for the entry, and click OK.

4.

From the Type drop-down, select the data type for the environment entry.

5.

Specify an Application Value, a Dynamo Value, or both.

If you specify an Application Value, this value is stored in the web.xml file. If you specify a Dynamo Value,
this value is stored in the dynamoJ2EESpecifier.xml file.

69
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

70
5 - Using the Dynamo Deployment Editor

ATG 6 J2EE Development and Deployment Guide

6 Enterprise JavaBeans

It is possible to write an application in which the user interface communicates directly with back-end
databases and resources. In the Web-based J2EE world, you implement this strategy by having Servlets,
JSPs, and JSP Tags communicate directly with a database through JDBC.
This architecture allows you to build applications quickly, but it has several drawbacks. It makes
applications sensitive to changes in the database schema, which in turn makes it more difficult to add or
change functionality. It also spreads out the knowledge of the systems functions, since that knowledge is
strewn throughout the interface code instead of being encapsulated in a controlled manner. Finally, its
harder to add new interfaces that perform similar functions. Such an operation usually requires you to cut
and paste code from one interface to the other, which leads to a management nightmare.
Because of these problems, most non-trivial applications introduce a layer of business logic into the
architecture, implemented as a set of business objects. These business objects define an API for the
back-end services of the application. These APIs are defined in terms that are not specific to any one
application or interface. For example, the business objects might define the calls that you should use to
create a new customer account or place an order. In the end, these calls make the same database calls
that the interface would have made on its own. However, because the business logic is in its own layer,
you can build multiple applications on the same functionality without cutting and pasting code. Also, the
applications are not as sensitive to changes in the database. You can confine those changes to the
business objects without requiring changes to all of the connected applications.
An application server can improve matters further by hosting business objects and providing additional
services. For example, the application server can expose those objects to the network, so that remote
clients can gain access to the back-end functionality without having to link their code directly to the
business objects. The application server can also enforce security constraints, so that applications cannot
invoke certain functions unless a user with the proper credentials directs them to do so.
Enterprise JavaBeans (EJBs) are the mechanism for encapsulating business logic and data in the J2EE
platform. EJBs are Java components that you create according to a strict form. Any EJB container (a
required part of the J2EE platform) can host EJBs that you create in this manner. Once you have installed
an EJB into an EJB container, that container must allow applications to gain access to the EJB, which will,
in turn, gain access to resources (such as databases) to carry out its functionality. At the same time, the
EJB container provides several services to EJBs, such as remote access, security, and automatic
persistence.
One of the main goals of the EJB architecture is to allow developers to concentrate on writing business
logic without being bothered by the other concerns that come up in enterprise computing (remote
access, security, persistence, etc.). To do this, EJB developers must follow a specific form in creating their
components. Developers must define certain interfaces for each EJB, with naming conventions for
methods and other restrictions on arguments and return values. In many cases, the amount of code

71
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

required to adhere to the form will be greater than the actual business logic enclosed in the EJB. This is
natural, and should not be alarming to developers.

EJB Examples
Dynamo includes a sample application that illustrates the various types of EJBs. The example is in the
<DAS6dir>/J2EE-Examples/SimpleEJB directory. Before you can run this application, you must use
Darina to deploy it. Change to the <DAS6dir>/home directory, then run Darina like this (using forward or
backward slashes as appropriate):
bin/runDarina ../J2EE-Examples/SimpleEJB/j2ee-apps/simpleEJB -build

Darina will compile all of the applications source files, produce ejb-client-jar files, and create the
various RMI classes. When its finished, Darina will have produced a deployed DAR file at ../J2EEExamples/SimpleEJB/j2ee-apps/simpleEJB.dar.
Once the application has been deployed, you may run it by using the modules flag:
bin/startDynamo -m J2EE-Examples.SimpleEJB

This command starts Dynamo, installing the demonstration so that it starts up the same time Dynamo
does.
This demo includes eight different EJBs:

Averager is a stateful session bean.

StatelessAverager is a stateless session bean.

BMPPerson is an entity bean that uses bean-managed persistence.

CMPPerson is an entity bean that uses container-managed persistence (EJB 1.1 style).

CPKPerson is an entity bean that uses container-managed persistence (EJB 1.1 style)

with a compound primary key.

CMP2Person is an entity bean that uses container-managed persistence (EJB 2.0 style).

CPK2Person is an entity bean that uses container-managed persistence (EJB 2.0 style)

with a compound primary key.

TestMessageBean is a message-driven bean.

We assume that the demo will be running on SOLID, the evaluation database included with Dynamo. This
database comes pre-initialized with the schema you need to run the demo. If you use a different
database, or if the schema does not yet exist, you can use the schema by entering these commands:

CREATE TABLE EJB_PERSON (


ID INTEGER NOT NULL PRIMARY KEY,
NAME VARCHAR (128),

72
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

AGE INTEGER
);
CREATE TABLE EJB_CPK_PERSON (
ID INTEGER,
FIRSTNAME VARCHAR (128) NOT NULL,
LASTNAME VARCHAR (128) NOT NULL,
AGE INTEGER,
PRIMARY KEY (FIRSTNAME, LASTNAME)
);

CREATE TABLE EJB_PERSON2 (


ID INTEGER NOT NULL PRIMARY KEY,
NAME VARCHAR (128),
AGE INTEGER
);
CREATE TABLE EJB_CPK_PERSON2 (
ID INTEGER,
FIRSTNAME VARCHAR (128) NOT NULL,
LASTNAME VARCHAR (128) NOT NULL,
AGE INTEGER,
PRIMARY KEY (FIRSTNAME, LASTNAME)
);

Once you deploy and run the application, you can gain access to it by entering this URL:
http://{hostname}:8840/simpleEJB/

The URL displays links to demonstrations for different EJB types. Each demonstration is driven by its own
servlet that performs the appropriate client-side calls to gain access to the EJB and output the results. This
is not a recommended way to build an application; you should use JSPs and Tags to build interfaces. We
use servlets in this example for the purpose of simplicity.

Configuring EJBs and the EJB Container


Resolving References to EJBs
Any J2EE component that makes use of an EJB, either in the same application or supplied by a different
application, must declare that EJB reference in the appropriate deployment descriptor. The
AddNumbersTag in the simpleJ2EE application makes just such a reference, using the name
ejb/AddNumbers. The reference is then declared in the web.xml file:

73
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

<web-app>
...
<ejb-ref>
<ejb-ref-name>
ejb/AddNumbers
</ejb-ref-name>
<ejb-ref-type>
Session
</ejb-ref-type>
<home>

atg.simpleJ2EE.AddNumbersHome
</home>
<remote>
atg.simpleJ2EE.AddNumbers
</remote>
<ejb-link>
AddNumbers
</ejb-link>
</ejb-ref>
...
</web-app>

The reference must be resolved by pointing it at an EJB Home that is either in the same application, or an
external EJB Home supplied by another application. Internal references may be resolved within the
deployment descriptor using ejb-link tags, as is done in the SimpleJ2EE example. However, if the
reference were not resolved there, it would have to be resolved in the dynamoJ2EESpecifier.xml file,
something like this:

<dynamo-j2ee-specifier>
...
<war>
<module-uri>
web-app
</module-uri>
<ejb-ref>
<ejb-ref-name>
ejb/AddNumbers
</ejb-ref-name>
<ejb-link>
AddNumbers
</ejb-link>
</ejb-ref>
</war>
...
</dynamo-j2ee-specifier>

74
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

An ejb-ref may be resolved to point to an external EJB, supplied by another application, possibly hosted
by a different J2EE container provider. In this case, the deployer must know the JNDI name that should be
used to access that EJB Home. The JNDI name will depend on the vendor. The JNDI name should be
supplied using ejb-home-name, in place of ejb-link:

<dynamo-j2ee-specifier>
...
<war>
<module-uri>
web-app
</module-uri>
<ejb-ref>
<ejb-ref-name>
ejb/AddNumbers
</ejb-ref-name>
<ejb-home-name>
vendorprotocol:/somePrefix/AddNumbers
</ejb-home-name>
</ejb-ref>
</war>
...
</dynamo-j2ee-specifier>

Note that application clients may communicate remotely with EJBs in the same application, but because
they are in the same application they can use the EJBs name in an ejb-link.
As with env-entry references, ejb-ref references must be resolved on a per-EJB basis, or on a per-Web
application basis.

Resolving Environment Entries for EJBs


For EJBs, env-entry values must be resolved at the level of a single EJB. As an example, suppose that the
AddNumbers EJB required a configuration constant value to be supplied to it, such as a defaultValue. In
the ejb-jar.xml file, this might be declared as follows:

<session>
<ejb-name>
AddNumbers
</ejb-name>
...
<env-entry>
<env-entry-name>
defaultValue
</env-entry-name>
<env-entry-type>
java.lang.Integer
</env-entry-type>

75
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

</env-entry>
...
</session>

The AddNumbers EJB could access the value of this entry with the following code:
InitialContext ctx = new InitialContext ();
int defaultValue = ((Integer)
ctx.lookup ("java:comp/env/defaultValue")).
intValue ();

However, the env-entry must be given a value. This could be done in the ejb-jar.xml file using an
env-entry-value. Or, it can be supplied in the dynamoJ2EESpecifier.xml file. To do this, use an enventry declaration in the dynamoJ2EESpecifier.xml file:

<dynamo-j2ee-specifier>
...
<ejb-jar>
<module-uri>
ejbs
</module-uri>
<enterprise-beans>
<session>
<ejb-name>
AddNumbers
</ejb-name>
<env-entry>
<env-entry-name>
defaultValue
</env-entry-name>
<env-entry-value>
25
</env-entry-value>
</env-entry>
</session>
</enterprise-beans>
</ejb-jar>
...
</dynamo-j2ee-specifier>

To specify this environment entry in the deployment editor:


1.

In the browser, select the EJB.

2.

In the data pane, select the Environment tab.

3.

Click the Add button, and in the dialog box, specify a name for the entry, and click OK.

4.

From the Type drop-down, select the data type for the environment entry.

76
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

5.

Specify an Application Value, a Dynamo Value, or both.

If you specify an Application Value, this value is stored in the ejb-jar.xml file. If you specify a Dynamo
Value, this value is stored in the dynamoJ2EESpecifier.xml file. For example, suppose you set the
application value to 25, and the Dynamo value to 30. When you save the configuration, defaultValue is
set to 25 in the ejb-jar.xml file, and is set to 30 in the dynamoJ2EESpecifier.xml.
When you run the application in Dynamo, the value in the dynamoJ2EESpecifier.xml file overrides the
value in the ejb-jar.xml file, so defaultValue is set to 30. However, if you were to deploy the
application on another J2EE application server, defaultValue would be set to 25 (using the value in
ejb-jar.xml), because the settings in dynamoJ2EESpecifier.xml are used only by Dynamo.

Communications Protocols
EJBs can use a variety of communications protocols for remote method calls. By default, Dynamo uses
iiop, but you can specify standard RMI instead by setting the ejb-protocol tag in the
dynamoJ2EESpecifier.xml file to rmi. For example:

<dynamo-j2ee-specifier>
<application-name>
simpleJ2EE
</application-name>
<ejb-protocol>
rmi
</ejb-protocol>
...
</dynamo-j2ee-specifier>

When you run Darina (either from command-line or through the Build option in the deployment editor), it
determines what stubs and ties to build based on the value of this setting. If you want to override the
setting, Darina accepts the command-line flags -iiop and rmi.
For example, to build the simpleJ2EE application and use standard RMI as the EJB protocol:
bin/runDarina ../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE
build -rmi

When you use the rmi or iiop flag, Darina sets the value of ejb-protocol to match the flag, so
Dynamo can recognize which protocol is supported by the generated stubs.

IOR Security
IIOP uses Interoperable Object References (IORs) to control access to EJBs. An IOR is a reference to an
object that uses a string of digits to encode identity and security requirements for calls to that object. For
each EJB, you specify a transport configuration definition (which defines certain IIOP parameters), the
authentication service context (which specifies how callers are authenticated), and the secure attribute
service context (which specifies whether the callers identity is propagated between objects).
For example, the IOR security definition in the dynamoJ2EESpecifier.xml file might look like this:

77
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

<enterprise-beans>
<session>
<ejb-name>
AddNumbers

</ejb-name>
<ior-security-config>
<transport-config>
<integrity>
supported
</integrity>
<confidentiality>
required
</confidentiality>
<establish-trust-in-target>
supported
</establish-trust-in-target>
<establish-trust-in-client>
supported
</establish-trust-in-client>
</transport-config>
<as-context>
<auth-method>
username_password
</auth-method>
<realm>
default
</realm>
<required>
True
</required>
</as-context>
<sas-context>
<caller-propagation>
required
</caller-propagation>
</sas-context>
</ior-security-config>
</session>
</enterprise-beans>

EJBs and Transactions


The ATG 6 Dynamo Programming Guide describes Dynamos transaction management in detail. This
section explains some of the concepts that apply specifically to EJBs.
Dynamo EJB offers both declarative and programmatic transactions. Declarative transactions allow the
deployment descriptor to specify the transaction attribute to be applied to each of an EJBs methods
using the trans-attribute tag. This tag can specify one of six transactional behaviors to be applied to a

78
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

demarcated area, which in the case of an EJB is a single method call. We explain the transaction attributes
in the section on transaction demarcation. By using declarative transactions, you can control and change
transactional behavior without touching any of the EJBs code.
If an EJB uses programmatic transactions, then it can start and end transactions within code. It does so
through the javax.transaction.UserTransaction interface, which it can obtain by calling
getUserTransaction() on the EJBContext. If an EJB declares that it uses programmatic transactions,
then any existing transaction is suspended before you enter the EJBs method, and is resumed after the
EJBs method ends. The EJB is responsible for ending any transactions it creates within its method call.
An EJB must use either programmatic or declarative transactions, also known as bean-managed and
container-managed transactions. It cannot use both. Furthermore, only session beans can use beanmanaged transactions. Entity beans can use only declarative transactions.
You must specify declarative transactions in the EJB deployment descriptor. Declare the transactions in a
separate section called the assembly descriptor. You can declare them to apply to all methods in an EJB or
to individual methods. For example:

<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>
AddNumbers
</ejb-name>
<method-name>
*
</method-name>
</method>
<trans-attribute>
Required
</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>
AddNumbers
</ejb-name>
<method-name>
addNumbers
</method-name>
</method>
<trans-attribute>
Supports
</trans-attribute>
</container-transaction>
</assembly-descriptor>

79
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

This example indicates that all methods of the AddNumbers EJB should have a transaction attribute of
Required, except for the addNumbers method, whose declaration of Supports overrides the *
declaration. The EJB specification describes how even more specific declarations can be made to
differentiate between methods with the same name but different arguments, or even methods with the
same name and arguments in the home and remote interfaces.

EJBs and Security


The EJB security system builds on the general J2EE Security facilities (see the J2EE Security chapter). EJB
allows you to place declarative security on individual methods of an EJB, indicating that those methods
may not be called unless the calling user matches one of the security roles declared for that method. For
example:

<assembly-descriptor>
<method-permission>
<role-name>
admin
</role-name>
<method>
<ejb-name>
AddNumbers
</ejb-name>
<method-name>
addNumbers
</method-name>
</method>
</method-permission>
</assembly-descriptor>

This declaration indicates that only users belonging to the admin role can call the addNumbers method.
This admin role is only an internal name. It must be declared in the assembly-descriptor:

<assembly-descriptor>
<security-role>
<role-name>
admin
</role-name>
</security-role>
<method-permission>
<role-name>
admin
</role-name>
<method>

80
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

<ejb-name>
AddNumbers
</ejb-name>
<method-name>
addNumbers
</method-name>
</method>
</method-permission>
</assembly-descriptor>

The deployer must then map the internal admin role to an actual role name in the Dynamo security
system. This is done in the dynamoJ2EESpecifier.xml file by resolving the role name to a security
group. See the J2EE Security chapter.
EJBs can also use programmatic security, in which the EJB code uses EJBContext APIs to determine the
identity of the current caller, or determine if the caller is in a particular role. You can use programmatic
security in conjunction with declarative security (unlike transactions, in which declarative and
programmatic transactions are mutually exclusive). When using programmatic security, the EJB can call
getCallerPrincipal() on the EJBContext to obtain the name of the current caller, and can call
isCallerInRole(String roleName) on the EJBContext to see if the current caller is in a particular
role.
If the EJB uses isCallerInRole, then the EJBs deployment descriptor must declare security-roleref tags for each roleName tested. In the deployment descriptor, those security-role-refs must be
resolved through role links to security roles declared in the assembly descriptor.

Timing of ejbLoad and ejbStore


When Dynamo manages entity EJBs, Dynamo is responsible for determining when ejbLoad and
ejbStore must be called on a particular implementation instance. This is true for both bean and
container managed persistence.
In the most conservative case, Dynamo could call ejbLoad right before every method call, and call
ejbStore right after every method call. This would insure that the instance is always getting the freshest
copy of the database state, and that its changes are immediately stored into the database. The drawback
to this approach is that it can cause performance to suffer in a situation where many methods are being
called on a single EJB. For example, an application might be setting several properties of an EJB by calling
the individual setter methods. The application may not want ejbLoad and ejbStore to be called around
each of those setter methods - it might make more sense for ejbLoad to be called once before the setters
are called, then ejbStore to be called after the setters are complete.
This is what Dynamo does by default. Instead of calling ejbLoad and ejbStore around each method call,
it calls ejbLoad once at the beginning of a transaction, then ejbStore once at the end of a transaction.
For example, in Transaction T1, a client might gain access to the Person EJB with ID 4. One of the pooled
EJB instances is selected to represent ID 4, and is then associated with transaction T1. The client then calls
a method on that instance. The method call is routed to the instance already assigned to represent ID 4 in

81
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

T1. Because that instance has not yet been loaded from the database, ejbLoad is called on the instance.
The method call is then executed on the instance.
The client might then make more calls in the same transaction to that same instance. Each call is routed
back to the same instance. However, ejbLoad is not called before any of those method calls since it was
already called the first time the EJB was used. Neither is ejbStore called after each of those method calls.
At some point transaction T1 ends. At that time, any EJBs associated with T1 call ejbStore, including the
EJB associated with ID 4. Because those EJBs have been synchronized with the database, those EJBs can
be dissociated from their entity instances and returned to the instance pool. This means that if the client
gains access to ID 4 again in a different transaction, the client could end up communicating with a
different EJB instance.
So that is the default behavior that Dynamo uses - it only calls ejbLoad once per instance per transaction,
and ejbStore once per instance at the end of the transaction. There are, however a couple of situations
where this behavior can create problems:

If a client makes a change to an entity instance, then executes a finder method in the
same transaction, the results from the finder might be incorrect with respect to the
entity instances state. For example, a client might change an instances age field from
20 to 21. The client might then execute a finder method to find all instances with age
greater than 20, then be surprised to find that the instance just changed is not in that
result set.
The reason for this is that even though the instances age field has been changed, that
change has not been stored to the database because the transaction has not yet
ended and ejbStore has not been called. So a finder method that executes a query
against the database will not see the change because it hasnt yet been written to the
database.

The EJB specification describes a situation called a transaction diamond, which can
occur with distributed transactions. If a client gains access to two different VMs in the
same transaction, and each of those VMs gains access to the same EJB, each VM will
have its own copy of the EJBs state in its memory. This opens the possibility of the two
EJBs getting out of sync - the EJB on one VM might change its state, but the change is
not seen by the EJB on the other VM since the transaction has not yet ended and the
new state has not yet been written to the database.

If an application runs into one of these situations, then it can change the default behavior back to the
more conservative approach of calling ejbLoad and ejbStore around every single method call. This can
be set on an EJB-by-EJB basis using the ejb-load-every-method and ejb-store-every-method tags:

<entity>
<ejb-name>
CMPPerson
</ejb-name>
<ejb-load-every-method>
True
</ejb-load-every-method>

82
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

<ejb-store-every-method>
True
</ejb-store-every-method>
...
<cmp-mapping>
<repository-name>
...

Instance Pooling and Management


Dynamo is responsible for managing the EJB implementation instances that execute the EJBs business
logic. A client with a pointer to an EJB might think that it is making several calls to the same EJB, while in
reality Dynamo is routing each call to a different EJB implementation instance. As long as the behavior is
indistinguishable to the client, Dynamo is free to manipulate instances in whatever way it finds optimal.
For stateful session beans, Dynamo has little freedom in the way it handles implementation instances.
Each bean the client thinks it has must correspond to an actual implementation instance in Dynamo.
When the client creates an instance, a corresponding implementation instance must be created in
Dynamo, and when the client removes an instance, an instance is removed from Dynamos memory.
The only freedom Dynamo has for stateful session beans is to passivate them (as described in the Session
EJB Passivation and Expiration section of this chapter). This allows Dynamo to serialize the beans state to
disk and remove the bean from memory. However, Dynamo must be prepared to activate the bean from
disk and place it back into memory the next time the client needs to gain access to it.
For stateless session beans, Dynamo has more freedom in the way it manipulates instances. Each call to a
stateless session bean can be handled by any bean instance that is not already handling another call. So
Dynamo uses a pool of instances that are ready to handle method calls. Any time a method call is needed,
an instance is selected from the pool to handle the call, and is returned back to the pool when the
method call is complete.
By default, Dynamo starts with no instances in the pool. If a method call is made and an instance is
required, Dynamo will create an instance then use it. When the method call is complete, the instance will
be placed in the pool for use by further method calls.
If many simultaneous method calls are executed, then several instances will need to be created and used,
and all of those instances will be returned to the pool. This means that the number of instances in the
pool corresponds roughly to the maximum number of simultaneous calls made by clients.
If there is a spike in usage, then the number of instances in the pool can increase suddenly. After the
usage spike, most of those instances will sit around unused in the pool, taking up memory and possibly
other resources. To handle this, Dynamo will periodically sweep through the pool and remove some
percentage of the instances sitting in the pool. This allows the pool to recover slowly from a spike and
bring the system back to a more steady state.

83
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

Configuring Instance Pools


All of this happens automatically without any intervention from the application or deployer. However, the
deployer may wish to adjust some of operational parameters involved:

min-pool-size - By default, a pool starts with no instances. The deployer may wish to
change a particular EJB to create a set of instances when the application starts, rather
than waiting for the EJB to be requested. This might be used if each instance takes a
while to be created. This value can be set on an EJB-by-EJB basis in the
dynamoJ2EESpecifier.xml file:
<session>
<ejb-name>
AddNumbers
</ejb-name>
...
<min-pool-size>
10
</min-pool-size>
</session>

Dynamo will make sure that periodic sweeps that remove instances from the pool will
not drop the pool below the minimum size.

max-pool-size - By default, Dynamo will create as many instances as are needed to


handle all simultaneous requests. If each instance takes up significant resources, then
this can be a problem in high-load situations. The deployer can limit the number of
instances in existence at once by setting the max-pool-size. If a method call requires
an instance but the maximum has been reached, that method call will block until
another method is done with its instance:
<session>
<ejb-name>
AddNumbers
</ejb-name>
...
<min-pool-size>
40
</min-pool-size>
</session>

poolReductionSchedule - Specifies how often Dynamo should sweep through the


pools to remove some fraction of the unused instances. By default this is set to one
minute, but the deployer may wish to change this value to account for the sites own
usage patterns. This setting is global to all of Dynamo, and is set in the component
/atg/dynamo/service/j2ee/EJBContainer:
poolReductionSchedule=every 5 minutes

poolReductionFactor - Specifies how many instances Dynamo should remove from


each pool each time it performs a sweep. This is specified as a fraction. By default it is
set to .5, which means that half of the instances in the pool are removed on each

84
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

sweep. If set to .25, then one quarter of the instances are removed, etc. This is also set
on a global basis in the EJBContainer:
poolReductionFactor=.25

Entity EJBs, using both bean- and container-managed persistence, are treated in a similar manner by
Dynamo. A particular EJB implementation instance can be directed to represent many different entity
instances over its lifetime. Dynamo manages these instances by letting a particular instance represent a
single entity instance over the lifetime of a transaction.
For example, if a client requests the entity with ID 4 in transaction T1, Dynamo will select an
implementation instance from the pool, initialize it to point to ID 4, and remember that for transaction T1,
ID 4 is handled by that instance. If the client makes subsequent calls in the same transaction for the same
entity ID, it will use the same instance. But when the transaction ends, that instance will be dissociated
from the transaction and entity ID, and returned to the pool.
So even though entity implementation instances may be used over several method calls before being
returned to the pool, the basic pooling mechanism remains the same as that used by stateless session
beans. This means that the same operation parameters described above can be applied to entity instance
pools as well as stateless session pools.

Session EJB Passivation and Expiration


The stateful session EJB model requires that Dynamo maintain the state of each session bean created by
the EJBs clients. Each session bean instance consumes memory in Dynamo, so Dynamos ability to handle
multiple clients is limited by the amount of memory available to Dynamo.
To alleviate this, Dynamo has the ability to passivate implementation instances when it detects that it is
starting to run low on memory. When Dynamo passivates an instance, it serializes the instances state to
disk and removes the instance from memory. The client has no notion that this has happened and may
continue to make method calls on the instance. If it does so, the instance is activated, meaning that its
state is deserialized from disk and the instance is brought back into memory so it can handle the method
calls.
Just before an instance is passivated, its ejbPassivate() method is called to allow it to prepare itself for
serialization. Just after an instance is activated, its ejbActivate() method is called to allow it to recover
from the deserialization process.
Dynamos passivation mechanism works by periodically sweeping through all of the session instances in
the system and seeing if they take up too much memory. If so, then those sessions that have gone unused
the longest are passivated until the amount of memory used by the instances remaining in memory is
acceptable. Dynamo determines how much memory each instance takes up by serializing the instance
and seeing how many bytes the instances serialized state takes up. This is by no means exact, but it is a
good approximation.
Dynamo needs to be configured with a directory in which to store passivated instances. Dynamo uses a
rotating set of files to store the instances. Whenever an instance is passivated, its serialized state is
appended to the current file. When the current file becomes too large, a new file is created and becomes
the new current file. Meanwhile, instances are being activated or expired from older files, thereby
removing them from those files. Once all of the instances in a file have been removed, that file is removed.

85
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

So what should happen over time is that new files get filled up, become older, get drained out, and
eventually get removed.
Session expiration is closely related to passivation. Dynamo can be configured to expire session beans
that have gone unused for a period of time. At the same time that Dynamo sweeps through session
instances looking for instances to passivate, it also looks for instances to expire. Any that have gone
unused for too long are removed, after being notified through the ejbRemove call. If an instance was
passivated, then it is also marked as expired in the file holding the instances passivated state, which
might cause that file to be removed if there are no further instances in that file.
You can configure how Dynamo expires or passivates session beans. These properties must be set in the
/atg/dynamo/service/j2ee/EJBContainer component:

Property

Description

sessionInstanceTimeout

The length of time, in milliseconds, that a stateful


session EJB can go unused before it is destroyed. For
example, 1800000, the default, represents 30 minutes.
If set to -1, then session instance expiration is disabled.

maxTotalActiveSessionInstanceSize

The maximum number of bytes that can be held in


memory by stateful session instances. EJBs over this
limit are passivated. The default value is 16777216
bytes. If set to -1, then passivation is disabled.

sessionExpirationSchedule

The interval at which Dynamo sweeps through the


EJBs looking for instances to expire or passivate. By
default this is set to every 1 minute.

instanceStoreDirectory

The name of the directory on disk where Dynamo


should store passivated instances. If instance
passivation is activated, this must be configured. The
directory should be dedicated to Dynamos
passivation use and should not contain other files. The
default value is as follows:
{atg.dynamo.server.home}/sessionswap

instanceStoreMaxEntryCount

The maximum number of passivated instances a


single file will hold before it starts a new file. By default
this is set to 1000, and probably should not be
changed.

instanceStoreFileExpansionSize

The files holding passivated instances will expand


their size in chunks, to avoid fragmentation of the files.
This property determines how many bytes the file will
grab at once. By default it is set to 100000 and
probably should not be changed.

86
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

Accessing EJBs from Nucleus Components


If the client is in the same application as the EJB, then it should use the java:comp/env/ejb/... name
to gain access to the EJB. If the client is not in the same application, then it can use the technique
described in the Lightweight Application Clients section of the Application Clients chapter.
If the client is not part of the same J2EE application but is running in the same VM, then you can use a
more efficient method. This would be the case, for example, if a Nucleus component wanted to gain
access to an EJB running in the same VM.
In this case, the client should still use the same code to gain access to the EJB, but the JNDI name it
supplies should look like this:
dynamoejb:/{app name}/{module URI}/{ejb name}

For example, a Nucleus component can gain access to the AddNumbers EJB in the same VM by using this
code:

InitialContext ctx = new InitialContext (env);


AddNumbersHome addNumbersHome =
(AddNumbersHome)
PortableRemoteObject.narrow
(ctx.lookup ("dynamoejb:/simpleJ2EE/ejbs/AddNumbers"),
AddNumbersHome.class);

Note that for an EJB in an EJB 1.1 module, the JNDI name omits the module URI. In this case, the JNDI
name would be dynamoejb:/simpleJ2EE/AddNumbers.
This approach should yield better performance since it bypasses the remote call mechanisms and gives
the application a direct link to the underlying EJB objects.
You do not have to specify properties. The username and password are inherited from the current thread,
which may have set them through a variety of mechanisms, such as an HTML login.

Container-Managed Persistence
Container-managed persistence (CMP) is one of the most attractive features of the EJB system. It allows
developers to gain access to persistent data without any of the usual JDBC or network coding. The EJB
CMP model is fairly simple: The EJB declares which of its public member variables or properties it wants to
be persistent, and the EJB container loads those variables from the database before an instance is used
and saves their values back to the database after the instance has been used.
The J2EE 1.3 specification requires the application server to support both EJB 2.0 and EJB 1.1 CMP.
Conceptually the two CMP versions are similar, but there are some significant differences in the
implementation. This section provides an overview of features that are general to both versions of CMP,
and then discusses the simpleEJB demo, which includes examples of both EJB 2.0 and EJB 1.1 style CMP.

87
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

EJB Field Types for CMP


For an EJB to use Dynamos CMP for persistence, the EJBs fields must be one of the following types:

primitives - boolean, byte, char, int, long, float, double. Map these values to
repository properties of similar type. For example, int should map to a property of
type Integer. If a property value is of type null, then the value assigned to the
primitive field value is undefined.

primitive objects - java.lang.Boolean, Byte, Character, Integer, Long, Float,


Double. Map these values to repository properties of similar type. Unlike the primitive
types, these classes can represent null property values.

java.lang.String - String fields should map to String properties in the repository.

primitive arrays - boolean[], byte[], char[], int[], long[], float[], double[].


Map these values to properties that are either arrays of the same primitive, arrays of
the same primitive Object (e.g., map boolean[] to Boolean[]), or Collections of the
same Object (e.g., map int[] to a Set of Integers).

primitive object arrays - Boolean[], Byte[], Character[], Integer[], Long[],


Float[], Double[]. Map these values to properties that are either arrays of the same
primitive (e.g., map Boolean[] to boolean[]), arrays of the same primitive Object, or
Collections of the same Object (e.g., map Integer[] to a Set/List/Collection of
Integers).

java.lang.String[] - String fields should map to String[] properties in the repository,


or to properties that are Collections of Strings.

Serializable - Any other serializable object that doesnt fit the above descriptions will
be stored in its serialized byte form. This means that it must map to a repository
property of type binary. Fields of this type cannot be queried meaningfully.

Container Managed Relationships


EJB 2.0 includes container managed relationships (CMR) as part of the CMP system. CMR fields are
declared in the relationships and ejb-relation elements of the ejb-jar.xml. They can optionally
be mapped in the dynamoJ2EESpecifier.xml file using the relationship-field-mapping element.
A CMR field is always typed as an EJB local interface, or a Collection or Set of local interfaces.

Detecting Changed Fields


When you use container-managed persistence, Dynamo fills an instances fields with values from the
database and stores the fields values back into the database. Many times, however, the instance will not
change any fields, or will change only a few fields. In these cases, it is wasteful to write the beans entire
state back to the database. You should write back only those values that have changed.
Unfortunately, there is no way to tell which of the instances fields have changed. Dynamo cannot
intercept every time the EJB code sets a fields value, or the value of an object that a field indirectly
references. To get around this limitation, Dynamo saves the values of the fields when the field values are
loaded, and compares those values to the values of the fields after the EJB has completed its operation.
Only those values that have changed are written to the database.

88
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

This process will not detect all changes. Dynamo can reliably detect changes for immutable objects, such
as Strings and primitives, but is less reliable for more complex objects, such as arrays or collections.
As a result, Dynamo takes a conservative approach to detecting changes. If Dynamo can reliably
determine whether a value has changed or not, then it writes the value if it has changed. But if Dynamo
cannot be sure that a value has changed, then Dynamo writes the value anyway. Dynamo may appear to
be rewriting values that arent changing, but, in fact, Dynamo is only doing that because it cannot detect
that the value has not changed.

Configuring CMP
As described near the beginning of this chapter, the simpleEJB demo includes several entity beans that
use CMP. This section discusses two of those EJBs, CMPPerson and CMP2Person. These EJBs are
functionally equivalent, and differ primarily in that CMPPerson uses EJB 1.1 CMP, and CMP2Person uses
EJB 2.0 CMP.
Dynamo uses a SQL repository as its persistence mechanism for both versions of CMP. Mapping a CMP EJB
to an underlying data store involves two parts. The repository definition file (typically named
sqlRepository.xml) creates the repository views (item descriptors) and maps their properties to tables
and columns in a SQL database. The Dynamo J2EE specifier file then maps the EJBs member variables or
properties to repository views and their properties. Note that all EJBs in an application that use EJB 2.0
CMP must use the same repository.

The sqlRepository.xml File


The SQL repository maps repository views and properties to actual tables and columns in a database.
These mappings are defined in an XML file named sqlRepository.xml, which is found at J2EEExamples/SimpleEJB/j2ee-apps/simpleEJB/META-INF/DYNAMO-INF/sqlRepository.xml.
A repository view is analogous to a class, in that it represents an object type in the repository. You use an
<item-descriptor> tag to define each repository view. Within that tag, the view contains at least one
<table> tag that defines the primary table for that item descriptor. Each table must specify which of its
columns acts as the repositorys ID.
The following is the portion of the sqlRepository.xml file that creates two item descriptors,
ejbPerson and ejbCmp2Person, that represent the CMPPerson and CMP2Person EJBs:

<?xml version="1.0" encoding="ISO-8859-1" ?>


<!DOCTYPE gsa-template
PUBLIC "-//Art Technology Group, Inc.//DTD General SQL Adapter//EN"
"http://www.atg.com/dtds/gsa/gsa_1.0.dtd">
<gsa-template>
<item-descriptor name="ejbPerson">
<table name="EJB_PERSON"
type="primary"
id-column-name="ID">

89
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

<property name="id"
column-name="ID"
data-type="int"/>
<property name="name"
column-name="NAME"
data-type="string"/>
<property name="age"
column-name="AGE"
data-type="int"/>
</table>
</item-descriptor>
...
<item-descriptor name="ejbCmp2Person">
<table name="EJB_PERSON2"
type="primary"
id-column-name="ID">
<property name="id"
column-name="ID"
data-type="int"/>
<property name="name"
column-name="NAME"
data-type="string"/>
<property name="age"
column-name="AGE"
data-type="int"/>
</table>
</item-descriptor>
...
</gsa-template>

The repository views defined above are very simple. In a more sophisticated application, you may need to
define complex relationships in your data. For example, an EJB representing a person might have a
spouse property that points to another EJB.
The SQL repository is sophisticated enough to model a wide variety of relationships. However, the
mapping can be complex, especially if you are not used to the semantics of defining repository views. You
can avoid this step entirely by using CMP Automatic Mapping, described below.
For more information about configuring SQL repositories, see the ATG 6 Repository Guide.

Mapping EJBs to Repositories


The other part of configuring CMP for EJBs involves mapping each EJB to an item descriptor in the
dynamoJ2EESpecifier.xml file. The cmp-mapping tag in the dynamoJ2EESpecifier.xml file
determines how an EJBs fields map to repository properties.

90
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

The configuration begins by specifying which repository will handle the persistence. You can specify the
repository as either a global or application resource. The SimpleEJB demo creates a repository as an
application resource named gsa1, and the CMPPerson and CMP2Person EJBs both link to this resource:

<cmp-mapping>
<repository-link>
gsa1
</repository-link>
...
</cmp-mapping>

Each EJB must specify which repository view (item descriptor) in the repository will represent the EJB
instances:

<entity>
<ejb-name>
CMPPerson
</ejbname>
...
<repository-view-name>
ejbPerson
</repository-view-name>
...
</entity>
...
<entity>
<ejb-name>
CMP2Person
</ejbname>
...
<repository-view-name>
ejbCmp2Person
</repository-view-name>
...
</entity>

The next step is to map the each persistent field in the EJB to a property in the repository view. The EJB
container handles the datatype conversions between the values in the repository and the values of the
fields. For EJB 1.1 CMP, the EJB member variables are mapped to the properties of the corresponding
repository view. For example, the mapping for the mAge member variable of CMPPerson looks like this:

<field-mapping>
<field-name>
mAge
</field-name>
<property-name>

91
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

age
</property-name>
</field-mapping>
...

For EJB 2.0 CMP, the properties of the EJB (not the member variables) are mapped to the properties of the
corresponding repository view, so the equivalent mapping for CMP2Person looks like this:

<field-mapping>
<field-name>
age
</field-name>
<property-name>
age
</property-name>
</field-mapping>
...

Finally, each EJB 1.1 finder method or EJB 2.0 query method must have a corresponding query that the
container uses to query the repository. For EJB 1.1 CMP, the query is defined in the
dynamoJ2EESpecifier.xml file, and is written using Dynamos repository query language (RQL). Note
that the finder query is defined in terms of the property names (e.g., age), not the names of the member
variables (e.g., mAge). For example, the finder query for the findBetweenAges method of CMPPerson is
defined like this:

<finder-method>
<method-name>
findBetweenAges
</method-name>
<finder-query>
<![CDATA[ age >= ?0 AND age <= ?1 ]]>
</finder-query>
</finder-method>

The ?x expressions refer to arguments of the method. For example, the findBetweenAges method has
two arguments, pLowAge and pHighAge. When the method is called, pLowAge will be substituted in place
of ?0, and pHighAge will be substituted in place of ?1. The query is enclosed in a CDATA section so the <
and > characters do not affect the parsing of the XML file.
For EJB 2.0 CMP, the query is defined in the ejb-jar.xml file, and is written using EJB-QL, the standard
query language defined in the EJB 2.0 specification. The query for the findBetweenAges method of
CMP2Person is defined like this:

<query>
<description>

92
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

</description>
<query-method>
<method-name>
findBetweenAges
</method-name>
<method-params>
<method-param>
int
</method-param>
<method-param>
int
</method-param>
</method-params>
</query-method>
<ejb-ql>
<![CDATA[SELECT DISTINCT OBJECT(o) FROM CMP2Person o WHERE o.age >= ?1
AND o.age <= ?2]]>
</ejb-ql>
</query>

CMP Automatic Mapping


One downside of container-managed persistence is that the process of creating the database schema and
the SQL repository can be tedious and time-consuming, especially if there are many EJBs or persistent
fields. In addition, the mapping of EJB fields to repository views, and repository views to database tables
and columns, must be done exactly right or CMP will not work properly.
To simplify this process, Darina has the ability to automatically generate both the repository definition file
and a SQL script for creating the corresponding database tables. When you build the application, Darina
examines the ejb-jar.xml file to determine the fields that need to be mapped (and for EJB 2.0 CMP, any
container-managed relationships that have been defined), and then examines the EJBs to determine what
datatypes to use. Using this information, it then generates a repository definition file named
_cmpRepository.xml, and a SQL script named create_repository_tables.sql. These files are
created in applications META-INF/DYNAMO-INF subdirectory (the same location used for the
dynamoJ2EESpecifier.xml file).

Using Automatic Mapping


CMP automatic mapping is configured in the dynamoJ2EESpecifier.xml file. To specify automatic
mapping for an entity EJB, you use the auto-mapping tag. This is an empty tag that replaces the fieldmapping tags described above.
Darina uses automatic mapping by default, for both EJB 2.0 and EJB 1.1 CMP. When you run Darina on an
application in an EAR file, Darina unpacks the application into a staging directory, and creates a
dynamoJ2EESpecifier.xml file that specifies automatic mapping for all entity beans that use CMP.
Then, when you build the application, Darina automatically generates the repository definition file and
the SQL script for creating the tables.

93
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

The names of the item descriptors and database tables are automatically generated. You can modify the
SQL script to change the database table and column names, and you will probably need to change the
data types in the script to optimize them for your database and application.
If you modify the SQL script, you must also modify the repository definition file so the two files remain in
synch. For example, if you change the name of a database table in the
create_repository_tables.sql file, you must be sure to change it in the item descriptor definitions
in the _cmpRepository.xml file.
Its also a good idea to rename the files if you modify them, so your changes arent overwritten if you
build the application again. If you rename the _cmpRepository.xml file, you must also change the GSA
service definition in the dynamoJ2EESpecifier.xml file to reflect the new name.
Note that you cannot change the names of the item descriptors. When automatic mapping is specified
for an EJB, Dynamos J2EE container maps EJBs to the generated names of the item descriptors; if the
names have been changed, the mapping will not work. If you do change the names of the item
descriptors, you must remove the auto-mapping tags from the dynamoJ2EESpecifier.xml file and
manually map the fields. For example, you need to do this if you want your EJBs to use an existing
repository.
Darina also has a -cmp-repository-generate-all option that generates a repository definition file
and a SQL script for creating repository views and database tables for all CMP EJBs, regardless of whether
automatic mapping is specified.

Using the Deployment Editor


You can specify automatic mapping in the Dynamo Deployment Editor. To do this, open the application
in the editor, select an entity bean, and click the CMP tab. Your screen should look something like this:

94
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

Notice that there is a Mapping checkbox for each field, so you can turn mapping on and off on a field-byfield basis. This is useful if you are using CMP for an EJB that has one or more nonpersistent fields (e.g., a
field that is computed from the value of other fields, or a field whose data is not serializable).

EJB Clustering
For applications that involve many application clients, Dynamo provides an EJB clustering system that
allows you to scale these applications over many servers. Dynamos EJB clustering system was designed
to meet the following goals:

Limit the additional latency required to use a cluster rather than pointing directly at a
single server

Limit the overhead on the network of managing and maintaining information about
the cluster

Avoid bottlenecks that could limit the size of a cluster

Provide simple and dynamic cluster configuration

Support emerging standards for J2EE application management

95
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

Dynamos EJB clustering system is intended to be lightweight. Other EJB clustering systems impose a
great deal of network latency and overhead as they do things like multicast JNDI information to all nodes
in the cluster. Dynamos EJB clustering system avoids this overhead and focuses on providing lightweight
and reliable EJB clustering support.
Note: Dynamos EJB clustering system is intended for use with application clients only. It is not intended
to be used with other J2EE modules, such as web applications.

EJB Clustering Overview


To understand how Dynamos EJB clustering system works, you must first understand how application
clients communicate with a Dynamo server without using clustering.
First, an application client instantiates a JNDI (Java Naming and Directory Interface) InitialContext. The
InitialContext is configured to use a provider URL. The provider URL typically contains the URL of the
specific server that is going to serve all EJB requests.
Next, the application client looks up a specific EJB name in the JNDI InitialContext. If the lookup is
successful, it returns a stub that implements the EJB home interface.
The application client then makes calls through the home interface stub to create or find instances of the
EJB remote interface. The application client then makes calls through the EJB remote interface to execute
business logic.
While it is running, the application client talks only to one server. It does not matter how many threads or
transactions that application client creates; all the work load falls on a single server.
The key to understanding Dynamos EJB clustering system is to understand how the JNDI lookup behaves
differently and how the home and remote stubs behave differently when interacting with a cluster of
servers.

JNDI and Clustering


To use EJB clustering, the provider URL specified points towards a cluster manager. The JNDI context
implementation uses this URL to retrieve information about the cluster.
When the application client performs a lookup on a specific EJB name, the JNDI context information uses
a load balancing strategy to determine the servers in the cluster to which to send the request. A specific
server is chosen and the home interface stub for that server is returned.
Every call to a lookup method in JNDI provides an opportunity to balance load between multiple servers.
The load balancing strategy used is configurable. We describe this strategy in the next section.
Dynamo does not distribute directory information to the application client. The request to find the EJB
home interface is sent directly to one of the servers in the cluster. There is little advantage to distributing
directory information to application clients, and our approach avoids significant bookkeeping and
network traffic costs.

96
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

EJB Stubs and Clustering


The previous section described the load balancing that occurs when a JNDI look up takes place in an
application client. Dynamo also supports load balancing in individual stub method calls.
A cluster stub is a stub that can act as a proxy to a number of other stubs. For example, a single home
interface stub that is a cluster stub can also manage a number of other home interface stubs. Each stub
that is managed by a cluster stub can communicate with a different server.
A cluster stub allows load balancing to take place by directing method calls to stubs from different
servers. The load balancing strategy chooses the server to which to direct a specific method. (Please see
the next section for more on our load balancing strategy.)
The way in which we use a cluster stub depends on the kind of interface that the stub represents. The
following table describes how the type of interface affects the behavior of the cluster stub.

Interface

Cluster Stub Behavior

Home Interface

All method calls are load balanced using the load


balancing strategy.

Stateless Session Bean Remote Interface

All method calls are load balanced using the load


balancing strategy.

Stateful Session Bean Remote Interface

All method calls go to the original server. If the original


server fails, then the method call is load balanced to
another server in the cluster.

Entity Bean Remote Interface

All method calls go to the original server. If the original


server fails, then the method call is load balanced to
another server in the cluster.

Load Balancing Strategy


The default load balancing strategy in the Dynamo EJB clustering system is round robin and threadbased. Each thread in an application client is allocated a single server in a round-robin manner. Once a
thread is allocated to a single server, the thread uses that server until it fails or is no longer available in the
cluster.
The default load balancing strategy maintains information about the servers that are available in each
cluster and those that are available in each thread. If a server fails in one thread, then that server is labeled
as unavailable for that thread. We update this information whenever the application client retrieves new
information from the cluster manager.
The default load balancing strategy is suitable for application clients where many threads are used to
perform discrete tasks. An example of this might be a client that reads from a JMS queue and sends orders
to a cluster of EJB servers.

97
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

There are other types of applications for which the default load balancing strategy is not appropriate. In
those types of applications, a large number of inter-connected beans are being manipulated in many
threads. A visual user interface is an example of such an application. To support these kinds of
applications, you can change the default load balancing strategy to one where each application client
chooses a single server from the cluster. See the Lightweight Application Clients and EJB Clustering
section of the Application Clients chapter for information about how to specify this strategy.
Dynamo currently does not support transaction-based load balancing. The existing load balancing
strategies should be sufficient for many applications.

Failover and Clustering


In addition to scalability, the major advantage of EJB clustering is the ability to improve fault tolerance by
supporting failover when a server fails. The way in which failover occurs in the Dynamo EJB clustering
system is different for each kind of client interface.
For stateless session bean remote and home interfaces, all methods calls are load balanced. If a server
becomes unavailable, due to either the failure of a method call or the cluster managers reporting that the
server is unavailable, then that server will not be considered for load balancing.
For entity bean remote interfaces (using either CMP or BMP), the primary key of the entity bean is stored
in the cluster stub. When a method fails on an entity bean remote interface to a specific server, the
primary key is used to restore that bean in a different server in the cluster.
For stateful session bean remote interfaces, there is no primary key. The state of the stateful session bean
is not backed up in a database. To deal with this case, the Dynamo EJB clustering system introduces a
session ID that is associated with each stateful session bean.
The session ID for the stateful session bean is stored in the cluster stub. When a method fails for a
particular stateful session bean, you can use the session ID to restore that bean on a different server.
The Dynamo Session Backup Server backs up and restores stateful session beans. This is the same session
backup server that is used in Dynamo Web Application clustering.
Stateful session bean backup is expensive because it requires sending data to a back end network node.
Therefore, you can configure stateful session backup on a per bean basis. This process allows you to
protect the most critical stateful session beans in the case of failure.

Symmetric EJB Clusters


Dynamos EJB clustering system requires that all servers in the cluster be symmetric. All servers in the
cluster must be running the same applications and the same versions of these applications.
The Cluster Manager enforces the symmetry of the cluster by declaring a cluster policy. This policy defines
the names and versions of the applications that must be running in each server.
Other clustering systems may support asymmetric clusters. The Dynamo EJB clustering system uses
symmetric clusters because they are simpler to set up and manage, and they fulfill the vast majority of the
use cases expected. If asymmetric setups are needed, then you can set up multiple clusters, each with its
own cluster policy.

98
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

EJB Protocol Support


Dynamo currently supports only standard RMI as a transport protocol for EJB clustering. The Cluster
Manager will reject all applications that are configured to use RMI/IIOP.

Cluster Management
The Dynamo cluster management system is built on top of Suns JMX (Java Management Extensions)
technology. A JMX server runs on both cluster managers and cluster nodes. For more information about
JMX, visit http://java.sun.com/products/JavaManagement/.
Currently, the cluster management system uses SOAP-based services to handle communication between
managers and nodes. This strategy may change in the future. Several other Java Specification Requests
designed to fill this node are in development, and we may plug these requests into the cluster
management system at a later date. We do not currently support the use of third-party tools to invoke
these JMX interfaces.
For more information about SOAP, visit http://www.w3c.org/.

Dynamo EJB Clustering Architecture


The diagram below summarizes the major components in the Dynamo EJB clustering architecture. This
section discusses each component in turn.

JMX

Cluster Manager

JMX

Application Client

Cluster Node

Session Backup

Application Client

Cluster Node

Session Backup

RMI

Cluster Manager
The Cluster Manager is a Dynamo instance that manages information about the EJB cluster. The Cluster
Manager maintains information about the J2EE applications available in that server and the availability of
that server.
The Cluster Manager polls each server at a configurable interval and uses the collected information, in
conjunction with the cluster policy, to summarize the state of the cluster. The Cluster Manager serves this
information to application clients or servers that intend to use the cluster.

99
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

Cluster Node

A Cluster Node is an individual Dynamo Server. It must be running every J2EE application at the version
required by the cluster policy. Cluster Nodes are added to the cluster either explicitly via the
ClusterManager, or they can dynamically register themselves with the cluster.

Application Client
An application client is either a J2EE application client module or a standalone application. The
application client is configured with a list of cluster managers. When the application client first creates a
JNDI InitialContext, a thread is started in the application client. This thread polls the Cluster Manager at
configurable intervals to retrieve information about the cluster.

Session Backup Server


The session backup server is a separate Dynamo server that manages a dictionary of mappings from
Stateful Session bean IDs to the serialized state of Stateful session beans. The session backup server runs
its own lightweight TCP protocol for backing up and restoring dictionary entries.

Cluster Manager Configuration and Administration


The section describes how to configure and administer a Cluster Manager.

Configuring a Cluster Manager


The Dynamo cluster manager is provided by the
/atg/dynamo/service/management/EJBClusterManager Nucleus service. You need to configure the

following properties when you set up a ClusterManager:

Property

Description

enabled

Boolean. Switches the cluster manager on and off.


Example:
enabled=true

initialClusterNodes

java.lang.String[]. An array of SOAP service URLs for each initial


node in the cluster. By default, this service is located at
http://localhost:8830/ejbClusterManagement.

Example:
initialClusterNodes+=http://machinea.atg.com:8830/
ejbClusterManagement,
http://machineb.atg.com:8830/ejbClusterManagement

100
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

availabilityTolerance

int. The number of times a node can be unavailable before the


cluster manager removes it from the list of cluster nodes.

Example:
availabilityTolerance=2

We use the service /atg/dynamo/service/management/EJBClusterPolicy to define the valid nodes


in the cluster. You need to configure the following properties:

Property

Description

requiredApplicationNames

java.lang.String[]. An array of J2EE application names. The

J2EE application name is defined in the <application-name>


element in the dynamoJ2EESpecifier.xml file for the application.
Each node in the cluster must run each of the applications named
by this property.
Example:
requiredApplicationNames+=clusterEJB
requiredDarVersions

java.lang.String[]. An array of Dynamo Archive file (.dar)

version strings, one for each application name in the


requiredApplicationNames array. Each node in the cluster
must run each application in the requiredApplicationNames
property at the version specified in this property.
Example:
requiredDarVersions+=0

The version number of the .dar file is updated and printed to the console whenever you use the
runDarina command to build or update your .dar file, unless you have also specified one of the quiet
options, (-q or Q). The version number changes each time runDarina processes it, even if you have
made no changes to the application. To check the version of an existing .dar file without updating it, use:
runDarina dar-version dar-file

An application run from a stage directory will report a version number of zero to the cluster manager. You
may still use clustering in this case. Set the relevant element of the requiredDarVersions property to 0,
but keep all the stage directories in perfect synchronization to avoid subtle versioning problems.
The ClusterManager also uses the /atg/dynamo/service/management/DynamoInfoCollector
service to collect information about each cluster node. You can configure the following properties on this
service to control how this information is collected:

101
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

Property

Description

basicAuthenticationUsername

java.lang.String. The username passed in the HTTP basic-

authentication header. By default, this name is set to admin.


If you have changed the username for the admin servlet
pipeline, then change basicAuthenticationUsername to
the same value.
java.lang.String. The password passed in the HTTP basic-

basicAuthenticationPassword

authentication header. By default, this password is set to


admin. If you have changed the password for the admin
servlet pipeline, then change
basicAuthenticationPassword to the same value.
java.lang.String. The number of milliseconds for which the

socketConnectTimeout

DynamoInfoCollector will wait when creating the socket it

uses to communicate with the cluster node. The default value


is 30000. You can increase or decrease this value as needed.
int. The number of milliseconds for which the

socketSoTimeout

DynamoInfoCollector will wait when reading from an open

socket to the cluster nodes SOAP server. The default value is


20000. You can increase or decrease this value as needed.

Administering a Cluster Manager


Use Dynamos HTML Admin UI (/atg/dynamo/service/management/EJBClusterManager) to
administer the EJBClusterManager. You can use this Admin UI to perform the following cluster
administration actions:

Action

Description

Add a new node to the Cluster

Click on the addClusterNode property.


Enter the SOAP URL for that node (e.g.
http://machinec.atg.com:8830/ejbClusterManagement).

Click Change Value.


Remove a node from the Cluster

Click on the removeClusterNode property.


Enter the SOAP service URL for that node (e.g.
http://machinec.atg.com:8830/ejbClusterManagement).

Click Change Value.

102
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

View the state of the Cluster

Click on the clusterState property.


The cluster state property will display the state of the cluster at a
fixed number of snapshots. The stackSizeMax property on the
ClusterManager allows you to configure the number of
snapshots.

If a cluster node becomes unavailable that is, the cluster manager cannot poll the node successfully
within the required period, perhaps due to network problems or heavy load on the node the cluster
manager uses the entry for this node from the previous frame and notes that the node was missing. The
availabilityTolerance property controls the number of consecutive attempts that the cluster
manager makes before removing the node from the cluster. The cluster manager continues to poll the
node even after it has been removed from the cluster. If the node begins to respond again, the cluster
manager adds it back to the cluster and resets its availability count.
If a cluster node can be polled successfully but does not meet the requirements of the cluster definition,
then the cluster lists the node, but the nodes isAvailable flag is set to false.
Removing a node from the cluster manager does not guarantee that nodes or app clients will stop using
the node. An app client that already has a reference to an EJB from the removed node may continue to
use the node. The effect is to remove the node from the list of nodes the cluster manager advertises as
available.
Adding a node with this interface does not immediately make it available. The node becomes available
only when the manager polls it successfully and determines that it meets the requirements of the cluster
definition.

Cluster EJB Example: Running a Cluster Manager


Dynamo comes with a ClusterEJB demo in the J2EE-Examples directory. This demo illustrates the
configuration of Dynamos EJB clustering system. This section shows you how to set up a cluster manager.
To set up a cluster manager, begin by editing this file:
<DAS6dir>/J2EE-Examples/ClusterEJB/ClusterManager/config/
atg/dynamo/service/management/EJBClusterManager.properties

Set the property initialClusterNodes to point to the ejbClusterManagement service on each of the
Dynamos that are in the cluster. For example, if you plan to run two cluster nodes on machines
machinea.atg.com and machineb.atg.com, then set the following:
initialClusterNodes=http://machinea.atg.com:8830/
ejbClusterManagement,
http://machineb.atg.com:8830/ejbClusterManagement

To launch a Dynamo server with a Cluster Manager, run the following command from your
<DAS6dir>/home directory.
bin/startDynamo -m J2EE-Examples.ClusterEJB.ClusterManager

103
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

Cluster Node Configuration


This section describes how to configure each server node in the cluster.

Configuring the EJBClusterClientService


Each cluster node must configure the
/atg/dynamo/service/management/EJBClusterClientService Nucleus service.

Property

Description

enabled

Boolean. Required. Switches the cluster client service


on and off. (Note: For a node to run properly, you
must enable EJBClusterClientService. If you do
not enable this component, the cluster manager will
still be able to direct applications to this node, but
backup and failover of these applications will not
work.

Example:
enabled=true
providerURL

java.lang.String[]. Required. An array of SOAP


URLs that defines the list of cluster managers. The
array must have at least one element. The first
element in the array is the primary cluster manager.

Example:
providerURL=http://cluster-managerhostname:8830/ejbClusterManagement
clientProviderURL

java.lang.string[]. The URL that a cluster


manager uses to identify and communicate with this
cluster node. By default, this property points to
http://cluster-nodelocalhost:8830/ejbClusterManagement,

Dynamos SOAP-based management service.


Required if the joinClusterOnStartup or
departClusterOnShutdown properties are set to
true.

Example:
clientProviderURL=http://cluster-nodelocalhost:8830/ejbClusterManagement

104
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

joinClusterOnStartup

Boolean. Set this property to true if you want


Dynamo to send a join message to each cluster
manager configured in providerURL. A cluster
manager that receives this message will add the
sending Dynamo (identified by the
clientProviderURL) to the list of cluster nodes
from which it attempted to retrieve cluster
information. This action does not permanently add a
node to a cluster managers initialClusterNode
property.

Example:
joinClusterOnStartup=true
departClusterOnShutdown

Boolean. Set the departClusterOnShutdown


property to true if you want Dynamo to send a
depart message when the
EJBClusterClientService component shuts
down. A cluster manager receiving this message will
remove the sending Dynamo from the list of cluster
nodes from which it attempted to retrieve cluster
information. This action does not permanently
remove a node from a cluster managers
initialClusterNode property.

Example:
departClusterOnShutdown=true
departOnlyAutoJoinedClusterManagers

Boolean. Set
departOnlyAutoJoinedClusterManagers to true

if you are concerned about the amount of time it


takes the EJBClusterClientService to send the
depart message to all the cluster managers defined
in providerURL. If this property is true, then the
EJBClusterClientService will send a depart
message to only those cluster managers to which it
sent successfully a join message. This property is
meaningful only if joinClusterOnStartup and
departClusterOnShutdown are set to true. If
departOnlyAutoJoinedClusterManagers is set to
false, then the EJBClusterClientService
component will send the depart message to all the
cluster managers defined in the providerURL.
Example:
departOnlyAutoJoinedClusterManagers=false
retriesPerClusterManagerOnJoin

int. Sets the number of times the cluster node will


try to join the cluster. The default value is 10.

105
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

intervalBetweenRetriesOnJoin

int. Sets the time in milliseconds that the cluster


node will wait between attempts to join the cluster.

clusterPollingInterval

java.lang.Long. Defines the frequency in


milliseconds with which the client should update its
cluster information from the cluster manager. The
default value is 30,000.

clusterSecurityCredentials

java.lang.String. Defines the password passed in


the HTTP Basic Authentication header. This password
should be the same as the one set for the Dynamo
Admin pipeline.

clusterSecurityPrincipal

java.lang.String. Defines the username passed in


the HTTP Basic Authentication header. This username
should be the same as the one set for the Dynamo
Admin pipeline.

securityCredentials

java.lang.String. Defines the password that the


client should use when making EJB calls. This
password should be the same as the one set for the
Dynamo Admin pipeline.

securityPrincipal

java.lang.String. Defines the username that the


client should use when making EJB calls.

Configuring the Host Name


By default, Dynamo calls InetAddress.getLocalHost().getHostName() to determine the host name
of a cluster node. The host name is used by other cluster clients to identify the cluster node and its
services.
If a cluster node is in a different subnet from other cluster clients, getHostName() may not return
sufficient information to identify that cluster node to these clients. To ensure that other cluster clients can
communicate with a cluster node, you can set the rmiServiceHostName property of the nodes
J2EEContainer to the fully qualified domain name of the node. When this property is set, Dynamo uses
the value of this property rather than the value returned by getHostName().
For example, to set the rmiServiceHostName property for the default Dynamo server, create a
J2EEContainer.properties file in <DAS6dir>/home/localconfig/atg/dynamo/service/j2ee
and include a line similar to this:
rmiServiceHostName=machineb.dhcp.atg.com

Cluster EJB Example: Running a Cluster Node


To set up a cluster node, you must first edit the file:
<DAS6dir>/J2EE-Examples/ClusterEJB/ClusterNode/config/atg/dynamo/service/
management/EJBClusterClientService.properties

106
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

Set the property providerURL to point the Cluster Manager. For example:
providerURL=http://localhost:8830/ejbClusterManagement

To run a cluster node that includes the ClusterEJB J2EE application, run the following command from
the <DAS6dir>/home directory:
bin/startDynamo -m J2EE-Examples.ClusterEJB.ClusterNode

Note: When you first start a cluster, the cluster manager will try to communicate with each node in the
cluster and each node will in turn try to communicate with the cluster manager. If some of the services
with which they are trying to communicate are not yet running, you may receive warning messages on
the console. The ClusterClientService component may tell you that a retryable error occurred while
trying to receive ClusterInfo from the cluster manager, and the Cluster Manager may tell you that it
could not retrieve DynamoInfo from a particular cluster node. These messages should disappear once all
the members of the cluster are running. If, after five to ten minutes (depending on the size of the cluster),
these warnings persist, then you should check the Dynamo instances identified in the message to make
sure they are running and are configured correctly.

Configuring Session Backup


To enable a stateful session bean for session backup, you must use the enable-session-backup element.
For example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dynamo-j2ee-specifier SYSTEM
"http://www.atg.com/j2ee/dtds/dynamoJ2EESpecifier_1_3.dtd">
.
<session>
<ejb-name>Averager</ejb-name>
<session-backup-enabled>True</session-backup-enabled>
</session>

The Nucleus service /atg/dynamo/service/j2ee/SessionBackupClient backs up and restores


stateful session beans to backup dictionary servers. This service inherits configuration from the standard
Dynamo Configuration component /atg/dynamo/Configuration. In particular, the
SessionBackupClient inherits the properties listed in the following table. These properties are used to
configure HTTP session backup:

Property

Description

backingUpSessions

The property that you set to turn on session failover.

useSessionBackupServerHostName

The host name (or IP address) of the dictionary server


used to maintain backups of the servers session data.

useSessionBackupServerPort

The port number on which the dictionary server is


listening.

107
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

allowedRestorationAddresses

The list of IP addresses from which we can restore


sessions.

When general session backup is switched on in Dynamo, EJB session backup is switched on as well. Only
stateful session beans that have been labeled for session backup are backed up when session backup is
enabled in Dynamo.
The SessionBackupClient also has the following properties, which are not inherited from the general
Dynamo configuration:

Property

Description

dictionaryClientAddress

Use this property to specify a different address for the local end
of the socket if you have more than one network card.

socketFactory

Use this property to override the socket factory that create


sockets that connect to the dictionary server

clientPoolSize

Set this property equal to the number of clients that can


simultaneously back up stateful session beans. The default is 10.

waitForConfirmation

This property indicates whether the backup client will wait for
confirmation from the dictionary server when the client is
backing up a stateful session bean. The default is true.

108
6 - Enterprise JavaBeans

ATG 6 J2EE Development and Deployment Guide

7 Application Clients

Application clients are complete Java applications that are packaged into a J2EE application. An
application client runs within an application client container, in a VM that is separate from the main
Dynamo server processes, and typically interacts remotely with Enterprise JavaBeans on the server. An
application client can be a graphical interface to the business logic on the server, or a command-line
maintenance utility for use by system operators, or a batch utility run by a separate scheduler, etc.
Even without the use of application clients, Java applications can be written to interact with EJBs on other
servers (see Lightweight Application Clients at the end of this chapter). However, developing and
packaging an application as a J2EE application client has some advantages:

The applications environment is defined in a deployment descriptor, which makes its


configuration consistent with other J2EE elements.

The application can link to EJBs back on the server using the same ejb-ref and ejblink tags that other J2EE elements use. The container takes care of establishing the
right RMI connections, JNDI factories, etc.

The application can use the containers resource factories, such as JDBC data sources,
without having to create and manage those resources in its own code.

The application can be developed, verified, and packaged the same way as all other
elements of the J2EE application.

This chapter does not discuss the details of writing an application client. The basic mechanics of writing,
packaging, deploying, and running an application client are discussed in the Creating a Sample J2EE
Application chapter of this manual. This chapter concentrates on configuring and deploying application
clients.

Application Client Overview


Application clients are written in Java and packaged in EAR files as separate modules. Each module has its
own META-INF/MANIFEST.MF file, which identifies the Main-Class of the application client (the class
containing the main method).
Like other J2EE components, application clients may reference environment entries, resources, and EJB
homes through the JNDI java:comp/env space. The EJB references may be linked to other EJBs in the
same J2EE application (possibly in different modules), or they may be left blank to be filled in at
deployment time.

109
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

At deployment time, any unresolved references must be filled in using the dynamoJ2EESpecifier.xml
file. As with other J2EE components, environment entries may be filled in at this point, as can EJB
references.
Resource references, such as JDBC Data Sources and JavaMail Sessions, must also be resolved. Unlike
other J2EE components, these references cannot be resolved by pointing them at Nucleus components.
This is because these Nucleus components reside on the server and are inaccessible to an application
client in a different VM. Instead, these resource references must be resolved as application resources.
Once the J2EE application has been deployed successfully, both the server and application client can be
run. The server must be started first. Once the server is running, multiple instances of the application
client can be started and stopped.
The application client is run using a script called <DAS6dir>/home/bin/runAppClient. This script must
be passed several arguments, including:

the location of the deployed DAR file

the name of the application client in the J2EE application (a J2EE application may
contain several application clients)

the protocol/hostname/port of the server

the username and password to use to connect to the server, etc.

Note that the runAppClient script requires that the Dynamo server is installed and running on the same
machine as the application client. To run an application client on a different machine from the server, see
Running an Application Client Remotely.

Deploying Application Clients


Unlike other J2EE modules, application clients cannot resolve resource references using the JNDI form of a
Nucleus component name. Nucleus components reside on the server and are inaccessible to application
clients. Instead, application clients must resolve resource references locally, as described in this section.

Resolving JDBC Resource References


An application client that uses JDBC directly (as opposed to using EJBs for persistence) will have a
resource reference to a javax.sql.DataSource. In code, the application client gains access to this
reference through JNDI, using a name like java:comp/env/jdbc/db1. In its deployment descriptor, the
application client will declare that it has a resource reference of type javax.sql.DataSource.
This resource reference must be resolved in the dynamoJ2EESpecifier.xml file. One way to resolve it is
to set the resource reference to a resource link and then use jdbc-service to configure the resource
directly:

<jdbc-service>
<resource-service-name>

110
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

jdbc1
</resource-service-name>
<jdbc-lookup>
DriverManager
</jdbc-lookup>
<jdbc-url>
jdbc:solid://localhost:1313
</jdbc-url>
<jdbc-driver-class>
solid.jdbc.SolidDriver
</jdbc-driver-class>
<min-pool-size>
10
</min-pool-size>
<max-pool-size>
10
</max-pool-size>
<max-pool-free>
10
</max-pool-free>
<resource-username>
admin
</resource-username>
<resource-password>
admin
</resource-password>
</jdbc-service>

See Mapping Resource References in the Dynamo and J2EE chapter for more details.
Another approach is to resolve the JDBC reference using the resource-name and jdbc-res-conf tags:

<app-client>
<module-uri>
appclient
</module-uri>
...
<resource-ref>
<res-ref-name>
jdbc/db1
</res-ref-name>
<resource-name>
jdbc:solid://localhost:1313
</resource-name>
<jdbc-res-conf>
<jdbc-lookup>
DriverManager

111
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

</jdbc-lookup>

<jdbc-driver-class>
solid.jdbc.SolidDriver
</jdbc-driver-class>
<res-ref-username>
bob
</res-ref-username>
<res-ref-password>
secret
</res-ref-password>
</jdbc-res-conf>
</resource-ref>
</app-client>

There are two ways to specify the resolution of a JDBC driver:

JDBC 1.0-style uses a driver class and a JDBC URL. This is the style used by all preJDBC 2.0 drivers and many JDBC 2.0 drivers that depend on the DriverManager to
create JDBC connections.

JDBC 2.0-style, on the other hand, uses a vendor-specific JNDI name to gain access to
the driver. Not all JDBC 2.0 drivers automatically use this style - in fact, many still use
the DriverManager approach, or offer both styles. The JDBC drivers documentation
should indicate which style of access should be used.

resource-name
If JDBC 1.0-style driver access is being used, then this is the JDBC URL string that is used to gain access to
the driver. This string varies from database to database and driver to driver. If JDBC 2.0-style driver access
is being used, this field should contain the JNDI name used to gain access to the driver.

jdbc-lookup
If JDBC 1.0-style driver access is being used, then the value of this field should be DriverManager. If JDBC
2.0-style driver access is being used, then the value of this field should be JNDI.

jdbc-driver-class
This field is only specified if JDBC 1.0-style driver access is being used. If so, then the full class name of the
driver should be specified.

res-ref-username
If the application clients deployment descriptor specifies a res-auth of Container, then this field must
be filled in with the username to be used when connecting to the database. If res-auth is not
Container, then this field should not be supplied, since the client is expected to supply the username
and password in code.

112
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

res-ref-password
If the application clients deployment descriptor specifies a res-auth of Container, then this field must
be filled in with the password to be used when connecting to the database. If res-auth is not
Container, then this field should not be supplied, since the client is expected to supply the username
and password in code.

Resolving JavaMail Resource References


An application client can gain access to JavaMail Sessions directly to send and receive e-mail. The
application client must declare these resource references in the dynamoJ2EESpecifier.xml file.
One approach is to set the resource reference to a resource link and then use mail-service to configure
it directly in dynamoJ2EESpecifier.xml. (See Mapping Resource References in the Dynamo and J2EE
chapter.) Another approach is shown in the following example:

<app-client>
<module-uri>
appclient
</module-uri>
...
<resource-ref>
<res-ref-name>
mail/mailer1
</res-ref-name>
<mail-transport-protocol>
smtp
</mail-transport-protocol>
<mail-store-protocol>
pop
</mail-store-protocol>
<mail-host>
mail.mycompany.com
</mail-host>
</resource-ref>
</app-client>

The mail-transport-protocol field is optional, and presently can only be set to smtp. The mailstore-protocol field is also optional and presently can only be set to pop. The mail-host field
contains the address of the mail server to be contacted by the session.

113
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

Running Application Clients


Once an application has been deployed successfully with its dynamoJ2EESpecifier.xml file, the
application can be run using the <DAS6dir>/home/bin/runAppClient script. This script must be run
from a full Dynamo distribution, and the deployed DAR file must be available to the machine running the
application client. The script uses the following syntax:
bin/runAppClient dar-file [options] [other arguments]

The following table describes the arguments:

Argument

Description

dar-file

The name of the deployed DAR file.

options

Command-line flags that modify the behavior of the command. These


include:
-module-name app-client-display-name
-continue-after-main (allows JVM to continue running after application

clients main method returns)


-no-gui-login (always use a command-line login prompt)
-provider-url rmi-url (for standard RMI only, not IIOP)
-orb-host host-name (for IIOP)
-orb-port port-number (for IIOP)
other arguments

Additional arguments to pass to the main class of the application client


module being invoked.

For example, the command to run the default application client in the simpleJ2EE application using IIOP:
bin/runAppClient ../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE.dar
-module-name default orb-host localhost orb-port 8820

Application Clients and EJB Clustering


To run an application client module with Dynamos EJB clustering system, you run the runAppClient
script as described above. However, in this case you use the cluster-managers flag to specify a list of
the URLs of the cluster managers the application client will use. In addition, there are optional flags for
specifying timeout limits for connections. The following table summarizes these flags:

114
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

Option

Description

-cluster-managers

Comma-separated list of the SOAP service URLs of the


cluster managers the application client will use. The first
item in the list is the primary cluster manager. For
example:

cluster-managers
http://localhost:8830/ejbClusterManagement
-connect-timeout

Time in milliseconds to wait for a connection to a server.


For example:
connect-timeout 50000

If you omit this flag, the value defaults to 30000.


-read-timeout

Time in milliseconds to wait for a read to complete. For


example:
read-timeout 25000

If you omit this flag, the value defaults to 15000.

The ClusterEJB demo that accompanies Dynamo comes with a J2EE application client module that
communicates with each of the beans in the cluster.
To run the application client module, use the runAppClient script from the <DAS6dir>/home directory:
bin/runAppClient ../J2EE-Examples/ClusterEJB/
j2ee-apps/clusterEJB.dar module-name default cluster-managers
http://cluster-manager-host:8830/ejbClusterManagement
-connect-timeout 50000 -read-timeout 25000

Stopping Application Clients


Application clients that use the Dynamo EJB clustering system run a thread that collects information from
the Cluster Manager. An application cannot stop until you have stopped explicitly that thread. To stop the
collection of cluster information, call the following method:
atg.jndi.url.clusterejb.ClusterEJBContext.stopClusterClient();

The next time you try to look up a bean in the cluster, the collector thread will be restarted.

Running an Application Client Remotely


You can use the runAppClientContainer script to run an application client module on a machine that
does not include a complete Dynamo installation. This script supports the same command line arguments
as runAppClient. The supporting JAR file, atg-appclient-container.jar, provides the basic classes
needed to set up an instance of a J2EE application client module. You may need to augment this files

115
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

contents depending on your applications needs. These files are in the <DAS6dir>/J2EE-AppClients
directory.

Lightweight Application Clients


A lightweight application client is one that is not deployed within a J2EE application client module. In this
case, you must set CLASSPATH to include the classes for the standalone application client, the EJB client
JAR, and the classes.jar file from the <DAS6dir>/J2EEServer/lib directory.
If the classes.jar file is too big for your application client, you can use one of the lightweight JAR files
in the <DAS6dir>/J2EE-AppClients/lib directory. Use atg-clusterclient.jar if your application
client requires cluster support. Otherwise, you can use atg-client.jar. These JAR files contain the
smallest set of classes and resource files required to run an application client. You may need to augment
their contents depending on your applications needs.
A sample lightweight client for the SimpleJ2EE example is at <DAS6dir>/J2EEExamples/SimpleJ2EE/j2ee-apps/SimpleJ2EETestClient.java:

import java.rmi.*;
import javax.naming.*;
import javax.rmi.*;
import javax.ejb.*;
import atg.simpleJ2EE.*;
public class SimpleJ2EETestClient
{
public static void main (String [] pArgs)
throws NamingException,
RemoteException,
CreateException,
RemoveException
{
// Find the AddNumbersHome
InitialContext ctx = new InitialContext ();
AddNumbersHome addNumbersHome =
(AddNumbersHome)
PortableRemoteObject.narrow
(ctx.lookup ("simpleJ2EE/ejbs/AddNumbers"),
AddNumbersHome.class);
// Get an AddNumbers instance
AddNumbers addNumbers = addNumbersHome.create ();
// Determine the result
int result = addNumbers.addNumbers (18, 95);

116
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

// Remove the EJB now that we're done with it


addNumbers.remove ();
System.out.println ("18 + 95 = " + result);
}
}

Dont place standalone clients in the J2EE application module or create them without a package. For
simplicitys sake, this source code appears in the module and has no package. We recommend, however,
that you place application clients in whatever package and source control structure the developer uses.
The code here is similar to any other code that gains access to an EJB. The biggest difference is the JNDI
name used for the EJB. Because standalone clients do not belong to the same J2EE application as the EJB,
they cannot use the java:comp/env namespace. Instead, they must use this convention to name the EJB:
{app name}/{module URI}/{ejb name}

The name of the application is specified in the applications dynamoJ2EESpecifier.xml file under the
application-name tag. In this case, the name of the application is simpleJ2EE.
The name of the EJB is specified in the EJBs ejb-jar.xml file, under the tag ejb-name. In this case, the
name of the EJB is AddNumbers, so the full JNDI name remote clients should use is
simpleJ2EE/ejbs/AddNumbers.
Note that for an EJB in an EJB 1.1 module, the JNDI name omits the module URI. In this case, the JNDI
name would be simpleJ2EE/AddNumbers.
You can override this naming convention by specifying an external-uri element in the
dynamoJ2EESpecifier.xml file for the EJB. For example:

<session>
<ejb-name>
AddNumbers
</ejb-name>
<external-uri>
adder
</external-uri>
</session>

This external-uri then becomes the JNDI name that you should specify:

AddNumbersHome addNumbersHome =
(AddNumbersHome)
PortableRemoteObject.narrow
(ctx.lookup ("adder"),
AddNumbersHome.class);

117
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

Use this feature with care, since Dynamo does not enforce uniqueness of these names. In other words, it is
possible for two EJBs to have the same external-uri name, which would cause one of the EJBs to hide
the other.
The code does not specify the hostname and port of the remote server, but you can supply this
information in a number of ways.
Once you have written the code, you then compile the class. Compilation requires access to two
additional libraries. The class requires the standard J2EE library to supply classes such as javax.ejb.*,
javax.naming.*, and javax.rmi.*. The easiest way to find this library is to use the
<DAS6dir>/J2EEAPI/lib/classes.jar file, which contains the J2EE classes. You can also use any
compliant J2EE distribution library.
The second required library is the set of interfaces representing the EJB, such as AddNumbersHome and
AddNumbers. This library is called the EJB client JAR, and is formed by using Darina to extract the
appropriate classes from the SimpleJ2EE application. To do this, change to the <DAS6dir>/home
directory, then run Darina:
bin/runDarina ../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE
-build -output-client-jar
../J2EE-Examples/SimpleJ2EE/j2ee-apps/simpleJ2EE-client-jar.jar

In most command line shells, you must enter the entire command on a single line. The command is
broken up here for clarity.
This example and others in this section use the UNIX forward slash (/) and colon (:) separator characters;
use the backslash (\) or semicolon (;) instead on Windows.
This is no different from running Darina normally, except that Darina will generate a second file,
simpleJ2EE-client-jar.jar, at the specified directory. This file contains all of the additional classes
needed to compile and run the client program (with the exception of the standard J2EE classes). This
includes the AddNumbersHome and AddNumbers classes, as well as a few required Dynamo-specific
classes. If there are multiple EJB modules in the J2EE application, all of the classes from all of those
modules will be collapsed into this single JAR file.
Once both libraries are ready, you can compile the class:
javac -classpath
../J2EEAPI/lib/classes.jar:../J2EE-Examples/SimpleJ2EE/j2ee-apps/
simpleJ2EE-client-jar.jar -d ../J2EE-Examples/SimpleJ2EE/j2ee-apps
../J2EE-Examples/SimpleJ2EE/j2ee-apps/SimpleJ2EETestClient.java

Once you compile the class, you can run it. First, make sure that Dynamo is running and hosting the EJB:
bin/startDynamo -m J2EE-Examples.SimpleJ2EE

Then invoke the client:


java classpath
../J2EEAPI/lib/classes.jar:../J2EE-Examples/SimpleJ2EE/j2ee-apps/

118
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

simpleJ2EE-client-jar.jar:../J2EE-Examples/SimpleJ2EE/j2ee-apps
-Djava.naming.factory.initial="atg.jndi.url.dynamoejb.RemoteEJBContext"
-Djava.naming.provider.url="rmi://localhost:8860/"
SimpleJ2EETestClient

This command should invoke the remote EJB and return the sum of 18 and 95.
The command line specifies a classpath with three elements. The first element is the classes.jar file
containing the standard J2EE classes. The second element is the client JAR file containing the interfaces
specific to Dynamo and the AddNumbers EJB. The third element is the directory containing the
SimpleJ2EETestClient itself.
The next portion of the command line defines a couple of system properties that use -D flags. The first
system property, java.naming.factory.initial, defines the name of the class that you should use to
produce a JNDI InitialContext. Do not change this value. The second system property,
java.naming.provider.url, specifies the server and port hosting the EJB. This allows you to point the
client at different servers without modifying the code.
The SimpleJ2EE application does not have any security declarations, so any EJB client can connect and
invoke methods. If the SimpleJ2EE application did specify security constraints, then the client program
must log in with a username and password. It can do this using the system property
java.naming.security.principal for the username and java.naming.security.credentials for
the password:
java classpath
../J2EEAPI/lib/classes.jar:../J2EE-Examples/SimpleJ2EE/j2ee-apps/
simpleJ2EE-client-jar.jar:../J2EE-Examples/SimpleJ2EE/j2ee-apps
-Djava.naming.factory.initial="atg.jndi.url.dynamoejb.RemoteEJBContext"
-Djava.naming.provider.url="rmi://localhost:8860/"
-Djava.naming.security.principal="admin"
-Djava.naming.security.credentials="adminpass"
SimpleJ2EETestClient

If these are specified, then when the client obtains a home interface, it will attempt to authenticate itself.
If it succeeds, then subsequent calls will be associated with the specified principal.
If you enter the system properties on the command line, then they will apply to the entire application.
This may not always be desirable since other parts of the application may wish to gain access to other
EJBs on other servers, or with different usernames and passwords. If this is the case, then you can set
these properties in the code:

// Create the properties


java.util.Properties env = new java.util.Properties ();
env.setProperty (Context.INITIAL_CONTEXT_FACTORY,
"atg.jndi.url.dynamoejb.RemoteEJBContext");
env.setProperty (Context.PROVIDER_URL, "rmi://localhost:8860/");
env.setProperty (Context.SECURITY_PRINCIPAL, "admin");
env.setProperty (Context.SECURITY_CREDENTIALS, "adminpass");

119
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

// Find the AddNumbersHome


InitialContext ctx = new InitialContext (env);
AddNumbersHome addNumbersHome =
(AddNumbersHome)
PortableRemoteObject.narrow
(ctx.lookup ("simpleJ2EE/ejbs/AddNumbers"),
AddNumbersHome.class);

The difference here is that a Properties structure is created and passed to the InitialContext. You
then can invoke the client without using any -D arguments:
java -classpath
../J2EEAPI/lib/classes.jar:../J2EE-Examples/SimpleJ2EE/j2ee-apps/
simpleJ2EE-client-jar.jar:../J2EE-Examples/SimpleJ2EE/j2ee-apps
SimpleJ2EETestClient

This need not be an all or nothing choice. You can use D to set some properties and use the
Properties structure for others. Any properties you specify using the Properties structure will
override -D properties of the same name.

Lightweight Application Clients and EJB Clustering


If a lightweight application client is accessing clustered EJBs, the configuration properties are similar, but
they are set to values that support clustering. The following table summarizes these properties:

JNDI Environment Property

Description

java.naming.provider.url

Comma-separated array of SOAP URLs of the cluster


managers the application client will use. The first item in
the list is the primary cluster manager. For example:
http://localhost:8830/ejbClusterManagement

java.naming.factory.initial

To use EJB clustering, set this property to:


atg.jndi.url.clusterejb.ClusterEJBContext

java.naming.security.principal

Specify the user name that will be used to gain access to


the EJB servers in the cluster. This property is required
only if the EJB application has security specified on
methods.

java.naming.security.credentials

Specify the password that will be used to gain access to


the EJB servers in the cluster. This is only required if the
EJB application has security specified on methods.

atg.jndi.url.clusterejb.

Specify the user name that will be used to gain access to


the cluster manager. Default is admin.

cluster_security_principal

120
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

atg.jndi.url.clusterejb.
cluster_security_credentials
atg.jndi.url.clusterejb.
cluster_polling_interval
atg.jndi.url.clusterejb.
cluster_client_strategy_class

Specify the password that will be used to gain access to


the cluster manager. Default is admin.
Specify the interval in milliseconds that the application
client will poll the cluster manager. Default is 90000.
Specify the load balancing strategy class that the
application client will use. The default is:
atg.jndi.url.clusterejb.
ThreadClusterClientStrategy

For multi-threaded applications that want to use only


one server until a failure takes place, change this value to:
atg.jndi.url.clusterejb.
SimpleClusterClientStrategy
atg.jndi.url.clusterejb.
logging_info
atg.jndi.url.clusterejb.
logging_warning
atg.jndi.clusterejb.
logging_debug

Set to true if you want the application client to log


information messages.
Set to true if you want the application client to log
warning messages.
Set to true if you want the application client to log
debugging messages.

For example, the ClusterEJB application includes a lightweight application client class,
atg.clusterEJB.StandaloneAppClient. You can run the client using this command:
java -Djava.naming.provider.url=
http://localhost:8830/ejbClusterManagement
-Djava.naming.factory.initial=
atg.jndi.url.clusterejb.ClusterEJBContext
classpath "../J2EE-Examples/ClusterEJB/j2ee-apps/clusterEJB
/clusterAppclient:../J2EE-Examples/ClusterEJB/j2ee-apps
/clusterEJB/ejbclient_clusterEJBs.jar:..
/J2EEAPI/lib/classes.jar:../DAS/lib/resources.jar"
atg.clusterEJB.StandaloneAppClient

Configuring Timeouts for Lightweight Application Clients


To configure the connect and read timeout used by a lightweight application client, include the following
code in the application clients main() method. This code performs the equivalent of the readtimeout and connect-timeout configuration used by the runAppClient scripts.

import atg.jndi.url.clusterejb.ClusterSocketFactory;
..

121
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

public static void main(String[] pArgs) {


int readTimeout = .
long socketTimeout =.
ClusterSocketFactory socketFactory = new ClusterSocketFactory(readTimeout,
socketTimeout);
java.rmi.server.RMISocketFactory.setDefaultSocketFactory(socketFactory);
}

122
7 - Application Clients

ATG 6 J2EE Development and Deployment Guide

8 J2EE Security

The security mechanism in J2EE serves two main functions:

It allows an application to know which user is making a particular request or method


call, so that the application can react appropriately.

It allows Dynamo to deny access to certain pages or method calls unless the calling
user fits one of the roles declared by the application.

Getting these two functions to operate correctly in Dynamo requires the cooperation of several Dynamo
subsystems. The list of users must be kept in some data storage facility, which is accessed through a
repository. For example, the user list might be maintained in a database accessed by a SQL repository. The
repository must then be mapped to Dynamos security API through the use of a UserAuthority
implementation. Finally, the UserAuthority API must be mapped to a specified J2EE application
through declarations in the J2EE applications dynamoJ2EESpecifier.xml file.

Dynamo J2EE Security Architecture


Dynamo supports the full J2EE security model. However, the J2EE security model does not completely
specify the security architecture that the server must use. More specifically, the J2EE security model does
not say how principal (user) names and security roles should be stored by the server, or how the server
should map users and roles to the names referenced in a J2EE application. Thus, each server may choose
its own scheme to map and manage user accounts.
In Dynamo, users and roles are accessed through a repository. This repository might be a separate
repository dedicated to holding security information, or it might be the same repository that the
application is already using to represent users. By default, Dynamo uses an SQL repository for user
information, but you can use an LDAP repository instead.
A UserAuthority component is used to translate the security requests from the J2EE system to the
proper data access requests on the repository. For example, the J2EE system will ask the UserAuthority
if user X can login using password Y. The UserAuthority in turn will ask the repository to find the user
with login property X, and checks to see if that users password property matches Y. A UserAuthority
must be configured to point to a repository, and must also be configured with the names of the item
descriptors and properties that will provide the necessary information.
Each J2EE application should be configured to point to a UserAuthority component in Dynamo. This is
done with the user-manager tag in the dynamoJ2EESpecifier.xml file. Whenever a J2EE application
needs security information, it will ask its associated UserAuthority, which will in turn ask its associated
repository:

123
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

J2EE Application

UserAuthority

Repository

SQL
LDAP

Where the security system is involved, the entire chain of data operates in a read-only mode. Data is
stored in the repository, which is queried by the UserAuthority, which is queried by the J2EE
application. However, reading security data is only half the story. An application must also be able to
manage the user database - create and remove users, add roles to users, remove roles from users, etc.
Managing the user database is a much more complex problem than simple authentication and access
control. Applications have widely varying needs in their storage and management of users, and there is
no generic solution that meets all needs. For example, one application might be used by only a few
people with a very simple management tool, while another application might serve thousands of internet
users, giving them the ability to manage their own application. It turns out that most developers would
much rather write the interfaces and code to manage an application-specific user database than rely on a
single management tool.
For this reason, Dynamos security system does not include a generic user management tool (although
there is one available for managing administrative users, described later). Instead, Dynamo strives to
make it easy for applications to write their own user management code.
There are several approaches an application can take to manage the user database. The first is to
manipulate the underlying data source directly:

J2EE Application

User Authority

Repository

SQL

In this case, the J2EE application might issue SQL commands directly to the database to perform any user
account manipulation. These changes would then be picked up by the repository and user authority,
which will act on those changes when new login or role requests arrive.
This approach is usually discouraged since it can get the application mired deep in SQL code - something
most developers want to avoid. In addition, changes made to the SQL database will not be picked up by
the repositorys caches, so the repository will have to run in a cacheless mode, thereby hurting
performance.
A second approach involves having the J2EE application communicate directly with the underlying
repository, issuing Repository API commands to manipulate the user database:

124
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

J2EE Application

User Authority

Repository

SQL

This approach has several advantages - it allows the component to use an abstract API to manipulate the
data, so that it doesnt have to be rewritten if the underlying data source changes. It also cooperates with
the repositorys caches, thereby improving performance.
The disadvantage to this approach is that it requires the J2EE application to call non-standard APIs (the
repository API is not a part of J2EE). This makes it more difficult to port the application to another
application server.
The final approach takes advantage of Dynamos entity EJB architecture. Dynamo implements containermanaged persistence for entity beans by storing EJB instances in a repository. Each EJB maps to an item
descriptor, and each instance field maps to a property of that item descriptor.
Using this approach, a J2EE application can manipulate the user database through entity EJBs. Then, by
configuring the EJBs to point at the same repository as the user authority does, these entity EJBs can
directly affect the security mechanism used by Dynamos J2EE infrastructure:

J2EE Application

User Authority

Entity EJB

Repository

SQL

CMP

The advantage to this approach is that it uses entity EJBs to manage users, so the application does not
need to call any nonstandard APIs. However, this approach may still make porting the application difficult,
because other application servers may use separate data stores for security and CMP.

Configuring Dynamo Security for J2EE


The most complex part of the Dynamo security architecture is getting everything configured correctly.
The application must point to a UserAuthority, which must point to a repository, which must point to a
DataSource, which must point to an SQL database. Each junction requires some additional
configuration. The UserAuthority must be configured to know which views and properties to use in the
repository. The repository must be configured with a mapping from the schema in the database to views
and properties in the repository. Finally, the DataSource component must be configured to point to the
correct database.
The UserAuthority can be configured either as a global resource or an application resource. To
configure the UserAuthority as a global resource, point it to a component in Nucleus that implements
the UserAuthority interface. For example:

125
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

<user-manager>

dynamo:/atg/dynamo/service/j2ee/J2EEUserAuthority
</user-manager>

The component /atg/dynamo/service/J2EEUserAuthority is the default UserAuthority for J2EE


applications. If you do not specify a UserAuthority in the dynamoJ2EESpecifier.xml file, the
application will use J2EEUserAuthority, which is actually a proxy that points to
/atg/dynamo/security/UserAuthority.
By default, /atg/dynamo/security/UserAuthority points to the repository
/atg/userprofiling/ProfileAdapterRepository if your installation includes Dynamo
Personalization Server, or to /atg/dynamo/security/AdminSqlRepository otherwise.
Alternatively, you can define a UserAuthority as an application resource like this:

<user-manager-link>myUserAuthority</user-manager-link>
...
<user-authority-service>
<resource-service-name>myUserAuthority</resource-service-name>
<gsa-service-link>myGSA</gsa-service-link>
<user-view>applicationUser</user-view>
<user-view-login-property>login</user-view-login-property>
<user-view-password-property>password</user-view-password-property>
<user-view-roles-property>groups</user-view-roles-property>
<role-view-role-name-property>name</role-view-role-name-property>
<password-hasher-name>
/atg/dynamo/security/DigestPasswordHasher
</password-hasher-name>
</user-authority-service>

The user-authority-service entry in a dynamoJ2EESpecifier.xml file tells the J2EE Container to


create a UserAuthority of class RepositoryApplicationUserAuthority. The various child tags of
the user-authority-service set the properties of the component that define how the
RepositoryApplicationUserAuthority will map items from the underlying SQLRepository to
actual J2EE principals and roles:

userView - the name of the item descriptor representing a user. This property is

required.

userViewLoginProperty - the name of the String property in the users item

descriptor that holds the users login name. This property is required.

userViewPasswordProperty - the name of the String property in the users item

descriptor that holds the users password. This property is not strictly required - if it
isnt specified, then users wont require a password in order to log in. However, it is
strongly recommended that sites require passwords.

userViewRolesProperty - the name of the property in the users item descriptor

that holds the users roles. The value of the property may be an array or collection of

126
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

Strings, representing the role names. The property might also be an array or collection
of repository items, where each item represents a role, and one property of that item
contains the roles name.
This property is optional. If it is omitted, then users will still be able to log in, but users
will appear to have no roles.

roleViewRoleNameProperty - as mentioned above, roles might be represented as a

set of Strings, or as a set of repository items. If the latter, then this property will define
which property in the repository item represents the role name.

passwordHasher - the name of a Nucleus component that will hash passwords before

storing them in the repository. This prevents passwords from being stored in plain text
in the database, so that unauthorized access to the database will not result in access to
every users password. If plain text passwords are desired, this should be set to
NullPasswordHasher. If hashing through some digest algorithm (e.g., MD5) is
desired, this should be set to DigestPasswordHasher. This is described in the
Hashing Passwords section.
A UserAuthority defined as an application resource needs a reference to a SQLRepository. This
repository, too, can be defined as either a global resource or an application resource. To define a global
resource, use the pre-configured SQLRepository component in Nucleus:

<user-authority-service>
...
<gsa-service-link>myGSA</gsa-service-link>
...
</user-authority-service>
...
<gsa-service-instance>
<resource-service-name>myGSA</resource-service-name>
<resource-name>
dynamo:/atg/dynamo/service/jdbc/SQLRepository
</resource-name>
</gsa-service-instance>

Or create a SQLRepository as an application resource:

<user-authority-service>
...
<gsa-service-link>myGSA</gsa-service-link>
...
</user-authority-service>
...
<gsa-service-instance>
<resource-service-name>myGSA</resource-service-name>
<repository-name>my.repository</repository-name>
<definition-file>sqlRepository.xml</definition-file>

127
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

<jdbc-resource-link>myJDBCDataSource</jdbc-resource-link>
</gsa-service-instance>

The details of configuration are described in the ATG 6 Repository Guide; however, an example will be
discussed later in the SQL Repository Configuration Example topic of this chapter.
The SQLRepository application resource definition also has a reference to a JDBC resource. Once again,
this JDBC resource can be defined as either a global resource or an application resource. To define a
global resource, use the pre-configured JTDataSource component in Nucleus:

<jdbc-service>
...
<resource-service-name>myJDBCDataSource</resource-name>
<resource-name>
dynamo:/atg/dynamo/service/jdbc/JTDataSource
</resource-name>
...
</jdbc-service>

Or create a JDBC data source as an application resource:

<gsa-service-instance>
...
<jdbc-resource-link>myJDBCDataSource</jdbc-resource-link>
...
</gsa-service-instance>
...
<jdbc-service>
<resource-service-name>myJDBCDataSource</resource-service-name>
<jdbc-lookup>DriverManager</jdbc-lookup>
<jdbc-url>jdbc:solid://localhost:1313</jdbc-url>
<jdbc-driver-class>solid.jdbc.SolidDriver</jdbc-driver-class>
<min-pool-size>10</min-pool-size>
<max-pool-size>10</max-pool-size>
<max-pool-free>10</max-pool-free>
<resource-username>admin</resource-username>
<resource-password>admin</resource-password>
</jdbc-service>

In either case, the SQLRepository service will use a DataSource that pools and monitors connections
from another DataSource. The JTDataSource Nucleus component has properties like
loggingSQLWarning, loggingSQLInfo, and loggingSQLDebug which if set to true, will display
communication between Dynamo and the database.
By default, the JTDataSource is configured to point to
/atg/dynamo/service/jdbc/FakeXADataSource. This is a DataSource that uses a JDBC 1.1 driver to
point at a database. By default, the FakeXADataSource points at the Solid database that comes with

128
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

Dynamo for evaluation purposes. The DataSource can be changed by setting the driver, URL, user, and
password properties.
Note that this setup illustrates just one possibility for configuring the security system. This setup can be
changed to point to another type of repository, such as an LDAP data source. Or different applications
might be configured to point at different sets of users (often called domains in security parlance).
Setting up these alternate configurations requires a little more work, since new components must be
configured, but all of the previously-discussed principles remain the same.

Single Login
The J2EE specification states that once a user has been authenticated to one application, that users
identity is made known to all applications in the same container. For example, if Dynamo is running three
applications, and user bob logs in to one of those applications, then that application will associate the
principal bob with all requests from that user. But if the user moves to another application on the same
Dynamo, that Dynamo will also recognize the user as bob. This means that the user does not have to log
in separately to each application running on the Dynamo. Logging in to one application is as good as
logging into all applications.
However, this works only if all of those applications are using the same UserAuthority. If one of the
applications is using a different UserAuthority, then the user must log in separately to that application.
However, the user still remains logged in to the other applications.
So a user may log in to several applications at once, and if the user logs into an application driven by one
UserAuthority, then the user is automatically logged into any other applications that use the same
UserAuthority.

Logging Out
Most secure applications require the ability to let the user log out, which has the effect of dissociating any
security identity from the users session. This prevents someone else from using the users terminal and
gaining access to the users privileged information.
J2EE does not really have a logout mechanism that mirrors its login mechanisms. The best way to log a
user out programmatically is to invalidate the users session. This can be done by calling
HttpServletRequest.getSession().invalidate(). This has the effect of logging the user out of all
Web applications on that server, not just the application the user is currently accessing.
Note that this works best for form-based logins. If the user is logged in through information that is kept
on the browser, such as HTTP basic authentication information, then invalidating the server-side session
will not necessarily prevent the browser from automatically logging the user in again on the next request.

J2EE Security Example


This section describes the sample security application that comes with DAS, illustrating many of the
principles outlined above. The application uses declarative security to protect certain pages, drawing its
user and role information from an SQL database, through the SQL repository, translated by the

129
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

ApplicationUserAuthority. In addition, the application uses entity EJBs to add new users and roles to

the database. Note that because the same repository is used for user information and for EJB CMP, the
example must use an SQL repository and not an LDAP or other repository implementation.
This section does not explain the entire application in complete detail. Developers can glean the major
concepts from the explanation in this section, but should go through the example code themselves to get
the full detailed picture.
This example is meant to serve as a template for other applications that perform similar functions.
However, the Web interface is built in a quick-and-dirty fashion using servlets and tags that generate
HTML, and should not be considered exemplary. Developers should not use these interface techniques as
a model for good programming.

Deploying the J2EE Security Example


The J2EE Security example is located in the <DAS6dir> directory under J2EE-Examples/Security.
Before the application can be run, it must be deployed using Darina. To do this, change to the
<DAS6dir>/home directory, then run Darina like this (using forward or backwards slashes as appropriate):
bin/runDarina ../J2EE-Examples/Security/j2ee-apps/security -build

Darina will compile all of the applications source files, produce ejb-client-jar files, and create the
various RMI classes. When its finished, Darina will have produced a deployed file at ../J2EEExamples/Security/j2ee-apps/security.dar.
Once the application has been deployed, you can start it using the -m flag:
bin/startDynamo -m J2EE-Examples.Security

This command starts up Dynamo and the Security demonstration.


It is assumed that the demo will be running on Solid, the evaluation database included with Dynamo. This
database comes pre-initialized with the schema needed to run the demo. In the case where a different
database is being used or for some reason the schema does not yet exist, the schema can be created
using these SQL statements:

CREATE TABLE SECURITY_USER (


ID INTEGER PRIMARY KEY,
LOGIN_NAME VARCHAR (128),
PASSWORD VARCHAR (128)
)
CREATE TABLE SECURITY_ROLE (
ID INTEGER PRIMARY KEY,
ROLE_NAME VARCHAR (128),
DESCRIPTION VARCHAR (128)
)

130
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

CREATE TABLE SECURITY_USER_ROLE (


USER_ID INTEGER,
ROLE_ID INTEGER
)

Running the J2EE Security Example


Once the security example has been deployed and Dynamo has been started to run the example, the
example can be accessed at the URL http://{hostname}:8840/security/. This will bring up the main
page, which has three options - initialize the database, go to the administration page, or view content.
This main page has no security restrictions on it, so anyone can access it. The administration page can
only be accessed by users with the admin role, and the content page can only be accessed by users with
the subscriber role.
Initializing the database also has no security restrictions on it. Click on this link first. This will actually send
the request to a servlet which accesses JDBC directly - it clears out all three of the tables mentioned
above, creates the security roles admin and subscriber, creates a user named admin (with password
admin), and associates the admin user with the admin security role. The tables in the database end up
looking like this:

SECURITY_USER Table
ID

LOGIN_NAME

PASSWORD

admin

admin

SECURITY_ROLE Table
ID

ROLE_NAME

DESCRIPTION

admin

Administrator who can create new users/roles

subscriber

Can view content

SECURITY_USER_ROLE Table
USER_ID

ROLE_ID

Go back to the main page, then attempt to View content as a paid subscriber. A login form page should
appear, asking for a login name and password. Enter admin for the login name and admin for the
password, since that is the only account known to the system.

131
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

Unfortunately, the content page can only be viewed by a user with the subscriber role, which the
admin user does not have. So an error page will appear, refusing access to the page.
To get to the content page, a new user must be created with the subscriber role. To do this, go back to the
main page, then go to the Administration Page.
Notice that no login page is required to get to the administration page, even though that page is only
accessible to users with the admin role. Even though the previous login attempt failed to get into the
subscriber page, the system still remembers that the current user successfully logged in as admin, and so
has access to any pages requiring the admin role.
The administration page shows the users and roles currently in the system. Each user displays the roles
associated with that user, and each role displays the users associated with that role. Notice that users and
roles use an integer ID as their primary keys, rather than the login name or role name. In theory, because
login names and role names must be unique, they could also serve as primary keys. However, it is often a
good idea to use a separate field to represent a user or role ID to avoid complications if a login name or
role name has to change in the future.
Underneath the list of users and roles are two forms - one is used to create a new user, and the other is
used to create a new role. To create a new user, choose a unique ID number, a unique login name, and a
password. For example, 2, joe, and D6rules. The form also presents a set of checkboxes representing the
various roles that have been created in the system. If more roles are created using the Add New Role
form, those roles will appear in this list of checkboxes. The new user will be associated with any roles that
are checked. For the new joe user, check off both admin and subscriber, then click on Create New
User.
After creating the new user, return to the main page and attempt again to View content as a paid
subscriber. The login form will once again pop up. The system hasnt forgotten that the current user is
admin. However, since admin doesnt have access to the page, the system is giving a chance to login in as
a different user. So login as joe, with password D6rules. The system will now treat the current user as
joe, who does have the subscriber role, and can access the content page.

The J2EE Security Example Explained


The security example demonstrates the major elements of an application security system - authentication
(form logins), access control (declarative security on pages and servlets), and user management (creating
new users and roles). Making all of this work requires precise configuration, so developers should
concentrate on learning the configuration aspects of this demonstration, rather than the details of the
Web interface or EJB code.
The following is an explanation of the various components in the application:

UserAccount - This entity EJB uses container-managed persistence to represent a

single user in the SECURITY_USER table. It has fields representing the ID,
LOGIN_NAME, and PASSWORD columns. It defines a finder method that finds a User
by primary key (ID, not LOGIN_NAME), and a finder method that finds all Users.
The UserAccountEJB also has a container-managed field of type Role[], which
represents the set of roles with which a user is associated. This association is kept in
the SECURITY_USER_ROLE table, which maintains the many-to-many mappings

132
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

between users and roles. This means that the data in a single UserAccount instance
might come from two tables - one row in the SECURITY_USER table, and possibly
many rows in the SECURITY_USER_ROLE table. Dynamos EJB facilities allow this sort of
configuration.

Role - Similar to the UserAccount EJB, this EJB represents a role from the

SECURITY_ROLE table, along with any associated UserAccounts as read from the
SECURITY_USER_ROLE table.

InitializeDatabaseServlet - This servlet initializes the tables to contain just the

admin user. It uses JDBC directly, wired through the Dynamo J2EE Specifier to get
connections from the JTDataSource and remove all rows from the SECURITY_...
tables. It then uses the above entity EJBs to create the admin and security roles, and
the admin user.

AddNewUserServlet - This servlet reads the form inputs from the Add New User form

on the administration page, and creates a new UserAccount EJB. This also associates
the new user with any Roles that have been entered through the checkboxes.

AddNewRoleServlet - This servlet reads the form inputs from the Add New Role form

on the administration page, and creates a new Role EJB.

index.jsp/admin.jsp/content.jsp - These JSPs make up the application interface.

login.jsp/loginFailed.jsp - These JSPs handle login and login failures.

The JSPs use the ATG Core tag library, plus an additional tag library containing the following special tags.
Note that these tag implementations are not meant to be taken as a good Web programming technique
(they generates HTML directly and violate several other good JSP guidelines), but are provided in this
quick and dirty format to simplify the example:

DisplayUsersTag - Displays the table of users and associated roles on the

administration page.

DisplayRolesTag - Displays the table of roles and associated users on the

administration page.

DisplayRolesCheckboxesTag - Displays the list of checkboxes in the add new user

form.

The web.xml File


The security portion of the application is configured in the web.xml file. First, URL spaces are declared to
be accessible to only certain roles. For example, the admin.jsp page and the AddNewRole and
AddNewUser servlets are declared to be accessible only by a user with the Administrator role:

<security-constraint>
<web-resource-collection>
<web-resource-name>
adminPages
</web-resource-name>
<url-pattern>
/admin.jsp
</url-pattern>

133
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

<url-pattern>
/AddNewRole
</url-pattern>
<url-pattern>
/AddNewUser
</url-pattern>

</web-resource-collection>
<auth-constraint>
<role-name>
Administrator
</role-name>
</auth-constraint>
</security-constraint>
...
<security-role>
<role-name>
Administrator
</role-name>
</security-role>

Note that protected pages can be specified individually (/index.jsp), or as a URL pattern (/content/*).
Developers should be careful when protecting a large area to make sure that guest users or other
necessary users are not somehow locked out of a common area.
The web.xml file also declares how users will log in. In this case, login is performed through a form:

<login-config>
<auth-method>
FORM
</auth-method>
<form-login-config>
<form-login-page>
/security/login.jsp
</form-login-page>
<form-error-page>
/security/loginFailed.jsp
</form-error-page>
</form-login-config>
</login-config>

The dynamoJ2EESpecifier.xml File


In addition to the standard configuration described above, the application must be mapped to Dynamo
facilities in the dynamoJ2EESpecifier.xml file. For example, the mappings for resource references:

<resource-ref>
<res-ref-name>

134
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

jdbc/db
</res-ref-name>
<resource-link>
securityDataSource
</resource-link>
</resource-ref>
...
<jdbc-service>
<resource-service-name>
securityDataSource
</resource-service-name>
<jdbc-lookup>
DriverManager
</jdbc-lookup>
<jdbc-url>
jdbc:solid://localhost:1313
</jdbc-url>
<jdbc-driver-class>
solid.jdbc.SolidDriver
</jdbc-driver-class>
<min-pool-size>
10
</min-pool-size>
<max-pool-size>
10
</max-pool-size>
<max-pool-free>
10
</max-pool-free>
<resource-username>
admin
</resource-username>
<resource-password>
admin
</resource-password>
</jdbc-service>

The Dynamo J2EE Specifier also maps the role names used in the application (Administrator and
ContentSubscriber), to the role names stored in the database (admin and subscriber):

<security-role>
<role-name>
Administrator
</role-name>
<security-group>
admin
</security-group>
</security-role>

135
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

<security-role>
<role-name>
ContentSubscriber
</role-name>
<security-group>
subscriber
</security-group>
</security-role>

Next, the application must be told which UserAuthority it will use. This configuration indicates which
item descriptors and properties contain the information required to handle login and role membership
requirements. Users are declared to be stored in the userAccount item descriptor, with properties
loginName, password, and roles. The roles property is expected to point to a collection of repository
items, each of which contains a property called roleName:

<user-manager-link>
securityUserAuth
</user-manager-link>
...
<user-authority-service>
<resource-service-name>securityUserAuth</resource-service-name>
<gsa-service-link>securityRepository</gsa-service-link>
<user-view>userAccount</user-view>
<user-view-login-property>loginName</user-view-login-property>
<user-view-password-property>password</user-view-password-property>
<user-view-roles-property>roles</user-view-roles-property>
<role-view-role-name-property>roleName</role-view-role-name-property>
</user-authority-service>

Finally, the EJB configuration specifies that the EJBs use the securityRepository for CMP, and maps
each EJB to an Item descriptor (repository view), each field to a repository property, and each finder
method to an RQL or EJB-QL query. For example:

<entity>
<ejb-name>
UserAccount
</ejb-name>
<cmp-mapping>
<repository-link>
securityRepository
</repository-link>
<repository-view-name>
userAccount
</repository-view-name>

136
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

<read-only>
False
</read-only>
<field-mapping>
<field-name>
mId
</field-name>
<property-name>
id
</property-name>
</field-mapping>
...
</cmp-mapping>
<finder-method>
<method-name>
findByPrimaryKey
</method-name>
<finder-query>
<![CDATA[ id = ?0 ]]>
</finder-query>
</finder-method>
...
</entity>

For more information about configuring CMP, see the Container-Managed Persistence section of the
Enterprise JavaBeans chapter.

SQL Repository Configuration Example


The final component that needs to be configured is the SQL repository itself. This repository is used in two
places: in the UserAuthority just described, and in the EJB container-managed persistence system,
which declares which maps EJBs and fields to views and properties in that same repository.
Most of the time, the SQL repository is configured in the sqlRepository.xml file. This configuration can
get somewhat complicated, and is discussed more fully in the Enterprise JavaBeans chapter. However, the
basic idea is that the item descriptors and properties are defined in this file, and are mapped to tables and
columns. For example:

<item-descriptor name="userAccount">
<table name="SECURITY_USER"
type="primary"
id-column-name="ID">
<property name="id"
column-name="ID"
data-type="int"/>
<property name="loginName"

137
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

column-name="LOGIN_NAME"
data-type="string"/>
<property name="password"
column-name="PASSWORD"
data-type="string"/>
</table>
...

Recall that the UserAccount EJB requires another property called roles, which points to the Roles
associated with a user. In the repository, this is expressed as a multi property whose type is another item
descriptor, and is configured like this:

<table name="SECURITY_USER_ROLE"
type="multi"
id-column-name="USER_ID">
<property name="roles"
column-name="ROLE_ID"
component-item-type="role"
data-type="set"/>
</table>

It should be clear now that configuring an application to work with the Dynamo security system is not a
trivial process. It is also not a forgiving process - if something is configured wrong, its very possible that
the application will simply not allow logins, and will not say why. Deployers should be very careful when
configuring the security system, consulting the above example to make sure that all of the proper links
are made in all the required files.

Hashing Passwords
In the above example, passwords are stored in plain text in the database. While this works fine, it does
represent a security risk since someone who somehow gains unauthorized access to the database can
retrieve the passwords of every user in the system.
One solution to this problem is to hash passwords before putting them into the database. Hashing is a
way to perform a one-way transformation on a password, turning the password into another String,
called the hashed password. One-way means that it is practically impossible to go the other way - to
turn the hashed password back into the original password. There are several mathematically complex
hashing algorithms that fulfill these needs - MD5 is one of those algorithms, and is the one that is used
by default in Dynamo.
So by hashing passwords before they go into the database, the passwords are protected even if the
database is compromised. The passwords are stored in a form that does not allow the actual password to
be retrieved. When a user enters a password while attempting to log in, the password is run through the
same hashing function before being compared against the hashed password in the database. This allows

138
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

the system to check an entered password against the hashed version in the database, even though the
actual password cannot be retrieved from the database.
Dynamos architecture allows password hashing to be enabled with a few minor configuration changes,
and with no changes to code. An example of password hashing can be found in the module
HashedSecurity, which is identical to the Security module except that hashing is enabled. The
hashing can be demonstrated by deploying the HashedSecurity module, then running Dynamo with -m
J2EE-Examples.HashedSecurity.
To use password hashing, set the passwordHasher property of the user authority to point to a password
hashing component. If the UserAuthority is defined as a global resource, you set this property in the
properties file of the UserAuthority component. If the user authority is defined as an application
resource, you set the property as part of creating the resource definition for the UserAuthority in the
dynamoJ2EESpecifier.xml file. For example:

<user-authority-service>
...
<password-hasher-name>
/atg/dynamo/security/DigestPasswordHasher
</password-hasher-name>
...
</user-authority-service>

The DigestPasswordHasher will hash passwords using the MD5 algorithm, followed by converting the
digest to a hexadecimal form. The details of this can be configured in the DigestPasswordHasher. See
the ATG 6 Personalization Programming Guide for more information about password hashing.
The SQL repository allows an application to specify properties that are filters for other properties. These
filtering properties are not connected with a database column. They are instead connected with an
underlying property, which itself may be connected with a database column. When an application writes
a value to a filtering property, the property is transformed by a Java object, then submitted to the
underlying property. The reverse happens when the application reads a value - the value is read from the
database into the underlying property, then transformed through the Java object and appears in its
transformed state to the application.

abc
Application

cba
filtering property

cba
underlying property

database

In the case of hashed passwords, the filtering Java object will hash a password written to it before sending
it to the underlying property. However, the object performs no transformation when reading the value
from the underlying property (since it is practically impossible to undo the hashing transformation).
So when a password value is written through an entity EJB to the password property, it is hashed by the
Java object. For example, a password of admin will be hashed into
21232f297a57a5a743894a0e4a801fc3. This hashed value is then written to the hashedPassword
property, which in turn is written to the PASSWORD column in the database:

139
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

admin

21232f

Entity EJB

password

21232f
hashedpassword

PASSWORD

On the other hand, when the security system reads the password property, it will actually get back the
hashed version of the password since the property is not transformed on reading:

21232f
Security System

21232f
password

21232f
hashedpassword

PASSWORD

Fortunately, the security system needs to see the hashed version of the password, since the security
system will be comparing that value against a hashed version of whatever password the user entered to
log in.
In the sqlRepsitory.xml file, this is configured by first changing the name of the password property to
hashedPassword. Then a new password property is created, which uses the Java object
PasswordPropertyDescriptor to do its transformations, directing the results to the hashedPassword

property. The final result looks like this:

<item-descriptor name="userAccount">
<table name="SECURITY_USER"
type="primary"
id-column-name="ID">
...
<property name="hashedPassword"
column-name="PASSWORD"
data-type="string"/>
</table>
...
<property name="password"
property-type="atg.repository.PasswordPropertyDescriptor">
<attribute name="hashedProperty"
value="hashedPassword"/>
<attribute name="passwordHasher"
bean="/atg/dynamo/security/DigestPasswordHasher"/>
</property>
</item-descriptor>

One word of caution regarding password hashing - once a decision has been made to hash passwords
using a particular hashing algorithm (or with the default MD5 algorithm), it is very difficult to change that
decision. If hashing is later turned off or a new algorithm chosen, then all of the passwords currently in the
database will suddenly become invalid because they were hashed with the wrong algorithm. Worse yet,
because of the one-way nature of the hashing algorithms, it is impossible to extract the original

140
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

passwords so that they can be re-hashed under the new scheme. So the best advice is to choose whether
to hash or not very early on, and not change that decision.
Finally, the hashing algorithm is not a secret. In fact, it is possible that systems outside of Dynamo may
wish to insert users into the same database used by Dynamo, in which case, those external systems will
need to know how to hash passwords as well. The following is a Java code snipped that illustrates how to
produce hashed passwords the same way that the default system does:

import java.security.*;
...
MessageDigest md = MessageDigest.getInstance (messageDigestAlgorithmName);
byte [] source = new byte [originalPassword.length ()];
originalPassword.getBytes (0, source.length, source, 0);
byte [] digest = md.digest (source);
char [] digestChars = new char [digest.length];
char [] hexChars =
{ '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
for (int i = 0; i < digest.length; i++) {
digestChars [i * 2] = hexChars [(int) ((digest [i] 4) & 0xf)];
digestChars [(i * 2) + 1] = hexChars [(int) (digest [i] & 0xf)];
}
String hashedPassword = new String (digestChars);

The algorithm does little more than invoke the standard MD5 algorithm, then convert the resulting byte
array to hexadecimal.

Administrative Users
Earlier it was mentioned that applications are responsible for storing and maintaining their own users,
and that the security system would interface with whatever schema is used by the application.
Dynamo is itself an application with its own security needs. For example, the HTML Component Browser
requires a security system in order to restrict access to those who have the proper username/login
configuration. Dynamos development and deployment tool, the ATG Control Center, has even richer
security requirements. ACC users are able to change applications, change system configurations, manage
marketing campaigns (if Dynamo Scenario Server is installed), affect store catalogs, change site content,
etc. Because all of these functions are performed by the same tool, the security mechanism must have a
notion of roles or privileges to allow users to only access those functions to which they are entitled.
Dynamo defines the schema by which it maintains these administrative users. Dynamo also includes,
through the Admin window of the ATG Control Center, an interface that allows an administrator to
maintain this list of users, creating and removing users, and adding or removing roles and privileges.
A J2EE application may elect to base its security on this list of users instead of requiring its own schema
and user manipulation tools. If so, the J2EE application should point its user-manager (in the

141
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

dynamoJ2EESpecifier.xml file) to the component at


/atg/dynamo/security/AdminUserAuthority. This component stores its data in an XML file. Or the

system may have been configured to use a repository-based administrative user authority, found at
/atg/dynamo/security/RepositoryAccountManager. The details of these user authorities are

discussed in the ATG 6 Dynamo Programming Guide.


Developers using the administrative user authority will automatically have a pre-built schema, along with
tools to manipulate the lists of users. However, such developers should be aware of some important
points. First, the administrative user authority and associated tools are designed to handle small numbers
of users - not the thousands of users expected at an internet Web site. Second, the administrative user
authority uses the same namespace to represent users and roles, so developers have to be careful not to
give a user and role the same name. Finally, the administrative user authority defines a schema that is not
particularly adaptable to existing schemas - the developer will have to be content with the schema that
comes with that user authority.

142
8 - J2EE Security

ATG 6 J2EE Development and Deployment Guide

Appendix A: Darina Command Options

The following is a list of the command-line options that may be passed to the runDarina command:

Option

Description

-dar-version {dar-file-name}

Print DAR version number of DAR file to the screen and exit.

-no-dar

Validate and build application in staging directory, but do not


generate a DAR file.

-debug

Be more verbose and print out debugging status message.


May be useful in tracking down configuration, build or file
creation problems.

-o {output-dar-file-name}

Is taken as either the name of an output file to be created


next to the staging directory (i.e., in the parent directory of
the staging directory), or, if it is a path (contains a slash), is
taken as relative to the current directory.

-compiler,javac {command}

Specify the default javac compiler command. It is preferable


to specify this as a DAR_COMPILER environment variable in
your environment.sh or environment.bat file. See
Specifying Another Java Compiler.

-no-java-src

Filter out all Java source files (files ending in .java) from the
module JARs when creating the final DAR file.

-stage-dir {stage-dir-name}

Specifies the staging directory. Can be either an absolute


path or a path relative to the current directory.

-server {server-name}

Specifies the server whose Dynamo environment should be


loaded.

-0, -1, -2, -3.... -9

Specifies the compression level used for JAR files. Defaults to


0 (no compression) to speed the JAR creation process.

-q

Be quieter in emitting messages.

-Q

Be silent, except for errors or problems which stop DAR file


creation.

-build

Recompile any source files that are out of date with respect to
their corresponding class files.

143
Appendix A: Darina Command Options

ATG 6 J2EE Development and Deployment Guide

-buildall

Perform a full rebuild. Regenerate and recompile all Impl and


Stub EJB files, and compile all source files, even those that are
not out of date with respect to their class files.

-m {modules}

Specifies the list of modules (separated by spaces) to use to


set the CLASSPATH when compiling the application.

-jsp-compile

Precompile all JSP files.

-jsp-compile-config-path
{config-path}

Specifies the CONFIGPATH to use when precompiling JSPs. If


omitted, Darina uses the DAS CONFIGPATH plus a special
directory used only for batch page compilation.

-cmp-repository-generate-all

Generate a SQL repository definition file for all EJBs that use
container-managed persistence, regardless of whether
automatic mapping is specified.

-max-table-name-length

Specifies the maximum length (in characters) for the table


names in the SQL script generated for EJB containermanaged persistence.

{number-of-chars}

-regen

Regenerate and recompile all Impl and Stub EJB files.

-output-client-jar
{client-jar-name}

Generate a separate ejb-client-jar file with the given


name. This client JAR file will be a combination of all the ejbclient-jar files in the application. External applications that
wish to use this applications EJBs will need to include this file
in their CLASSPATH when compiling and running their
applications. This is described more fully in the Application
Clients chapter.

-iiop

Use IIOP as the EJB protocol. Overrides setting in


dynamoJ2EESpecifier.xml file.

-rmi

Use standard RMI as the EJB protocol. Overrides setting in


dynamoJ2EESpecifier.xml file.

-merge-ejb-class-loaders

Allow EJB modules to share all classes, including internal


classes, when building and deploying. Allows EJB client JARs
to be built even if there are dependencies between EJB
modules.

-separate-ejb-class-loaders

Dont allow EJB modules to share classes. EJB client JARs must
be self-contained to be built.

-unpack-rar-subjars

Unpack the specified list (separated by commas) of connector


sub-JARs. Specify each sub-JAR as a pathname relative to the
staging directory, or use all to unpack all connector subJARs.

{jar-path-names}

144
Appendix A: Darina Command Options

ATG 6 J2EE Development and Deployment Guide

Appendix B: Sun JMS Reference


Implementation

Dynamo includes several different JMS providers. The Dynamo Message System, discussed in the ATG 6
Dynamo Programming Guide, has two JMS providers, SQL JMS and Local JMS. However, these providers do
not support the complete JMS API, so in addition, Dynamo includes the Sun JMS Reference
Implementation. You should use the JMS Reference Implementation, for example, if your J2EE
applications include any message-driven beans.
This appendix discusses some aspects of using the JMS Reference Implementation. For more information,
see http://java.sun.com/products/jms/.

Configuration and Administration


Dynamo uses the Nucleus component /atg/dynamo/service/j2ee/JMSService to manage the Sun
JMS Reference Implementation. This component starts up the reference implementation, and has
properties for configuring the data sources and the IIOP server used by the RI.
The JMSService component has dataSource and xaDataSource properties for configuring the data
sources used by the RI. By default, these properties point to the Nucleus component
/atg/dynamo/service/j2ee/JmsDataSource. Note that this is separate data source from the one
used by many Nucleus components (/atg/dynamo/service/jdbc/FakeXADatasource). Like the
FakeXADataSource, JmsDataSource is configured by default to point to the SOLID database that comes
with Dynamo. On a production site, you should reconfigure JmsDataSource to point to your production
database.
You can use the jmsadmin script (in <DAS6dir>/home/bin) to administer the JMS Reference
Implementation. This script has options for creating topics and queues, listing the messages in a queue,
creating and deleting connection factories, etc. For more information, go to the directory
<DAS6dir>/home and type:
bin/jmsadmin -usage

145
Appendix B: Sun JMS Reference Implementation

ATG 6 J2EE Development and Deployment Guide

Database Tables

This section describes the database tables used by the Sun JMS Reference Implementation. These tables
must be installed in your database if you are using the Reference Implementation. See the ATG 6
Installation and Configuration Guide for Dynamo Application Server for information about installing these
tables:

sun_jms_message

sun_jms_dest

sun_jms_dur_sub

sun_jms_unack_msg

sun_jms_message
The table used to persist JMS messages.

Column

Data Type

Constraint

msg_id

VARCHAR(256)

NOT NULL

The message ID field.


dest_name

VARCHAR(256)

NOT NULL

The destination for which the message is intended.


msg_txid

VARCHAR(256)

NULL

The consumer transaction ID field.


msg_object

LONG VARBINARY

NULL

The serialized message object.

sun_jms_dest
The destination table used to persist the list of destinations.

Column

Data Type

Constraint

dest_name

VARCHAR(256)

NOT NULL

The name used to refer to this destination.


dest_type

INT

NOT NULL

Specifies the topic or queue.

146
Appendix B: Sun JMS Reference Implementation

ATG 6 J2EE Development and Deployment Guide

max_messages

INT

NULL

Maximum number of messages allowed.


max_bytes

INT

NULL

Maximum number of bytes per message.

sun_jms_dur_sub
The table used to contain the list of durable subscribers.

Column

Data Type

Constraint

client_id

VARCHAR(256)

NOT NULL

The identifier for the subscribing client.


subscription_name

VARCHAR(256)

NOT NULL

The name of the subscription.


selector

VARCHAR(256)

NULL

Pattern used to filter out unwanted messages.


dest_name

VARCHAR(256)

NOT NULL

Name of the destination to which this client is subscribing.


no_local

CHAR

NULL

Allows a subscriber to inhibit the delivery of messages published by its own


connection.

sun_jms_unack_msg
The table used to hold the unacknowledged messages.

Column

Data Type

Constraint

msg_id

VARCHAR(256)

NOT NULL

ID of the unacknowledged messages.


client_id

VARCHAR(256)

NOT NULL

Identifier for the client of this durable consumer.


Note: Not used for unacknowledged messages for a Queue.

147
Appendix B: Sun JMS Reference Implementation

ATG 6 J2EE Development and Deployment Guide

subscription_name

VARCHAR(256)

NOT NULL

Subscription name for this durable container.


Note: The subscription name is the Queue name for unacknowledged
messages for a Queue.
delivery_count

INTEGER

NOT NULL

The number of times delivery has been attempted.


consumer_txid

VARCHAR(256)

NULL

The transaction ID of the intended consumer, message property


JMSXConsumerTXID.

148
Appendix B: Sun JMS Reference Implementation

ATG 6 J2EE Development and Deployment Guide

Index

A
administrative users, 141
application clients
configuring timeouts, 121
developing, 109
J2EE modules, 114
resource references, 110, 113
running, 27, 114
standalone, 116
application resources, 6, 62
applications
building, 22, 27
debugging, 13
developing, 14, 19
J2EE modules, 21
monitoring, 13, 27
reloading, 28
running, 13, 22, 26
runtime directory, 30
structure, 21

B
building applications, 22, 27
deployment editor, 61
running Darina, 22

C
clients. See application clients
cluster manager, 99
administration, 102
configuration, 100
cluster nodes, 100
configuration, 104
clustering EJBs, 95
command options for Darina, 143
communications protocols
IIOP, 77
RMI, 77
compiler
Java, 36
connectors, 67
container-managed persistence (CMP), 9, 87
automatic mapping, 93
configuring, 89
mapping EJB fields to properties, 88

mapping EJBs to repositories, 90


container-managed relationships, 88
context parameters, 40

D
DAR files
creating, 12
Darina, 22
command options, 143
running, 10
staging directory, 10
data source. See JDBC data source
database tables
JMS, 146
debugging applications, 13
demo applications
security example, 130
deploying applications
assembling EAR files, 9
deployment editor, 49, 53
running Darina, 10, 22
staging directory, 10
deployment descriptors
deployment editor, 44
EJB references, 73
deployment editor, 49
adding elements to applications, 55
building applications, 61
deployment descriptors, 44
developing applications, 54
file transfer, 57
installing applications, 53
overview, 49
resource references, 62
running applications, 61
standalone modules, 61
template applications, 55
text editor, 59
validating applications, 60
developing applications, 14, 19
adding new elements, 55
standalone modules, 62
DSP tag library, 40
DSPEL tag library, 40
Dynamo and J2EE, 3
Dynamo Archive files. See DAR files
Dynamo J2EE Specifier file
creating, 10
filling in, 11

149
Index


Dynamo request, 38
Dynamo services
Nucleus components, 3
repositories, 4

E
EAR files
assembling, 9
EJBs
accessing from Nucleus components, 87
cluster management, 99
cluster manager administration, 102
cluster manager configuration, 100
cluster nodes, 100, 104
clustering, 95
communications protocols, 77
container-managed persistence, 9
EJB references, 73
environment entries, 75
failover, 98
field types for CMP, 88
finder methods, 9
IOR Security, 77
JNDI and clustering, 96
load balancing, 97
loading and storing data, 81
overview, 71
passivating, 83, 85
pooling, 83
security, 80
session backup server, 100
stubs and clustering, 97
transaction management, 78
Enterprise Archive files. See EAR files
environment entries, 68
Web applications, 68
external build tree, 33
external source tree, 31

F
failover
configuration, 107
session backup, 107
failover of EJBs, 98
file transfer
deployment editor, 57
filters, 41
example, 42
processing, 38
finder methods, 9
RQL statements, 92

G
global resources, 6, 62
GSA repositories. See repositories

ATG 6 J2EE Development and Deployment Guide

H
hashing passwords, 138

I
IIOP, 77
IOR Security, 77
installing applications
DAR files, 53
EAR files, 53
standalone modules, 62
internal source tree, 35
IOR Security, 77

J
J2EE modules, 21
J2EE projects, 20
J2EE security. See security
Java compiler
specifying, 36
Java Connector Architecture, 67
JavaMail
resource references, 66, 113
JDBC
connection pools, 63
data sources, 64, 128
resource references, 110
JMS, 145
database tables, 146

L
logging in to Web applications, 129
logging out of Web applications, 129

M
mapping resource references, 6, 62
monitoring applications, 13, 27

N
Nucleus components
overview, 3

P
passivating EJBs, 83, 85
password hashing, 138
pooling EJBs, 83

R
RAR files, 67
reloading applications, 28
command-line tools, 30
repositories

150
Index

ATG 6 J2EE Development and Deployment Guide

configuration, 8
configuring for security, 137
mapping resource references, 7
overview, 4
repository items, 5
resource references, 65
RQL, 9, 92
security architecture, 127
SQL repositories, 8
repository query language. See RQL
resource adapters, 67
resource references
application resources, 6, 62
connectors, 67
deployment editor, 62
global resources, 6, 62
JavaMail, 66
JDBC connection pools, 63
mapping to Dynamo services, 6
mapping to repositories, 7
repositories, 65
URL service, 66
RMI, 77
roles (security)
role references, 68
RQL (repository query language). See repositories
running applications, 13, 22, 26
application clients, 114
deployment editor, 61
runtime directory, 30

passivating, 85
session failover, 44
specifying a Java compiler, 36
SQL repositories. See repositories
staging directory, 10
standalone modules, 61
Sun JMS Reference Implementation, 145

T
tag libraries, 40
template applications, 55
text editor
deployment editor, 59
timeouts
configuring for application clients, 121
transaction management
EJBs, 78
transferring files
deployment editor, 57

U
URL service, 66
UserAuthority, 123, 125

V
validating applications
deployment editor, 60

S
security
administrative users, 141
architecture, 123
configuration, 125
configuring repositories, 137
demo applications, 130
EJBs, 80
JDBC data source, 128
password hashing, 138
repositories, 124, 127
role references, 68
UserAuthority, 123, 125
servlets, 41
processing, 38
Web applications, 46
session backup
configuration, 107
session beans (EJBs)

W
Web application deployment descriptor. See web.xml
Web applications, 40
EJB references, 73
environment entries, 68
logging in, 129
logging out, 129
mappings, 44
servlets, 46
session failover, 44
session timeouts, 43
Web services, 41
web.xml
adding new resources, 41
optional resources, 40
required resources, 40

151
Index