Bean Coding Guidelines

Here are some coding guidelines for new Able beans. Elements of a Java source file are discussed to encourage reuse of design patterns and styles so new Able beans are similar to the current beans. This is how to code, not what to code; for what to code, see Creating an AbleBean. See Sun's Code Conventions for the Java Programming Language for more general and comprehensive Java coding guidelines.

The following the elements of a Java source file are discussed:

  1. Constructors
  2. Copyright and source protection
  3. Header comment
  4. Data variable names
  5. Exceptions: throwing and handling
  6. Get/Set methods
  7. Javadoc
  8. Main method
  9. National Language Support
  10. Serialization
  11. Synchronization
  12. Tracing and logging

Constructors

(top)

Copyright

There are three main copyright and source protection requirements:

1. Jar/zip protection: a text file in each jar that contains the copyright protection notice. This should be a file named Copyright.txt containing what is called the full protection notice. After the notice all files contained in the jar/zip protected by this notice are supposed to be listed. Our full protection notice is:

Licensed Materials - Property of IBM

Package: com.ibm.able

(C) Copyright IBM Corp. 1999, 2003. All Rights Reserved.

US Government Users Restricted Rights - Use, duplication or
disclosure restricted by GSA ADP Schedule Contract with IBM Corp.

2. Binary/class protection: a long or a short embedded String containing copyright protection. 'Major' classes (the main class in a package, or a class implementing a patent) should have the long form. We defined major as the class com.ibm.able.Able. The long copyright protection notice is the same as the full protection notice above. Licensed Materials - Property of IBM

Package: com.ibm.able

(C) Copyright IBM Corp. 1999, 2003. All Rights Reserved.

US Government Users Restricted Rights - Use, duplication or
disclosure restricted by GSA ADP Schedule Contract with IBM Corp.

Other Able classes use the short protection notice which can be provided as a String or method:

(C) Copyright IBM Corp. 1999, 2003. All Rights Reserved.

In Able this is provided by embedding the following method:

/**
* Determine the copyright of this class.
*
* @return A String containing this class's copyright statement.
* <p>
*/
public static String Copyright() {
   return Able.Copyright;
}

3. Source code protection, in the form of comments in the header section. This varies depending on the kind of file.

Java files (.java) for internal opensource code:

//*********************************************************************
//* Licensed Materials - Property of IBM                              *
//*                                                                   *
//* "Restricted Materials of IBM"                                     *
//*                                                                   *
//* Package: com.ibm.able                                             *
//*                                                                   *
//* (C) Copyright IBM Corp. 1999, 2003. All Rights Reserved.          *
//*                                                                   *
//* US Government Users Restricted Rights - Use, duplication or       *
//* disclosure restricted by GSA ADP Schedule Contract with           *
//* IBM Corp.                                                         *
//*********************************************************************

For reference only, the object-code-only statement is:

//*********************************************************************
//* IBM Confidential                                                  *
//*                                                                   *
//* OCO Source Materials                                              *
//*                                                                   *
//* Package: com.ibm.xxx or product name xxxx-yyy                     *
//*                                                                   *
//* (C) Copyright IBM Corp. year1, year2                              *
//*                                                                   *
//* The source code for this program is not published or              *
//* otherwise divested of its trade secrets, irrespective of          *
//* what has been deposited with the US Copyright Office.             *
//*********************************************************************

Example source code is:

//====================================================================
//
// Licensed Materials - Property of IBM
//
// "Restricted Materials of IBM"
//
// Product: com.ibm.able.examples
//
// (C) Copyright IBM Corp. 2001, 2003 All Rights Reserved.
//
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with
// IBM Corp.
//
//
// DISCLAIMER
// ----------
//
// This material contains programming source code for your consideration.
// These examples have not been thoroughly tested under all conditions.
// IBM, therefore, cannot guarantee or imply reliability, serviceability,
// performance or function of these programs. All programs contained
// herein are provided to you "AS IS". THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
// DISCLAIMED.
//
//====================================================================

 

Properties (.properties) files:

- ===========================================================================
- Licensed Materials - Property of IBM
- "Restricted Materials of IBM"
- Package: com.ibm.able
-
- (C) Copyright IBM Corp. 1999, 2003. All Rights Reserved.
- ===========================================================================

 

HTML (.html or .htm) files:

<!-
 ===========================================================================
 Licensed Materials - Property of IBM
 "Restricted Materials of IBM"
 Package: com.ibm.able

 (C) Copyright IBM Corp. 1999, 2003. All Rights Reserved.
 ===========================================================================
->

(top)

Data variable names

(top)

Exceptions: throwing and handling

The objectives are:

  1. Provide an NLS-enabled message to the user or rules developer via the message logger
  2. Provide a stack trace to the developer or able programmer) via the trace logger
  3. Throw an exception embedding the original exception as the cause.

When wrappering a base Java exception, in many cases we can rely on the exception caught to provide an appropriate NLS-enabled message like this:

catch(IOException theException) {
  throw new AbleException(theException.getLocalizedMessage(),theException);
}

Better is to provide additional context to a base Java exception by supplying your own text message. The message should be retrieved from a message bundle and used as shown:

catch(java.net.MalformedURLException theException) {
  String msg = Able.NlsMsg("Ex_NamingRebind", new Object[] {this.agentName,this.agentHost});
  throw new AbleException(msg, theException);
}

If you handle an exception, you may wish to provide a warning or informational message to the user, and/or provide a stack trace to the developer.

catch(java.net.MalformedURLException theException) {
  String msg = Able.NlsMsg("Ex_NamingRebind", new Object[] {this.agentName,this.agentHost});
  logger.text(Able.MSG_INFO,this,"rmiRebind",msg);
  if (trace.isLogging()) trace.exception(Able.TRC_LOW,this,"rmiRebind",theException);
  lclName = "A default name and host";
}

When creating a new exception which is not based on a Java exception, again the message must be retrieved from a message bundle. Note the stacktrace will be based on the line where the AbleException is constructed.

String msg = Able.NlsMsg("Ex_NamingRebind", new Object[] {this.agentName,this.agentHost});
AbleException exp = new AbleException(msg);
logger.text(Able.MSG_ERROR,this,"rmiRebind",msg);
if (trace.isLogging()) trace.exception(Able.TRC_LOW,this,"rmiRebind",exp);
throw exp;

(top)

Get/Set methods

(top)

Header comment

(top)

Javadoc

A good general source is Sun's How to Write Doc Comments for the Javadoc Tool.

Able conventions are:

Some of the more relevant general guidelines are:

(top)

Main method

(top)

National Language Support

(top)

Serialization

(top)

Synchronization

(top)

Tracing and logging

Able wrappers the Logging for Java utility called JLog. AbleLogger is the interface we chose to use as a JLog wrapper, and AbleTraceLogger is the class that implements that interface. JLog's design suggests, and Able provides and uses, two logging fields in AbleObject:

  1. Message logging, whose output is intended for end users and should be NLS translatable. Levels are Error, Warning, and Informational, and by default message logging is set to the Error level.
    logger.message(Able.MSG_ERROR,this,"methodName","messageBundleKey",new Object[]{"why"});
  2. Trace logging, whose output is intended for developers and need not be NLS translatable. Levels are High, Medium, and Low and by default trace logging is not enabled. To avoid the overhead of creating trace messages when tracing is disabled, test to see if the tracer is logging.
    if (trace.isLogging()) trace.text(Able.TRC_LOW,this,"methodName","A low level trace message");
    Debug-only tracing can be eliminated from production output using the static Able.Debug boolean:
    if (Able.Debug && trace.isLogging()) trace.text(Able.TRC_LOW,this,"methodName","A low level trace message");

Helper methods for starting and stopping loggers, changing levels, adding and removing console and file handlers, and formatting logger output are all provided as static methods in the Able class. The Able class instantiates a static global logger (Able.MessageLog) and a static global trace (Able.TraceLog) objects which are referenced by all classes which extend AbleObject. The local references in AbleObject are logger and trace respectively. In order to debug beans during development, Able provides the ability to switch to bean level tracing to enable individual beans to have their own trace logger object.

Here are some guidelines on what to trace and log:

If you see this message:
LOG0004E No handlers are registered with the logger AbleMessageLog.
You have no message logger started. You either have your preferences set to provide no message logging, or you have not started the Able logging facilities. When the Able.class is loaded, a static initializer starts whatever trace and log facilities are defined in preferences. You can also start these facilities from your api if you wish via::
Able.startMessageAndTraceLogging();

If you see this message:
LOG0004E No handlers are registered with the logger AbleTraceLog.
You have no trace logger started. You either have your preferences set to provide no trace logging, you have not started the Able logging facilities (see description of AbleMessageLog), or you have not prefaced your trace statement with the conditional statement:
if (trace.isLogging()) trace.text(...)

Trace and log levels

We have standardized three levels of logging output for logging and tracing as follows:

  Message logging Trace logging
Low: only the most essential such as errors; no impact to performance Able.MSG_ERROR
Exception message text
Able.TRC_LOW
Exception stack trace
Medium: significant actions and progress; minimal impact to performance Able.MSG_WARNING
Autonomic action taken
Able.TRC_MEDIUM
Configuration parameter changed
High: detailed activities; expect performance degradation
Able.MSG_INFO
Transaction begun or completed, property modified
Able.TRC_HIGH
Method entry or exit, property modified

Tracing in rulesets

AbleRuleset objects always provide their own unique trace logger. Any handlers registered to the static trace logger are shared by the ruleset trace logger.

Applications such as editors may be interested in specific kinds of rule functions, and may provide handlers to the ruleset to be added to the ruleset's trace logger. In addition, ruleset statements themselves may manipulate these application-specific tracing features.

  1. Parse handler, for trace statements which need not be translated and are of interest primarily to the developers of the Able parsing routines. Parse output is considered high level. Parse exception messages are passed to the caller, and not logged by the parser itself.
  2. Inference handler, for display of intermediate inferencing steps as well as final results. Inference statements are to be translated and can be high, medium, or low level. Ruleset developers are primary users of inference output.
  3. Base handler, for trace statements which show activity and progression through the ruleset API. Level may be high, medium, or low. Those developers using the various ruleset APIs to construct rulesets programmatically will be interested in base trace output. Base trace is not translated.
 Task Application providing handlers or using default console handler Ruleset
Start inference tracing* myRuleset.setInferenceTraceHandler(myHandler,Able.TRC_LOW);
myRuleset.setInferenceTraceLevel(ARL.LOW);
this.setInferenceTraceLevel(ARL.LOW);
Change trace level myRuleset.setInferenceTraceHandler(myHandler,Able.TRC_HIGH);
myRuleset.setInferenceTraceLevel(ARL.HIGH);
this.setInferenceTraceLevel(ARL.HIGH);
Stop inference tracing myRuleset.setInferenceTraceHandler(myHandlerAble.TRC_NONE);
myRuleset.setInferenceTraceLevel(ARL.NONE);
this.setInferenceTraceLevel(ARL.NONE);
Check inference level myRuleset.isInferenceTraceLow(); this.isInferenceTraceLow();
Send inference message if (myRuleset.isInferenceTraceLow()) {
myTrace.message(this, "methodname", Able.TRC_LOW, "Resource_key",new Object[]{parm1, parm2});
}
trace("We are nearly here");
traceFormat("We are nearly {0}","here");

(top)