Chapter 7. Developer's guide

Table of Contents

Introduction
Coding conventions
Using logging
Writing documentation
Releasing OpenJMX

Introduction

Simone Bordet

Revision History
Revision $Revision: 1.1 $$Date: 2002/02/14 15:08:46 $

This chapter aims to give some suggestion to developers of OpenJMX, in order to have some common base to start from. Furthermore it gives also some indication on how to create and distribute a new OpenJMX release.

Coding conventions

The base to start from are the coding conventions for Java, see here.
We require as additional convention the one-line one-brace style:

Example 7.1. One-line one-brace style

	
public class Main { // bad
	private String name;
	public Main(String n) { // bad
		if (n != null) { // bad
			name = n;
		}
	}
}

public class Main
{ // good
	private String name;
	public Main(String n)
	{ // good
		if (n != null)
		{ // good
			name = n;
		}
	}
}
	
	

Using logging

It is good practice to insert logging statements in the code, to help debugging and to record information about what the program is doing.

OpenJMX has a built-in logging system based on the openjmx.log.Logger class, whose usage is very similar to the Category class of the Log4J project.

Class Logger has six methods that logs at a different priority; from the lowest priority to the highest they are:

  • public void trace(...);

  • public void debug(...);

  • public void info(...);

  • public void warn(...);

  • public void error(...);

  • public void fatal(...);

They all have two overloaded version, one that takes one argument of type Java.lang.Object, and one that takes two arguments of type Java.lang.Object and java.lang.Throwable.

Class Logger has another useful method that returns the priority enabled for that instance of Logger:

  • public boolean isEnabledFor(...);

Using correctly this method will save the run-time cost associated with the concatenation of String objects:

Example 7.2. Saving run-time cost of String concatenation

	
Logger logger = ...;
if (logger.isEnabledFor(Logger.TRACE))
{
	logger.trace("Result is: " + result + " on item: " + item + " for process: " + process);
}
	
	

Saving the time associated with the creation of temporary objects used only for the logging statement is mandatory when the priority is trace, debug or info, to avoid unnecessary drop of performance.

Another useful way to avoid creation of temporary String objects is to use the StringBuffer class, following this example:

Example 7.3. Saving run-time cost of String concatenation with StringBuffer

	
Logger logger = ...;
if (logger.isEnabledFor(Logger.TRACE))
{
	StringBuffer message = new StringBuffer("Result is: ").append(result).append(" on item: ").append(" for process: ").append(process);
	logger.trace(message);
}
	
	

This version, when the logging is performed because the priority is enabled for the logger instance, is more efficient than the previous example that used String concatenation.

How do you obtain an instance of the Logger class ? You must use the openjmx.log.Log class, this way:

Example 7.4. Retrieving a Logger instance

			
Logger logger = Log.getLogger("MyCategory");
			
			

Every logger instance is associated with a category, i.e. a string that normally represent a correlated group of logging requests.

Choosing the right priority

Choosing the right priority is important, and here there are few guidelines:

  • Use Logger.trace to log execution flow. Always surround a log with trace priority with a call to Logger.isEnabledFor.

  • Use Logger.debug to log variables values. Always surround a log with debug priority with a call to Logger.isEnabledFor.

  • Use Logger.info to log information that can be of interest for the user. For every public method there should be at least one log with info priority. Always surround a log with info priority with a call to Logger.isEnabledFor.

  • Use Logger.warn to log recoverable errors that in normal situations should not happen. The warn priority is the default priority for OpenJMX.

  • Use Logger.error to log exceptions. Typically, log with error priority are inside catch blocks, just before rethrowing:

    Example 7.5. Logs with error priority

    	
    Logger logger = ...;
    try
    {
    	thisMethodThrows();
    }
    catch (Exception x)
    {
    	logger.error("Exception happened: ", x);
    	throw x;
    }
    	
    	

  • Use Logger.fatal(...); to log fatal errors that will force the JVM to terminate. Typically log with fatal priority are inside catch blocks, just before calling System.exit:

    Example 7.6. Logs with fatal priority

    	
    Logger logger = ...;
    try
    {
    	Class.forName("java.lang.Object");
    }
    catch (ClassNotFoundException x)
    {
    	logger.fatal("Can't find core classes", x);
    	System.exit(1);
    }
    	
    	

    However, it is mandatory that in the OpenJMX code System.exit is never called.

Writing documentation

The documentation that comes with OpenJMX is written using DocBook. It is very easy to use DocBook, and an on-line manual is available here.

Generally, the layout is defined in the file index.xml. All other files are DocBook sections belonging to a chapter, also defined in index.xml.

Every section must contain a sectioninfo with the information about the authors and revision history. It is mandatory that every author that adds a paragraph to the section adds him/herself to the list of authors, and it is mandatory that the tags revnumber and date contains the CVS keywords $Revision$ and $Date$ respectively. This ensures that every section will be automatically updated by CVS on every commit, thus allowing the reader to immediately know how old is the document.

Releasing OpenJMX

The following steps are required for a new release of OpenJMX:

  • Fresh checkout from CVS. Do NOT update, checkout to a new directory the whole CVS
  • Add to lib directory all the optional libraries
  • Build the code and run the test suite. All tests must pass
  • Build the distribution kit
  • Check that the distribution kit contains all the jars, the sources and licensing information (also for third party software used)
  • Tag CVS with the suitable tag
  • Upload the new kit to SourceForge, creating a new release version
  • Update the Change Notes tracker in SourceForge
  • Submit a new News in SourceForge
  • Submit a new News in FreshMeat