The K-Zone: A SunONE Application Server 7 FAQ
[Update 08/07: this document is completely obsolete!]
Disclaimer
The author is a certified iPlanet/SunONE instructor, but not
involved in any way with the development or management of the
SunONE product line. Please bear in mind that the
following notes are based on my own experiences, and those of
other people working with SunONE Application Server in the field. They do not
constitute official pronouncements from Sun Microsystems.
Statements like `...has been found to work in practice' mean
exactly that: at least one person has reported success. They
should not be taken as a recommendation to follow a particular
course of action.
What versions of the application server are available?
SunONE Application Server 7 has two basic versions: a Platform
Edition, which is supplied
as part of modern Solaris releases and is free-of-charge for
development and production, and a
Standard Edition, which is free-of-charge for development and
evaluation. For production use, the Standard Edition costs about
$2000 per CPU. The most obvious difference between the Platform
Edition and the Standard Edition is that the former has no support for
remote administration. You have to have console access to administer
it.
At the time of writing (June 2003), the Enterprise Edition,
which will provide full failover and load balancing support, was
not available for general release.
The Standard Edition is also available bundled with the SunONE Studio
IDE tool, version 5. Integration between the IDE and the application
server is now very slick, and well worth investigating.
Is there a Linux version?
Yes. Administration is almost identical to the Solaris version.
Is there a Windows version?
Yes, but I haven't used it so I can't really comment on it.
How is SunONE Application Server 7 different from iAS 6/6.5?
In every conceivable way. S1AS7 is, in effect, a completely new
product, and has little, if any, version 6 code in it. S1AS7 shares
code with the J2EE Reference Implementation, Tomcat,
SunONE Message Queue, Forte Transparent Persistence, and the SunONE
Web Server, version 6.
What is the application server's basic architecture?
The application server services web clients using the HTTP core from
the SunONE Web Server, version 6. This core is written in C, and
supports all the usual web server features, such as CGI, static
content, quality of service definitions, and virtual servers. In
addition, on Solaris platforms the HTTP core can integrate with the
kernel-level HTTP cache.
If an incoming HTTP request is not for an item of static content, but
corresponds to a web application, then the request is routed to a
J2EE plug-in module based on the proprietary NSAPI interface. This module
is also written in C. The plug-in passes the request to an embedded
JVM, which is running a variant of the Tomcat servlet/JSP engine. The
JVM also runs the EJB core and the various back-end services, such as
connection pooling, resource adapters, and persistence management.
The EJB core is also accessible to IIOP clients, which might be
stand-alone Java applications, or applications written in other
languages.
Supplied with the application server is a variant on the SunONE
Message Queue (formerly iPlanet Message Queue) which can be used to
support applications that use asynchronous messaging. Note that this
is not related in any way to the SunONE Messaging Server, which is an
e-mail server.
What are domains, instances, and virtual servers?
A S1AS7 installation is structured heirarchically, with the
domain being the top level of the hierarchy. Domains are, to
all practical intents and purposes, different installations of the
server (except that the installations share a common set of binaries).
Each domain has its own administration server with its own
admininstrator credentials and administration port number.
Within each domain there are any number of instances. In practice
there must be at least two -- the administration server instances and
one working instance. Applications and content are deployed on the
working instances, while the administration server instance supports
the administration console.
Each instance has its own HTTP listener configuration, so different IP
numbers of ports can be handled by instances. Each instance, including
the administration server instance, has its own set of three
appservd processes.
Each instance has at least one virtual server. When the instance is
created, by default it gets one virtual server with the same name as
the instance. Virtual servers, which can be IP-based or host-based
(see below). Virtual servers appear to clients to be independent web
servers, but in fact they are only different configurations of a
particular instance. Each virtual server has its own quality of
service configuration. For example, different virtual servers can have
different bandwidth limits.
Also associated with each instance are one or more HTTP listeners. A
listener runs in one or more threads (selectable in the administration
console), and accepts incoming HTTP connections. A listener listens
either on a single IP number, or any IP number. In either case, the
listener binds to a single port number. The default is for a listener
to accept requests on any IP number.
Each listener feeds incoming requests to one or more virtual servers.
Each virtual server that is attached to a listener has the opportunity
to handle the request. If no virtual server handles the request, then
it is passed to the listener's default virtual server. Typically the
default virtual server is the one that was created first, and has the
same name as the instance. Where a listener is feeding requests to
more than one virtual server, typically the virtual servers will be
configured to accept requests when the host name supplied by the
browser matches some pattern. For example, suppose we have a server
with a single IP number (say 100.101.102.103), which corresponds to
two DNS names -- fred.acme.com and bill.acme.com. We want requests to
fred.acme.com to go to a virtual server called `fred', while requests
for bill.acme.com go to virtual server `bill'. Because there is only
one IP number, there can only usefully be one HTTP listener. The
virtual servers fred and bill will both be assigned to this listener.
However, one of the instances has to be the default, for requests that
don't correspond to either fred.acme.com or bill.acme.com.
To support multiple host names on the same physical host, should I
use different virtual servers or different instances?
Either will work. If you have a small number of hostnames, then
assigning different instances gives a finer degree of control. This is
only possible if the host names map onto different IP numbers. Where
there is only one IP number, or where there are many hostnames to
support, it is much more efficient to use virtual servers.
How do I stop and start the application server?
As each instance of the application server is a daemon process in its own
right (actually, it's three daemons), it is instances that are stopped
and started, rather than the server as a whole. However, it is
possible to stop or start all instances in one operation, which is
equivalent to stopping or starting the entire server.
There are two basic methods: use the asadmin utility, or
start the admin server and instances by running their daemons
explicitly.
To start all instances using asadmin:
asadmin start-appserv
To start all instances in domain `domain1':
asadmin start-domain --domain domain1
To start instance `instance1' in domain `domain1':
asadmin start-instance --domain domain1 instance1
To stop, just replace the word `start' with `stop'.
To start and stop the daemons explicitly, find the bin
directory of the instance, then run `startserv' or `stopserv'.
For example:
cd /var/appserver/domains/domain1/instance1/bin
./startserv
Which operating system processes are associated with the
application server?
For each instance of the application server you should see the
following processes.
appservd -- two processes per server instance (see
below for why). These processes handle all incoming HTTP and IIOP
requests
appservd-wdog -- starts the other processes, and
restarts them if they shut down unexpectedly
imqbrokerd -- a shell script or batch file that
starts, and acts as a watchdog for, the IMQ message broker, which is
a Java application
- IMQ message broker -- appears as a java process
Why are there two appservd daemons for each server
instance (unix platforms) ?
These are the primordial and worker daemons. It is anticipated
that in future releases of the product, each instance will support
multiple worker processes, with the primordial balancing load between
the workers. At present, the primordial process has no particular
function.
Where are the configuration files?
Configuration files operate at an instance level, and are found in
the config directory of a particular instance. The
important ones are as follows.
-
init.conf -- specifies minimal instance-level
configuration, such as the account that will own the application
server processes. This file also contains the NSAPI commands to load
the plug-in module that connects the web server core to the
application server, and to intialize it. There are few good reasons to
edit this file, and it is not modified by the administration server
-
obj.conf -- configuration for plug-in modules,
including the J2EE connector plug-in. As with init.conf,
there are few good reasons to edit this file
-
server.xml -- main configuration file for the application
server and web server cores. Contains configuration for the HTTP
listeners, IIOP listeners, virtual servers, security, etc., etc. Most
changes made by the administration console or the asadmin
command modify server.xml. If you modify it by hand, you
will need to restart the instance for the changes to take effect.
-
keyfile -- user IDs, groups, and passwords, for users
whose credentials are stored in the `file realm' security realm
(see below).
-
login.conf -- provides a list of Java classes that
implement the authentication methods the application server
supports.
-
mime.types -- maps file extensions onto MIME data
types. This file is only relevant to the processing of static HTML
pages.
What are security realms?
A security realm is a particular method for authenticating users
and assigning them to groups. Another way of expressing this concept
is that a realm is a set of users who authenticate against a
particular authentication repository (see next question).
What authentication repositories are supported?
As delivered, the application server supports unix authentication,
LDAP authentication, and text files. Unix authentication simply passes
an authentication request to the underlying operating system, so
any Unix PAM modules will be invoked as for a Unix log-in. LDAP
authentication operates against a directory server. Text file
authentication works against a text file containing user IDs and
encrypted passwords. The administrator can manage this file using
the administration console.
Because the application server supports JAAS (Java Authentication and
Authorization Service), you can plug in any JAAS-compliant
authentication module, or write your own. Alternatively, you could use
one of the many JAAS modules that already exist. For example,
a JAAS module for authenticating to a database table is available
as part of the Jakarta project.
Where are kregedit, etc
Gone, thankfully. iAS6 provided a `registry viewer' to manipulate the
configuration registry product, to achieve tasks that could not be
carried out using the graphical administration console. This version
of the application server has no equivalent of kregedit
for
two reasons. First, it keeps all its configuration in files in the
config directory, and if you want fine control you can
edit them using a text editor, or programmatically. Second, most
configuration that you'll need to do can be done using the graphical
console. If you want to change configuration settings in a script, and
don't want to manipulate server.xml directly, the you
could use the asadmin set command, which can set any
configuration property.
Where are the log files
By default, logs are collected for each instance. All virtual servers
show their logging information in the same log. This behaviour can be
changed by specifying new log file locations in the administration
console. Otherwise, the logs are in
[instance_directory]/logs. The file access
records requests made on the HTTP core. The file
server.log records messages from the application server.
Can the application server log to the Unix system log?
Yes, but it is not enabled by default. This facility can be
managed through the administration console.
Can the logging granularity be changed?
Yes, both for an instance as a whole and for the individual services
within it. At the instance level, log granularity can be set to one of
nine levels, from `info' (a great deal of logging) to `fatal' (only
logs crashes). In each subsystem you can set the log level to one of
these nine levels, or you can set it to `Default', so it takes
the default value for the instance.
How can I view the logs?
The logs are only text files. You can view them with a text editor. If
you cannot log in to your server and get a prompt (a wise precaution),
you can view the logs through the administration console.
Are the logs buffered?
This may be important because on a very busy system the access log
will grow very quickly, and writing the log to file is a significant
overhead. By default, the access log is kept in memory and flushed
every 30 seconds. server.log does not appear to be
buffered for such a long period, but the amount of data delivered to
this file should, in normal operation, be small.
Does the application server support log rotation?
Yes, but the settings page in the administration consoles is easy to
miss, because the link for it appears below the tabs. Select the
required server instance then click the `Logging' tab. The link for
`Log Rotation' is below the tabs, but you may have to scroll the tab
pane to get to it.
There are two built in methods of log rotation. `Internal' log
rotation is carried out by the appservd process itself,
while `scheduler-based' rotation is done by a separate process called
schedulerd. The documentation talks about a `cron'
process, but schedulerd is unconnected with the standard
unix cron utility.
The application server will also coexist with system-based rotation
utilities like newsyslog (Solaris) and
logrotate (Linux).
Does the application server support load balancing?
The Standard Edition does not support load balancing, at least not in
a way that is supported. However, the application server is supplied
with a reverse proxy plug-in called libpassthrough.so
(passthrough.dll on Windows systems) which has
rudimentary load sharing facilities. In particular, it can do simple
round-robin distribution of requests, with session affinity at the IP
level. IP-level session affinity means subsequent requests from
clients with the same IP number go to the same server in the group.
This avoid the problem of breaking up session data between the
servers, but is less flexible that session affinity that works at the
HTTP protocol level.
libpassthrough.so is rather fiddly to configure because,
although it is documented, the documentation assumes that you
understand NSAPI configuration in general. If you don't, you might
find it helpful to have a skim through the NSAPI reference manual
first.
What is the difference between a `DataSource' (or data source)
and a `connection pool'?
A connection pool is named set of physical connections to a particular
external resource, that can be shared between different users. Each
connection in a particular connection pool connects to the resource
using the same user credentials. The `name' assigned to the connection
pool is registered with the application server's naming service, and
typically takes the form `jdbc/XXX' when the external resource is a
relational database.
A DataSource is a named connection to an external resource that may,
or may not, be pooled. Again, the name is assigned to the naming
service, and has the form `jdbc/XXX'.
In normal operation, an application server connects to an external
resource using a named DataSource, not a connection pool. A single
connection pool may be shared between different DataSources. So,
setting up the application server to allow applications to connect to
an external resource has two steps:
- Create a connection pool
- Create a DataSource with the newly created connection pool as its
allocated connection pool
This two-stage approach gives significantly increased flexibility,
because other parts of the application server (e.g., the persistence
manager) can use the connection pool via its registered name, without
needing to go through a DataSource. At the same time, have
applications use the DataSource name decouples them from the internal
pooling system of the application server.
There is one complication with all this. I said that a DataSource is a
named connection to an external resource that may, or may not, be
pooled. The problem is that the connection pool itself needs some way
to connect to the external resource. It does this by using a
DataSource! This sounds like a circular argument, but in fact there
are two different DataSources at work here. The application server's
connection pool connects to an external resouce using a DataSource
supplied by the resource vendor, then the application server offers
its own DataSource to the application. The chain of communication
from the application to the external resource thus looks like
this:
application
|
|
V
app. server's DataSource
|
|
V
app. server's connection pool
|
|
V
resource vendor's DataSource
|
|
V
resource vendor's drivers
|
|
V
external resource
What database engine is the application server supplied with?
The distribution versions of the application server are supplied with
a limited version of
the PointBase relational database. The Platform Edition that comes
with Solaris 9 is not, but PointBase is available as part of the
Solaris 9 distribution and can be installed separately (package name
SUNWasdbo). The problem with this latter approach is that
the JAR file containing the driver does not end up on the application
server's class search path. You need to find
pbclient42RE.jar and copy it to the application server's
lib directory.
How do I enable SSL for the application server?
SSL is enabled for specific HTTP listeners, not for server instances
or virtual servers (except for the administration server -- see below).
So if you want to enable SSL for a specific
virtual server, you must find the HTTP listener that is servicing that
virtual server. In most cases this is straightforward, because there
will be one virtual server per listener. However, if you are using
host-based virtual servers, you may have a complex mapping between
listeners and virtual servers. In any case, you can find the
properties page for the virtual server in the administration console,
and it should show which listener(s) are servicing the server.
In the configuration page in the appropriate HTTP listener, check the
box that says `SSL/TSL enabled'. You may want to review the cipher
settings; by defualt 40-bit ciphers are disabled. Then you'll need
to select a certificate to use. Certificates are selected using the
`Certificate Nickname' list, where the nicknames are the names you
assigned when you installed the certificates. It is at this stage that
administrators typically realise that they don't know how to get or
install a certificate (see next question).
How do I install a server certificate?
I assume (for now) that you want to install a certificate that has
been validated by a commercial or organizational certificate
authority (CA) (if not, see next question). There are three steps to the
process: (1) generate a certificate signing request (CSR); (2) send the
CSR to the CA to be signed; (3) get the signed certificate back; (4)
install the signed certificate. All these steps can be accomplished
using the administration console, in the `Certificate Management' page for a
particular server instance. To get this page, select the `Security'
node in the console, then the `Certificate Management' tab. Under the
list of tabs (and therefore difficult to see) are three links:
`Request', `Install', and `Manage'. Use the `Request' page to generate
a CSR, and the `Install' page to install the signed certificate when
you get it back. It's as simple as that.
Before you can do any of the steps described above, you'll need to
initialize the keystore database (there is a tab labelled `Manage
Database' for this). Bear in mind that the keystore database is
password protected. On the Manage Database page the password is
referred to as the `database password', but on all the other
administration pages it is referred to as the `key pair file
password'. These are the same password; this is just to keep you on
your toes. All changes to the certificate database require a server
restart, and once you have created a keystore database you'll have to
enter the keystore database password every time you start up the
server.
The administration console gives the option of e-mailing the CSR to
the CA, or invoking a URL to send the CSR. What happens if your server
doesn't have internet access? In a production environment it is most
likely that it won't have. When the console generates a CSR to send by
e-mail, it also writes it to a file in the /tmp
directory, so you can just enter a bogus e-mail and then capture the
file for later processing.
Can I use a non-CA certificate for development/evaluation?
There might be occasions on which you want to enable SSL for a server,
but don't want to go through the hassle of generating a CSR and having
it signed by a CA. In a development system, for example, and quite
possibly for the administration console itself, you won't need a
signed certificate.
However, to the best of my knowledge (and I've searched really hard),
there is no way to drop a self-signed certificate into the certificate
database, and use that as the server certificate. The reason for
this is that the administration console expects the server certificate
to come back from the CA encrypted using the certificate's public key,
and then to have to decrypt it using the certificate's private key.
The private key was stored during the generation of the CSR. So if the
administration console is given a server certificate that is not
encrypted, it won't install it. If it is encrypted, then it won't be
able to decrypt it because it doesn't have the matching private key
available.
Now, you can install a self-signed certificate as a CA certificate,
rather than a server certificate, without its needing
to be encrypted (obviously -- you've won't have the CA's private key
to decrypt it with). However, the application server refuses to use what it
believes is a CA certificate as the server certificate. This appears
to be an aribtrary design decision: there is no cryptographic reason
why the server can't offer a self-signed certificate as part of the
SSL handshake. Most other web servers allow self-signed certificates
to be used.
Anyway, the long and short of it is that you will need to generate a
CSR and have it signed to get SSL working on the application server.
The server does not care who signs the certificate -- it can be
any self-signed certificate -- but it requires that the certificate
has been through the CSR process. You can use a commercial CA product,
such as SunONE Certificate Manager, to sign your CSRs. Alternatively,
you can use OpenSSL, which is free of charge.
The following is a detailed description of how to use OpenSSL and the
application server administration console to generate a CSR, send it
to the CA (you, in this case), sign it, send the signed certificate
back, and install it. You can get a Solaris version of OpenSSL
from sunfreeware.com. If you don't have
GCC installed, you'll need to get libgcc-3.3 as well, from the same
place. It speeds things up enormously if you can get a copy of the
script sign.sh,
which is part of the Apache mod-ssl distribution. This
script automates the creation of the large number of files and
command-line arguments you need to use OpenSSL to sign a CSR.
Step 1 - generate the self-signed certificate using OpenSSL
In the following, I assume that the openssl utility is on
the PATH. If not, you'll need to modify PATH or modify
sign.sh; the former is easier.
PATH=$PATH:/usr/local/ssl/bin
First, create a keypair file to use with the new certificate. Call this
file ca.key. As part of the process you will be prompted
to enter a passphrase for the key file. This can be anything you like,
but remember it for the next step.
% openssl genrsa -des3 -out ca.key 1024
Now generate a self-signed certificate, signed by the key you
generated in the previous step. Call this certificate
ca.crt. As part of the process you will be prompted for
the passphrase for the key file ca.key, and for the
details of the new certificate. These are arbitrary; they will be
presented to web browser users if they ask to see who signed a
particular server certificate.
% openssl req -new -x509 -days 365 -key ca.key -out ca.crt
You can use the file ca.crt to sign any number of
server certificates hereafter. Note that ca.crt is not an
arbitrary name: the script sign.sh looks for a file
with this name.
Step 2 - create the keystore database
This step only has to be done once in the life of an application
server instance. Note that once you have done it, you will need to
enter the keystore password every time you start the server instance.
In the application server administration console, select the
`Security' node for the instance to be configured, then the `Manage
Database' tab. Enter the password for the keystore an hit `OK'. You
will need to restart the server after this step.
Step 3 - generate the CSR
In the application server administration console, select the
`Security' node then the `Certificate Management' tab. For
`CA E-mail Address' enter anything (you aren't really going to
send the e-mail). For `Key Pair File Password' enter the keystore
password that you assigned in the previous step. Fill in the
information that will go on the new certificate (from `Requestor Name'
downwards). This can be anything you like, except that `State or
Province' must be at least five letters long, and `Country' must be a
valid two-letter country code (e.g., `UK').
The console generates the CSR, and display the details on the screen.
Capture the last part of the display, from `--- BEGIN...' to
`---END...' into a file (e.g., cut-and-paste into a text editor).
Include the BEGIN and END lines in the file. Save the text file
as, for example, bogus.csr.
Sign the CSR with your CA certificate
Use sign.sh as follows:
% sh sign.sh bogus.csr
You may need to replace sign.sh and bogus.csr
with their full paths. Note that sign.sh writes its
temporary files to the current directory, so if you're not logged in as
root you'll need to be in a directory you have write
access to. The signed certificate will be called
bogus.crt, and located in the same directory as the CSR
file. Note that sign.sh isn't doing any magic; if you
look in this script you'll see that all it does is generate the rather
ugly configuration files that the command openssl ca
requires.
Install the signed certificate
In the administration console, select the `Security' node then
the `Certificate Management' tab. Select the link `Install' under
this tab. Enter the keystore password in the `Key Pair File Password'
box. Set the `Certificate Name' field to any name you like -- this is
the name that is assigned to the certificate in the server's
database, not the name of the certificate.
Paste the signed certificate data from the file `bogus.cert' into
the `message text' box, and check the button that enables this
method of entry. Paste everything between the ---BEGIN and ---END lines,
including those lines themselves. Click OK. When the certificate
details appear for review, click `Add certificate'. You will need to
restart the instances (again) after this step.
Assign the certificate to the listener
Find the name of the HTTP listener that is assigned to the server for
which you want to enable SSL. Select the configuration page for that
listener in the administration console. Check the box `Enable SSL/TLS'
then select the name of the certificate as you assigned it in the last
step. Click OK. That's it -- test by pointing a browser at
https://server:port and see what happens.
Can I enable both SSL and non-SSL communication for the same
(virtual) server?
Yes, but you'll need to create two HTTP listeners, and plumb them into
the same virtual server. When you enable SSL for a listener, this has
the effect of disabling non-SSL communication.
Can I use SSL to get access to the administration console
securely?
Yes. Enabling SSL for the administration server is essentially the
same as for individual HTTP listeners. The difference is that the
administration server only has one listener, so SSL is either enabled,
or not. You can't have both SSL and non-SSL connections to the
administration server. The administration server has its own
certificate database, and can't share certificates with the server
instances. So you'll have to go through the CSR/signing process
specifically for the administration server.
Can different virtual servers have different server
certificates?
With IP-based virtual hosting, there is usually no problem with
assigned different certificates to different virtual servers. All that
is necessary is to create an HTTP listener for each virtual server,
and install the appropriate certificate in each listener.
Things are less straightforward with host-based virtual servers. The
problems are not specific to the SunONE product, but are consequences
of the way that HTTPS works. Like all other HTTP server, S1AS
implements host-based virtual servers by looking at the
Host: header sent by the browser in each HTTP request.
Although all virtual hosts may have the same IP number, the
Host: header disambiguates them. The problem is that this
header is an ordinary part of the HTTP request, and will not be sent
until the SSL handshake is complete. The certificate exchange occurs
during the SSL handshake. In short, the server certificate is sent to
the browser before the browser will send the information the
server requires to select the correct virtual host. In general,
therefore, host-based virtual servers cannot have their own server
certifcates. The browser will receive the certificate dispatched by
the listener, and all virtual servers on that listener have the same
certificate.
In fact, the problem is worse than it first appears. During the SSL
handshake, the browser will verify that the hostname assigned to the
certificate is the same as the hostname to which it has just issued
the request. In general, their must be an exact match. So if two
virtual servers, www.acme.com and
www.fred.com issue the same certificate, at least one of
them is going to be queried by the browser as having an incorrect
hostname. If the virtual servers have hostnames that share a domain,
then this problem can be overcome using wildcard certificates.
A wildcard certificate is one that has a wildcard in the hostname,
e.g., *.acme.com. Such a certificate should be accepted
by a browser if the certificate is received from any server with a
name of the form something.acme.com.
Because wildcard certificates are a relatively recent innovation, not
all browsers support them, although most popular ones do. You can
generally expect to pay a bit more for a wildcard certificate than a
single-host one.
Can a J2EE application use the Java logging API?
Yes, but bear in mind that not all application servers support this
API (they are not obliged to), so your applications may not be
portable.
Where do standard error and standard output go?
If your Java components do a System.out.println or
a System.err.println, then the output is only captured if
the server instance is configured to capture it. This configuration is
done through the `Logging' tab of the instance in the administration
console. If enabled, standard output and standard error go to
server.log in the per-instance logs directory.
What is the class search path within an EJB/Web component?
This question is commonly asked by developers who want to deploy
shared class libraries that will be accessible to all EJBs or
all Web components in other applications. Consider, for example, a
library for doing financial operations, which is used by a number of
financial applications. The J2EE specification is quite clear about
this: the only way to make the shared library available to all
applications is to include it with all applications. The developer
cannot rely on anything else being portable. The problem with this
strict approach is that many developers don't like it. If the library
is large, then it slows deployment and redeployment considerably.
If the library is deployed in many different applications, the fact
that each application gets its own classloader means that many
different copies of the library's bytecode will be resident in memory
at the same time. So, many developers prefer to put shared code into a
directory where multiple applications can find it.
Whatever the merits of this approach, you should be aware that it is
outside the scope of the J2EE specification, and may not be portable.
Within an EJB component that is part of an application or stand-alone
module, the runtime environment is configured to look for classes in
the following places (in the order shown).
- The JVM bootstrap classes (such as
java.lang.String)
- The JVM's system classpath. This is defined in
server.xml for each instance, and can thus be set
differently for different instances. Note that the CLASSPATH
environment variable is ignored by default, but this can changed in
server.xml.
- JAR files in the directory
[instance_dir]/lib
within a specific
instance, and separate classes in
[instance_dir]/lib/classes (in the application server
documentation, these locations are called the common classpath).
- Classes in resource adapters that have been deployed independently
of applications
- Classes in the EJB JAR file itself.
- JAR files listed in the
Class-Path: attribute of
the file META-INF/MANIFEST.MF within the EJB JAR file.
For a Web module, the same locations are search, except that rather
than looking for referenced JARs in MANIFEST.MF, the
web module classloader looks in the directory WEB-INF/lib
withing the Web module. If the Web module is part of an application
that contains EJBs, then the Web module classloader will look for
classes in the EJB modules as well.
What is notably absent in the list of class search locations given
above is any mechanism by which the classes in one application or
module can locate classes in another. This is intentional;
applications and modules are independent, and expected to be isolated.
See the next question for ways to get around this isolation.
How can EJBs in one application/module call EJBs in another?
Before answering this question, it's worth pointing out that the J2EE
specification provides no mechanism for components to be shared
between applications. This is for security purposes: if you are
hosting multiple applications, you need to be sure that they cannot
interfere with one another, at least not unless you allow it.
The isolation between applications and modules is controlled by the
classloader scope. For a given EJB module, the classloader will load
at all the locations listed in the example above (previous question),
but nowhere else.
There are various ways around this `problem' (it isn't really a
problem, it's a feature), with varying degrees of elegance. The
simplest is to put all the classes that the calling component needs to
load onto the system classpath. Don't forget that this includes the
stubs of the EJB components. When you deploy the target application
(that is, the application whose components will be the targets of
other applications' calls), the server generates a `client JAR'
containing classes that calling components will need. If the
application EAR file is called `X', then this file will be called
XApplicationClient.jar, and will be found below the
applications directory for a particular instance. This
JAR is really intended to support the use of stand-alone clients, but
one EJB application can be seen as a stand-alone client of another.
So copying XApplicationClient.jar to
[instance_dir]/lib makes the classes the EJBs in
application X available to all other applications. These other
applications will look up EJBs in the target application using their
JNDI names; they can't use java:comp/env names,
because the java:comp/env namespace has application
scope, not instance scope.
Using the lib directory makes
the target application accessible to all other applications in
that server instance, which may be too wide a scope. If you just want
to make EJBs in application X available to application Y, then a
better approach is to package XApplicationClient.jar
inside one of the EJB modules in application Y. Then, in the
MANIFEST.MF file for that EJB module, reference the
included XApplicationClient.jar using a
Class-Path: statement.
©1994-2006 Kevin Boone, all rights reserved