Prob-lo-Matic Tutorial

 

by Dan Stieglitz

Version 1.0

Thursday June 3, 2004

 

 

Table of Contents

 

Read Me First

Obtaining Prob-lo-Matic

Project Structure

Running the Examples

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

 

 

Read Me First

 

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

 

 

Obtaining Prob-lo-Matic

 

Downloading via Anonymous CVS

 

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

 

 

Project Structure

 

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

 

 

 

Running the Examples

 

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

 

 

 

Prepackaged Problems and Handlers

 

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.

 

 

Example: Adding E-mail Notification to Your Application

 

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.

 

 

Example: Implementing Database Failover in Your Application

 

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.

 

 

Writing Your Own Problems and Handlers

 

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

 

Experimenting with Prob-lo-Matic

 

Experimentation with the system is encouraged. Potential handlers include:

 

 

Please e-mail any and all suggestions to dan@stieglitech.com

 

 

End Tutorial