///Using Aspects to Autonomic-Enable Legacy Applications

Using Aspects to Autonomic-Enable Legacy Applications

Using Aspects to autonomic-enable legacy applications

Learn how to use Aspects to generate Common Base Events in any legacy Java application, without modifying the original application source. This article shows you how and also provides an example framework that can be used with your applications today.

Introduction

As a software solution grows in complexity, it becomes more and more difficult to determine the root cause of any non-trivial problem situation and to address it. The first major step toward a self-healing solution is the ability to correlate and analyze heterogeneous data from all components acting in a solution. The Generic Log Adapter and the Log and Trace Analyzer for Autonomic Computing (see Resources for download information) provide a toolset that enables the viewing, analysis, and correlation of log files generated by any application, including IBM® WebSphere® Application Server, IBM HTTP Server, IBM DB2® Universal Database, and Apache HTTP Server. This correlation is possible through the conversion to Common Base Events. Common Base Events are an XML-based event representation that has been submitted to the Organization for the Advancement of Structured Information Standards (OASIS) by IBM for standardization.

Unfortunately, a software solution often depends on components written before an autonomic computing environment was created or even considered. These components might log only a subset of information that would now be useful for debugging complex error situations, or do so in a manner that does not allow for real-time analysis.

In this article, I present a method of generating Common Base Events natively by leveraging Aspect-oriented programming (AOP). I also provide and describe an Aspect framework that can be customized or extended for your software environment. I discuss how to tie these newly generated Common Base Events into a common logging-enabled application such as the Log and Trace Analyzer for Autonomic Computing.

Example legacy application

I’ll start with a very simple application to demonstrate legacy autonomic enablement. The application used is a variation on the “Hello World” code, which contains an encapsulated variable and makes several method calls in its execution.

Listing 1. HelloWorld.java

package com.mycompany.myapp;


public class HelloWorld {
private String helloWorldString = "Hello World";

public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
helloWorld.run();
}

public void run() {
String helloWorldString = getHelloWorldString();
System.out.println(helloWorldString);
setHelloWorldString("Goodbye World");
helloWorldString = getHelloWorldString();
System.out.println(helloWorldString);
}

public String getHelloWorldString() {
return helloWorldString;
}

public void setHelloWorldString(String helloWorldString) {
this.helloWorldString = helloWorldString;
}
}

This application contains one source directory and is built using Ant, as shown in Listing 2.

Listing 2. Original Ant Build Script

...

<javac srcdir="src/" destdir="build">
<include name="com/**/*"/>
</javac>
...

Incorporating Aspects

Although there are currently several different flavors of AOP available for Java™ applications, in this article I use AspectJ™, which is available from eclipse.org. (See Resources for download information.) From the AspectJ FAQ:

“AspectJ is a simple and practical extension to the Java programming language that adds to Java aspect-oriented programming (AOP) capabilities. AOP allows developers to reap the benefits of modularity for concerns that cut across the natural units of modularity. In object-oriented programs like Java, the natural unit of modularity is the class. In AspectJ, aspects modularize concerns that affect more than one class.”

After you’ve decided which internal actions of the legacy application are interesting, you can create Aspect pointcuts. Generally, an Aspect pointcut can define most Java execution points, such as method entry and exit, object creation or modification, and when Exceptions are thrown. After you’ve defined a pointcut, a set of arbitrary code can be set to be executed before, after, or instead of the action the pointcut defines. Conceptually, this approach can be thought of as weaving in functionality at generically described locations throughout a defined application. Aspects can be abstract and they can use inheritance to subclass, just like Java objects.

To compile a Java program that uses Aspects:

1. Download the AspectJ package from eclipse (see Resources).

2. Place the AspectJ Java Archive (JAR) files in your system or build environment classpath.

3. Modify your build environment, as shown in Listing 3, to include required AspectJ properties.

4. Replace instances of the javac task with the iajc task.

Listing 3. Modified Ant Build Script

<!-- Properties for aspect building -->

<!-- build.compiler value to pick up our CompilerAdapter for javac -->

<property name="ajc.adapter"
value="org.aspectj.tools.ant.taskdefs.Ajc11CompilerAdapter"/>
<!-- required libraries - install or predefine -->
<property name="aspectjrt.jar" location="lib/aspectjrt.jar"/>
<property name="aspectjtools.jar" location="lib/aspectjtools.jar"/>

<!-- checking required libraries -->
<available file="${aspectjtools.jar}" property="aspectjtools.jar.available"/>
<available file="${aspectjrt.jar}" property="aspectjrt.jar.available"/>

<!-- sets name of new task to iajc, old task to ajc -->
<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
<classpath>
<pathelement path="${aspectjtools.jar}"/>
</classpath>
</taskdef>

...

<iajc srcdir="src" destdir="build">
<include name="com/**/*"/>
</iajc>

...

If you use eclipse as your IDE, all you need to do is install the AJDT plug-in and add an AspectJ nature to your project.

Now that the ant build.xml has been set up to compile Aspect code, you are ready to include the Aspect framework. Add the framework code to the source directory of the project and, if necessary, modify the build.xml file to include the Aspect source in the build path.

An example Aspect framework to generate Common Base Events

To simplify the autonomic enablement of legacy applications, I have created a set of abstract Aspects and utility classes that can be extended to handle most possible event generation situations. (See Resources below for the download link.) Use this abstract Aspect layout to minimize what you have to define when you’re ready to include this in your application. Your Aspect would at most contain two pointcut definitions (which simply define the package or call structure the Aspect is applied against) and a method that returns a string representation of the application name.

The top-level Aspect for this example framework is CommonBase.aj, and is used to define abstract scope pointcuts and convert certain Aspect actions into methods that can be overriden. Examples of these action methods are enterMethodAction and exitMethodAction, and all are defined to be empty methods. These empty methods ensure that a subclassing Aspect needs only to override the methods that apply in its intended function. There are three abstract items that every concrete child Aspect (or parent below CommonBase) must have defined: classScope(), methodScope(), and getApplicationName().

Figure 1. Aspect framework UML

classScope()

The classScope pointcut defines the set of classes that a child Aspect is interested in. Generally, this is just the package of your application and should be used to define all of the points of interest in code that you have written. An example of the classScope pointcut is:

Listing 4. classScope pointcut

public pointcut classScope() : within(com.mycompany.myapp..*);

methodScope()

The methodScope pointcut defines any methods that your classes use that you would like to act upon. Generally, these are items like loggers or database calls. An example of the methodScope pointcut is:

Listing 5. methodScope pointcut

public pointcut methodScope() : call(* PrintStream.print*(..)) &&

classScope();

getApplicationName()

The getApplicationName method simply returns a string to be used in the resultant Common Base Event, which defines the application name where the event was generated from.

How to use and extend the example Aspect framework

When examining the set of correlated logs for a particular software solution, it might be very useful to understand what exactly is being executed during points of interest. A point of interest in this case might be an application crash or inappropriately high usage of a CPU. The CommonTraceLogger Aspect implements most of the action events defined in CommonBase and simply invokes the CommonEventHandler helper class to generate Common Base Events. To make your application generate these Common Base Event trace events, simply create a concrete Aspect that subclasses CommonTraceLogger, as shown in Listing 6 and recompile the application.

Listing 6. Concrete Aspect that subclasses CommonTraceLogger

import com.ibm.developerworks.autonomicenablement.aspect.CommonTraceLogger;


public aspect MyAppTraceLogger extends CommonTraceLogger {
public pointcut classScope() : within(com.mycompany.myapp..*);

public String getApplicationName() {
return "My Application";
}
}

Another point of interest that might exist is simply what the original application used to log or debug. In the context of the example application, no logs are ever written; all information is simply printed to the screen using System.out. One way to capture this information is to create a subclass of the CommonWrappingLogger Aspect that inspects every PrintStream.print command, ensures it is the System.out PrintStream, and then generates a Common Base Event. The implementation of this is shown in Listing 7.

Listing 7. Capturing System.out calls

package com.ibm.developerworks.autonomicenablement.aspect;


import java.io.PrintStream;
import org.aspectj.lang.JoinPoint;

public abstract aspect SystemOutWrappingLogger extends CommonWrappingLogger {
public pointcut methodScope() : call(* PrintStream.print*(..)) &&
classScope();

public void beforeMethodCalledAction(JoinPoint joinPoint) {
if (joinPoint.getTarget() == System.out) {
super.beforeMethodCalledAction(joinPoint);
}
}
}

After this new Aspect has been created, simply create another concrete Aspect as shown in Listing 8 and recompile the application.

Listing 8. Concrete Aspect that subclasses SystemOutWrappingLogger

import com.ibm.developerworks.autonomicenablement.aspect.SystemOutWrappingLogger;


public aspect MyAppSystemOutWrappingLogger extends SystemOutWrappingLogger {
public pointcut classScope() : within(com.mycompany.myapp..*);

public String getApplicationName() {
return "My Application";
}
}

Next steps

Now that you have an infrastructure that allows for the simple creation of Common Base Events in your legacy applications, you can leverage this new information in the overall autonomic computing environment. For simplicity, the presented framework uses the CommonEventHandler class to generate Common Base Events and to write them to an output log. The generated log can then be imported into an application such as the Log and Trace Analyzer for Autonomic Computing to correlate log events, or into another common logging-enabled application.

Resources

• Download AspectJ and AJDT from eclipse.org.

• Download the Generic Log Adapter and the Log and Trace Analyzer from the IBM Autonomic Computing Toolkit.

• The Autonomic computing technology zone provides more information on the Autonomic Computing Toolkit components used in this article.

• ” Standardize messages with the Common Base Event model” (developerWorks, February 2004) describes the Common Base Event format in detail.

Understanding the Common Base Events Specification V1.0.1 gives the official specification for the Common Base Event format.

• ” Generate Common Base Events from within a Java application” (developerWorks, February 2005) explains in detail how the example code creates native Common Base Even.

2010-05-26T11:21:22+00:00 May 13th, 2005|Java|0 Comments

About the Author:

Brian Temple is a Software Engineer for IBM in the Small to Medium Businesses Emerging Technologies group. He is currently responsible for database functionality within the Console for IBM Express Runtime, a portlet environment which provides integrated administration of IBM express applications.

Leave A Comment