 | Level: Intermediate Keys Botzum (swsvcs@us.ibm.com), Senior Consulting I/T Specialist, IBM Software Services for WebSphere
11 Jul 2002 Common code libraries that provide common function to multiple J2EE applications at run time are extremely valuable and provide a number of benefits. But how should these common code libraries be packaged? This article discusses the benefits, challenges and risks of run-time sharing, and of providing J2EE applications with their own local copies of common code binaries.
© 2002 International Business Machines Corporation.
All rights reserved. Introduction The packaging of J2EE applications is defined by
the J2EE 1.2 specification. The intent of the spec is that
Enterprise ARchive (EAR) files, the fundamental constructs that
contain applications, be completely self-contained. Applications
are expected to use APIs provided by the J2EE server vendor, or
those within the EAR, and nothing else. This way, applications can
be independent of each other. This, in fact, is stated quite
clearly in section 8.1.2 of the specification:
A J2EE application consists of one or more J2EE
modules and one J2EE application deployment descriptor. A
J2EE application is packaged using the Java Archive (JAR)
file format into a file with an .ear (Enterprise ARchive) filename extension. A minimal J2EE application
package will only contain J2EE modules and the application
deployment descriptor. A J2EE application package may also
include libraries referenced by J2EE modules, help files
and documentation to aid the deployer, etc.
The deployment of a portable J2EE application
should not depend on any entities that may be contained in
the package other than those defined by this
specification. Deployment of a portable J2EE application
must be possible using only the application deployment
descriptor and the J2EE modules (and their dependent
libraries) and descriptors listed in it.
This does not address the issue of the sharing of common code, or what are often referred to as dependent
libraries. Essentially, these common libraries, which may be developed internally
or purchased from external vendors, provide common function to multiple
applications at run time. Creating common code is extremely valuable and
provides a number of benefits that have been widely discussed elsewhere.
The question here is how should these common code libraries be packaged
at run time:
Should the common code binaries be shared at run time by applications the
way operating systems or product libraries are shared?
or
Should each application just have its own local copy?
The generally accepted practice, and the one consistently
recommended as described above and implied by the articles in the References
section below, is that applications should be as
self-contained as is reasonable. Thus, common code should be
copied into each EAR. More precisely, common code used by applications
should be placed in the root of the EAR (or an appropriate
subdirectory) and shared across the entire EAR. See Footnote 1 In theory, code
can also be placed within each WAR in WEB-INF/lib or within each
EJB JAR, but code placed in either of these places is not normally
sharable by other modules in the EAR.
Since EARs are self-contained applications, it is generally best
to place code libraries in the EAR root, EJBs in the EJB JARs, and
servlets in the WAR.See Footnote 2
It is important to note that the benefits of reuse are independent of this
issue. Whether the code is shared at run time or not, applications can
still use a common set of code libraries that are developed elsewhere and
still provide the usual benefits of reuse. This issue is about runtime
packaging, not reuse.
|
Runtime sharing Some organizations prefer to share common code libraries at run time for
various reasons. In recognition of this fact, most J2EE server vendors
have added non-portable
extensions to support shared code libraries. In the case of IBM© WebSphere© Application Server Version 4.0, this is known as the lib/app
classpath.See Footnote 3
Basically, there is a directory on each WebSphere Application
Server node that can contain JAR files. WebSphere Application
Server will automatically make those JARs visible to every
application on the node. At first glance, this would seem to suggest that
common code should be placed on this common classpath. However,
this is not the case. Common code can be placed here, but
careful consideration of the issues is required since the
implications boil down to a risk tradeoff between two opposing
forces: the desire to make the common code runtime sharable, and
the need to allow for application independence. The benefits of placing common code in a common location and
thus sharing it across all applications are:
- The common code development team only has to
support one (or possibly two) versions in production, rather
than the multiple versions that could conceivably exist if
applications were bundled with common code versions. However,
limiting the versions that applications can use could contain
this situation.
- The common code and underlying databases can
change in sync. Since the common code changes in all
applications at once, it is easier to force database changes.
- Fixes to the common code automatically apply to
all applications. Of course, this is mixed blessing.
- Some small amount of disk and memory space is
saved by not having multiple copies of the same binary images
on disk and in memory. Except for extraordinarily large
libraries, this is not a significant benefit.
The challenges and risks raised by sharing the
code across applications are:
- Backward
compatibility is paramount. Since every application uses the
same version of the common API, it is nearly impossible to
coordinate API changes. Thus, the API must be very stable.
- Changes
desired by one application impact all applications. This makes
introducing change very difficult. Application teams will have
to coordinate their development and test cycles.
- Fixes
required by one application impact all applications. This
creates the difficult tradeoff between fixing one application
quickly and the risks introduced by the change in other
working applications.
- Code on the lib/ext classpath is not reloadable. Thus,
changes to it require restarts of the application servers.
Updates to EARs require only a restart of the EAR.
Scenarios The risks involved with code sharing are not insignificant, and are
difficult to contain or even predict. This is why sharing is
generally not recommended, except for extremely stable code (like
JDBC drivers). Consider two scenarios:
- Three
mission critical applications (A, B, and C) are running on the
same node sharing some common code. One of the applications
fails in production. The appropriate teams are assembled and
it is quickly determined that there is a bug in the common
code that only affects application A. Application A requests
an immediate fix and the common code team quickly provides it.
Because of the critical nature of the defect, this code does
not go through a complete development and regression test
cycle. Application A wants the patch applied to production so
the application can be started (it has now been down for 2
days). Applications B and C do not want the patch applied
because they are afraid this may introduce an unexpected
problem. Do you:
- Apply
the change and tradeoff the risk to applications B & C
against the need to get application A back online? What if
the patch fails and B then stops working? What if it turns
out that the fix for A breaks B and that there is no easy
way to resolve the conflict?
- Do
you delay applying the fix by running the patch with
applications A, B, and C is in a pre-production environment
for 2 days and a full regression test suite? Do you have
such an environment? What about the fact that application A
is still down? What if the fix breaks application B but
works for application A?
- Three mission critical applications (A, B, and C)
are running on the same node sharing some common code.
Application A has a major release scheduled for October and
would like to take advantage of some new function (major
changes) in the common code. Application B is not scheduled
for a release until next year and application C is currently
in maintenance with no development budget. What do you do?
- You
could synchronize the development schedules for the two
applications that are being actively developed. Of
course, this doesn't address application C.
- You
could update the common code in pre-production and fully
retest all three applications. Who will pay the cost of
retesting application C? What do you do if the new
common code causes problems in application B or C?
Application B may not wish to update their code until
the next major release. Application C has no budget at
all.
- You could update the package in production and pray.
All of the risks raised by these scenarios are
alleviated by deploying applications as self contained EARs. Each
application can deploy with different versions of the same common
libraries without fear of disrupting other production systems.
Self-contained EARs greatly simplify the deployment and
operational procedures and reduce the need for synchronizing
development cycles and test cycles of multiple, possibly
unrelated, applications. The cost is minor, comprised mainly of
slightly increased memory and disk footprints. Thus, in most
situations, developing self-contained EARs is clearly the best choice.
Mapping applications to application servers We have focused on the packaging issues
surrounding applications and how best to create self-contained
applications by leveraging the J2EE EAR concept. We have not
discussed issues surrounding the sharing of application servers in
a production environment. There are a variety of considerations
surrounding whether multiple applications should share one
application server (a single JVM) or whether each application
should have its own application server. In general, the latter is
easier to manage, although it does use more resources. The key message of this article
is that by using the packaging approach recommended here, each
application is self-contained. Therefore, multiple EARs can be
deployed to the same application server or to different application
servers without regard to classloader issues. The number of
application servers then becomes an operational issue that should
have little impact on the application development teams. This
helps to reinforce the separation of concerns encouraged by J2EE.
 |
Conclusion It is worth noting that this problem is really
just another example of the more general issues associated with
sharing infrastructure. These same issues occur in the context of
sharing WebSphere Application Server infrastructure, databases,
and hardware. In many cases, it makes business sense to share
infrastructure when the cost benefits justify the increased risk.
In the case of shared infrastructure products and hardware, the
potential cost efficiencies are substantial because of the
enormous cost of maintaining computer hardware, and of buying and
supporting products. Even then, many business units within large
enterprises choose not to share infrastructure even when it is
available, often because cost savings are not sufficient to justify the
business risks. The questions raised by this article are:
- What costs are being avoided by runtime sharing of
common code?
-
Are the cost benefits sufficient in the case of common
internally-developed code to justify the runtime sharing?
The answers will depend on the business, but in general, it is hard to
justify the increased risk. If common code is to be shared at run time,
then it is imperative that each application team leader be made to understand,
agree and strictly adhere to specific constraints on their ability to request
change to the common code. They must accept that in a crisis situation,
where two or more application teams have opposing interests, that a third
party with business authority over both will be the one to decide what
is best for the overall business, not the individual application. At a
minimum, it is strongly recommended that the applications that share common
runtime code all belong to the same business unit. Finally, this article has assumed significant
knowledge regarding J2EE and JavaTM classloaders. Readers needing to
learn more are encouraged to check out the suggested reading in
the References section.
Footnotes | 1 |
For those rare occasions
where there is code that is truly used only by a single WAR or
EJB JAR it can be placed in those modules.
| | 2 |
Of course, you will need
to update the module dependencies to express that the EJB JARs
and WARs depend on the library in the EAR. In WebSphere
Studio, simply right click on the module and select update
dependencies. See the first two articles in the References section for details on using WebSphere Studio.
| | 3 |
Shared code could also
theoretically be placed on the application server classpath,
resulting in the code being shared by all applications on that
application server. However, this is strongly discouraged,
since code placed here is not dynamically reloadable and has no
visibility into the WebSphere Application Server or generic J2EE
APIs, making this
classpath useless.
|
Resources
About the author  | |  |
Keys Botzum
is a senior consultant with IBM Software Services for WebSphere. Mr. Botzum has over 10 years of experience in large scale distributed system design and additionally specializes in security. Mr. Botzum has worked with a variety of distributed technologies, including Sun RPC, DCE, CORBA, AFS, and DFS. Recently, he has been focusing on J2EE and related technologies. He holds a Masters degree in Computer Science from Stanford University and a B.S. in Applied Mathematics/Computer Science from Carnegie Mellon University. Consultants with Software Services for WebSphere help customers deploy IBM products into their organizations. If you are interested in engaging these consultants, please contact us at
swsvcs@us.ibm.com
.
|
Rate this page
|  |