An Application
Framework for a Distributed Environment
Ramanand Singh
Abstract
An Application
Framework for a distributed environment has been discussed. The purpose of
this Application Framework is to provide a set of application and platform
neutral services and components that are based on the best possible design
patterns, standards, and practices offered at the present time. The framework
encapsulates many of the application complexities and commonalities, as well
as encourages appropriate design and implementation principles to its consumers.
Special emphasis has been put on J2EE-based application environments.
An application
framework is a collection of reusable components. These components are designed,
developed, and tested in a general environment. These are not intended to
be used in just a single software application, rather the goal of this framework
is to reuse the services in multiple projects without alterations. Each of
these framework components provides a specific set of services to be used
in an application. The framework must be designed in such a way that an interested
project team can pick and choose its components to be used in its project
- based on the project needs. Such framework reduces development time while
improving the quality of the software using it. Developers of an application
can devote their time concentrating on the business specific problems at hand
rather than some auxiliary utility code required to perform generic tasks.
A good application framework also enhances the scalability and maintainability
of software application through well defined application programming interfaces
(APIs) and their documentation.
The Application
Framework discussed in this document has put special emphasis to Java 2, Enterprise
Edition (J2EE) based distributed environment and software applications development
using J2EE platform.
For an
application framework to be successful, following features have been kept
in mind:
The proposed
application framework consists of the following service components: Configuration
Services, Logging Services, Exception Handling, EJBXtension Services, and
Persistence Services. A general relationships amongst various components are shown in Figure 1. A scalable design of the framework will allow it to
add other components as the need for additional services arises.
The Configuration
Services component provides generic lookup services for any J2EE components
as well as for simple Java classes. The component works with an XML input
file containing all desired configuration items in an XML hierarchy. After
reading the XML file and parsing the XML document, the component maintains
an XML document tree. In providing the configuration lookup service, the Configuration
Services component makes sure that it retrieves the value for a given key
from the correct branch of the XML document tree. An example configuration
file is shown in Figure 2 below to depict the possible information hierarchy
available in the configuration parameters.
It is important
to note that this component can handle multiple configuration files. This
is accomplished by including auxiliary configuration files into the main configuration
file. This mechanism helps keep the various configuration files separately
to preserve the modularity and granularity of various other components.

Figure 1
Application Framework Components
Various
services provided by the Configuration Services component include:
<?xml version='1.0'?>
<configServicesParams>
<application>
<class>com.ti.apps.client.ClassLab</class>
</application>
<logging>
<debug>
<file>/com/ti/apps/classlab/logs/debug.log</file>
<level>3</level>
</debug>
<log>
<url>http://education.ti.com/apps/classlab/logs/application.log</url>
<level>1</level>
</log>
</logging>
<parameters>
<ExpirationPeriod>19</ExpirationPeriod>
<jdbc>
<driver>jdbc</driver>
<vendor>database-vendor</vendor>
<protocol>vendor-protocol</protocol>
<host>dbserver.ti.com</host>
<port>9000</port>
<dbServer>DatabaseServer</dbServer>
<mode>database-server-mode</mode>
<username>db-user</username>
<password>db-user-password</password>
<driverClass>com.dbvendor.jdbc.DriverClassName</driverClass>
<database>database-instance</database>
</jdbc>
<ContactInfo>
<ContactFilename>
/com/ti/apps/classlab/data/contact-info.xml
</ContactFilename>
</ContactInfo>
</parameters>
</configServicesParams>
Figure 2 A sample XML-based Configuration File
Event logging
is an essential and the most used component of the Application Framework.
Logging services provide facilities for logging various kinds of events -
general information, debugging information, application warnings, unexpected
errors, and so on. Logging such events and messages helps developers debug
their application, quality assurance personnel perform the software testing,
and application administrators troubleshoot application problems.
General
features of the Logging Services component are briefly noted below.
Message
Filtering:
It provides a filtering mechanism to filter out messages up to a desired
level of severity.
The message persistence is achieved by directing log messages and
events to a database. The log database is to be different from other transactions.
In other words, the log database must not be a part of a transaction. Otherwise,
the log message will also be rolled back should an unexpected situation
arise.
The various
services of Logging Services component fulfilling the above mentioned features
are listed in this section.
From the
point of view of flexibility, scalability, configurability and other such
capabilities of a Logging Service component, one of the best implementation
of this component would be based on Message Driven Bean (MDB). The MDB based
design will easily support the distributed
environment
of J2EE.
In this
design scenario the MDB will be the real engine to provide the actual logging
activity of writing the log message to the desired channel. In order to log
a message, a client component (it could be any J2EE component, such as session
EJB, entity EJB, or a client program) finds the appropriate message queue
and sends the log message to it. Alternately, the application component can
publish its message (to be logged) to the JMS topic.
The component
sending the message to the message queue or topic is known as message sender
or a publisher, respectively. Once, a message sender sends the message or
a message publisher publishes a message, the message driven bean is automatically
instantiated, if not already exists. The onMessage (Message) method gets invoked.
This onMessage method is the one who handles the log message as per the log
policy set forth for the application.
Software engineering process is usually a very methodical and rigorous if followed correctly. However, omission can not be completely ruled out at one of the stages of software life cycles. Also, it is almost impossible to test an application for all possible error conditions it can encounter in production. Exceptions provide a clean way to check for such omissions and/or errors in the application by signaling errors directly rather than using flags. An unexpected error condition in a method necessitates for throwing an exception, which is then caught further up in the method invocation stack. Uncaught exceptions result in the termination of the execution thread which prints a stack trace information. On occurrence of an exception, actions after the point at which the exception occurred do not take place. The next action will be either a finally block or a catch block that catches the exception.
Exceptions can be classified in two categories – System and Application exceptions, and synchronous and asynchronous exceptions.
A system exception indicates a problem with the services that support an application. Examples of these problems include: unable to obtain a database connection, a failure of SQL insert clause due to a full database, unable to find a desired object through a lookup method, and so on. RuntimeException types and subtypes are known as system exceptions. More serious errors are signaled by exceptions of type Error. These exceptions can occur at any time and in any code. The system exceptions are not supposed to be listed in the throws clause of a method. These are ubiquitous and every method can potentially throw them, making them unchecked by the compiler.
In the EJB environment, javax.rmi.RemoteException types and subtypes including javax.ejb.EJBException are also known as system exceptions. System exception is generated when a method (enterprise bean business method, onMessage method, or container callback method) encounter various exceptions or errors that prevent the method from successfully completing. This happens because either the exception/error is unexpected, or the EJB provider does not know how to recover from it. Failure to obtain a database connection, unexpected RuntimeException, JVM errors, unexpected RemoteException, and JNDI exceptions are few examples of system exceptions and errors.
An EJB container catches a system exception; logs it; and, except in the message driven beans, throws the javax.rmi.RemoteException to the remote client, or throws the javax.ejb.EJBException to the local client. The container in which the bean method participated rolls back transaction and makes sure that no other method is invoked on an instance that threw a system exception.
Any exception that does not extend javax.lang.RuntimeException or the javax.rmi.RemoteException is an application exception. These are checked exceptions – forcing compiler checking for their validity. Such exceptions must be declared in a throw clause. An application exception signals an error in the business logic, i.e., program logic.
An application exception thrown by an enterprise bean instance should be reported to the client precisely (i.e., the client get the same exception). Such exceptions should not automatically rollback a client’s transaction. The client should be given a chance to recover a transaction from an application exception. An unexpected exception that may have left the instance’s state variables and/or underlying persistent data in an inconsistent state can be handled safely.
Synchronous exceptions occur as a result of either a throw statement or an execution of a particular instruction (such as divide-by-zero).
On the other hand, an asynchronous exception can occur at any time and it can occur only due to an internal error in JVM. Java developers can not do much about such exceptions.
Exception Handling component provides exception propagation and handling services to other components of the application. Any component needing to handle an exception in a special way may simply pass the exception to this component. The exception handling component uses logging services to log the exception and any reformulation of the exception desired. This component also provides a list of predefined exceptions useful for handling various kinds of unexpected error conditions in EJB instantiations as well as its business methods.
EJBXtension
Services component provides the commonly and repeatable functionalities from
Enterprise JavaBeans. Using the services of this component results in a cleaner
and consistent code for various EJB and other client components.
Databases
are the integral part of any enterprise system. J2EE based enterprise system
is no exception. However, most of the J2EE developers do not want to know
where the database resides or what kind (vendor wise) of database they are
dealing with. They just want to get
a connection
to the database to talk to it. Since, JDBC has become standard protocol for
connecting Java and J2EE based applications to relational databases, this
component provides JDBC based services.
Framework
components are presented in the previous section. Now, wee need a way to bootstrap
the framework for business application. The framework makes sure that the
business application should not be burdened by the details of starting the
framework. In fact, business applications will have the framework and its
components readily available through the framework component’s service APIs.
Framework
driver performs the component creation and initialization, determines the
application server it has been deployed to, and makes all its information
available to its client components. The framework driver serves two different
kind of users: developers who want to extend the framework, and developers
who just want to use the framework. Members of the first group are primarily
interested in the underlying implementation of the framework itself, while
those in the second group are just interested in the public interfaces of
the framework.
Framework
driver provides a basic framework interface and abstraction which each and
every framework components will need to extend. This restriction will help
new services to be easily added to the framework.
Building
the framework and its components is not enough for it to be accepted amongst
the developers. We need to provide ease of use for the framework just as any
other packages. The framework and its components can be developed as an independent
Java package and deployed across application servers. JDK 1.2 and above provides
a hook for this purpose – the $JAVA_HOME/ext directory which is auto-inspected
by the Java runtime. This gives us an easy way to make sure that the framework
is located in a consistent location and also the framework is automatically
added to the classpath.
Developers need only to import the classes they require to start using the
framework.
A basic idea of an application framework for J2EE has been discussed. General introduction, component features, services for each of the components have been presented. Some of the design considerations have also been presented in the document. A relatively thorough guideline for exception handling has been discussed with J2EE components in mind. It is hoped that design and implementation of this application framework will help software development teams perform their tasks more easily, cleanly, and consistently.
Ramanand Singh is an Enterprise Java Architect with Nalanda Technology, Inc. He has over 14 years of experience in software industry. His focus has been on architecture, design, and implementation of enterprise applications using Object-Oriented technologies, design patterns, Java technology, CORBA technology, and J2EE technology. Mr. Singh was an invited guest speaker recently at IEEE Computer Society meeting for a presentation entitled “Building n-tier Enterprise Application using J2EE Platform.” He can be reached at rsingh@nalandatech.com.