by Dan Stieglitz
Version 1.0
Thursday June 3, 2004
Read Me First
Obtaining Prob-lo-Matic
Project Structure
Prepackaged Problems and Handlers
Example: Adding E-mail Notification to Your Application
Example: Implementing Database Failover in Your Application
Writing Your Own Problems and Handlers
This document details how to use Prob-lo-Matic from a low-level technical perspective. It assumes the reader already understands Prob-lo-Matic from a basic functional perspective and therefore does not remind the reader as to the purpose and architecture of the system. If you don ‚ Ä ôt know what Prob-lo-Matic is, you should first read:
http://www.stieglitech.com/chain.pdf
Currently, the only way to download Prob-lo-Matic is through the CVS source repository at sourceforge. The source code for Prob-lo-Matic can be obtained through anonymous CVS by issuing the following command from a shell:
cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/problomatic checkout problomatic
This will create a subdirectory called ‚ Ä òproblomatic ‚ Ä ô under the current directory containing the contents of the project. An alternative method is to use a CVS client to access the repository at sourceforge.
For more information about accessing sourceforge ‚ Ä ôs CVS repositories, see:
http://sourceforge.net/docman/display_doc.php?docid=14033&group_id=1
The project contains an Ant build.xml file in the top level. The subdirectories are organized as follows
Dir |
Contents |
build_lib |
Contains libraries required to build (but not execute) the software. These files are not distributed. |
dist |
Contains distribtions (executables and configuration files) |
legal |
Contains licenses and other files that are required to be distributed with the source code. |
lib |
Contains libraries required to run the software. These are included in the distribution archive |
misc |
Contains miscellaneous files |
src |
The root of the source tree |
temp |
Contains temporary files and directories created during build process |
After downloading, you ‚ Ä ôll probably want to run the examples to see some action. The examples are found in the examples package
$PROJECT_HOME/src/java/examples
Building the project with ant will produce class files in
$PROJECT_HOME/temp/classes/examples
There are two examples that demonstrate the basic functionality of Prob-lo-Matic. The first, examples.Configuration, shows how to configure Prob-lo-Matic both programmatically and through an XML file using the XMLConfigurator class. This example can be executed by entering
export PATH_TO_PROPERTIES=$PROJECT_HOME/misc/handlerproperties
java -cp ../../build_lib/log4j-1.2.7.jar:../../dist/bin/Prob-lo-Matic.jar:$PATH_TO_PROPERTIES examples.Configuration
at the shell prompt. Note that on the classpath there is a reference to a directory containing properties files for the handlers. Each handler has an associated properties file called [HandlerClassName].properties that specifies some variables for the handler (more on this later).
The second example, examples.DatabaseFailover, shows how Prob-lo-Matic can be used to retry failed database connections. It should be configured to work in your environment, and an appropriate database driver must be put on the classpath. After modyifing the source code, enter
java -cp ../../build_lib/log4j-1.2.7.jar:../../dist/bin/Prob-lo-Matic.jar:$PATH_TO_JDBC_DRIVER examples.DatabaseFailover
Prob-lo-Matic provides out of the box a default implementation of the Problem interface. The class
com.stieglitech.problematic.problems.GenericThrowableProblem
is a simple Problem that takes in its constructor a source Object and a Throwable. It ‚ Ä ôs specifically designed to be used in the following situation:
try {
// some work
} catch (Exception anException) {
GenericThrowableProblem problem = new
GenericThrowableProblem(this,anException);
Problomatic.handleProblem(problem);
}
GenericThrowableProblem is designed to be extended so specific functionality can be implemented. The examples section contains a class called
examples.problems.SampleDatabaseProblem
that extends GenericThrowableProblem (but doesn ‚ Ä ôt really add anything). The simple fact that a subclass is created allows for the creation of a handler chain specific to this problem.
There are a number of prepackaged ProblemHandler implementations in the com.Stieglitech.problematic.problems package. Each class expects a properties file of the name [class-name].properties to be available on the classpath (e.g., SystemPrintlnHandler.properties) These files can be found in the
$PROJECT_HOME/misc/handlerproperties
directory, which must be on the classpath when the system is run. Alternatively, you can put these files in some other directory already on your classpath.
The available handlers are:
Handler com.stieglitech.problematic. |
Details |
SystemPrintlnHandler |
Dumps the contents of the Problem to System.out. Essentially dumps the result of the toString() method on the Problem implementation |
EmailNotificationHandler |
Uses the JavaMail API (packaged with project) to send an e-mail message containing the problem details when a problem occurs. Use the EmailNotificationHandler.properties file to specify mail server and related information. |
XMLPersistenceHandler |
Persists the details of a particular Problem in XML format. The filename is generated by the system and the directory is specified in the XMLPersistenceHandler.properties file. |
XSLTransformationHandler |
Applies an XSL stylesheet to an XML file on disk |
BrowserLaunchHandler |
Launches the system ‚ Ä ôs default web browser and points it to the value of the URL parameter contained in the Problem. |
A useful production tool is to have e-mail notifications sent to inboxes, pagers, etc. when serious problems occur. Prob-lo-Matic is suited to provide this functionality, and this project contains a prepackaged handler suited for this purpose.
Installation
A single handler called EmailNotificationHandler is provided that uses the JavaMail API to send messages through a mail server to a predetermined list of recipients. The details required to access the mail server can be found in the EmailNotificationHandler.properties file in the $PROJECT_HOME/misc/handlerproperties directory. They are:
Property |
Details |
emailnotificationhandler.smtp.host |
Hostname or IP address of the SMTP server |
emailnotificationhandler.smtp.username |
Username required to access the server |
emailnotificationhandler.smtp.password |
Password required to access the server |
emailnotificationhandler.subject |
Subject line of the email message |
emailnotificationhandler.recipients |
A comma delimited list of recipients that the e-mail will be sent to |
emailnotificationhandler.sender |
Name to be put in the ‚ Ä òfrom ‚ Ä ô field |
To use the EmailNotificationHandler, simply edit the properties file to work with your mail server and include the handler in your Prob-lo-Matic configuration, either programmatically or using the XMLConfigurator class and an XML file. See the examples.Configuration source file for more detail.
Database failover is a critical part of any application that demands high reliability. The ability to automatically connect to a backup database when a problem occurs is a desirable and oftentimes required part of many enterprise applications. Prob-lo-Matic is suited to deliver a standard and flexible way to implement database failover.
Example Architecture
This example is by no means the only or best way to handle database failover, but it is suitable to show how the framework can be used. The idea is to design the class doing the database work in such a way as to separate the connection management from the actual work. In our example class, examples.DatabaseFailover, this is shown by the methods connectToDatabase(), doDatabaseWork() and closeConnection(). In our example, the Connection is an instance variable (which may be undesirable in some architectures).
The method responsible for obtaining the connection will have a block similar to connectToDatabase() in our example:
private void connectToDatabase() {
try {
// make connection
Class.forName(DRIVER_CLASS);
setConnection(
DriverManager.getConnection(
PRIMARY_DB_URL,DB_USER,DB_PASS));
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
SampleDatabaseProblem prob =
new SampleDatabaseProblem(this, e);
Problomatic.handleProblem(prob);
}
}
DatabaseRetryHandler
To implement failover, we insert a DatabaseRetryHandler in the Prob-lo-Matic chain. The job of the Handler is to make a connection to the secondary database and set this connection on the class doing the work (this is the reason for the Connection instance variable in our example). When the chain finishes executing, control is returned to the original class and it should have a valid connection. See the examples.handlers.SampleDatabaseRetryHandler for more details.
The meaty part of the DatabaseRetryHandler is repeated here:
public synchronized
void handleProblem(Problem aProblem)
{
if (aProblem instanceof
SampleDatabaseProblem) {
SampleDatabaseProblem
dbProb = (SampleDatabaseProblem) aProblem;
DatabaseFailover
source = (DatabaseFailover) dbProb.getSource();
connectToSecondaryDatabase(dbProb,
source);
}
}
Simply put, the handler interrogates the Problem passed in. If it ‚ Ä ôs a SampleDatabaseProblem, the handler retrieves the source class, attempts to make a secondary connection to the failover database, and through a callback sets this new connection on the source class. When the chain finishes executing, the source class has a valid connection and is able to complete the work.
Configuration
<define-chain
id="developmentChain"
problem-class="examples.problems.SampleDatabaseProblem">
<chain-link
handler="examples.handlers.SampleDatabaseRetryHandler"/>
<chain-link
handler="com.stieglitech.problomatic.handlers.SystemPrintlnHandler"/>
<chain-link
handler="com.stieglitech.problomatic.handlers.XMLPersistenceHandler"/>
<chain-link
handler="com.stieglitech.problomatic.handlers.XSLTransformationHandler"/>
<chain-link
handler="com.stieglitech.problomatic.handlers.BrowserLaunchHandler"/>
</define-chain>
Above is an excerpt from the problomatic.xml file distributed with Prob-lo-Matic. This configuration is loaded when running the examples.DatabaseFailover example. It illustrates how to configure the SampleDatabaseRetryHandler, and it includes some additional handlers distributed with the project. Specifically, the last 3 handlers persist problem information as XML, perform an XSL transformation to HTML, and then launch the system ‚ Ä ôs default web browser to examine the resulting file in a more human-readable format.
Prob-lo-Matic is designed to be customized to meet individual user ‚ Ä ôs needs. This section explains how to create custom problems and additionally some possible (but as yet unimplemented) handlers.
To create a custom Problem, create a Java class that extends the
com.stieglitech.problematic.problems.AbstractProblem
class. This abstract class extends AbstractAttributableObject (which encapsulates attribute handling) and provides a rudimentary toString() method.
Any additional functionality can exist in your custom subclass, including strong typing of attributes, web or system access, etc. AbstractProblem contains no abstract methods; it is abstract to force the creation of named subclasses, as Problomatic keys handler chains by problem class name.
Creating Handlers requires creating classes that implement the
com.stieglitech.problematic.ProblemHandler
interface. This interface defines two methods, init() and handleProblem(). An abstract subclass exists that defines the properties instance variable for storing handler properties and a method to retrieve named properties safely (meaning return the value or throw a meaningful Exception rather than experience a NullPointerException). This class is called
com.stieglitech.problematic.handlers.AbstractProblemHandler
Experimentation with the system is encouraged. Potential handlers include:
Please e-mail any and all suggestions to dan@stieglitech.com