ESD Software Exceptions: Programmer's Guide


This page describes the definition, use, and logging of ESD Software Exceptions.  ESD Software Exceptions provide language-independent exception Definition, Handling, and Logging.  It is an object-oriented, corba-based system for use by C++ and Java programs.  It is not part of AIDA, but AIDA uses it.

The ESD Software Exceptions System logs an exception by sending log data through the CORBA Event service and logging it into CMLOG.  For instructions on starting the Event Service and related processes, see the Err System Administration Guide.

Table of Contents

Overall Architecture Language APIs
How to define new ESD Exceptions Guidelines for using exceptions



Overall Architecture

The architecture of the exception handling and logging system is described in "ESD Software Exceptions: Definition, Handling and Logging Requirements and Design Document". In short, the ESD Software Exceptions System:
  • Provides a way to define exceptions in a common IDL file.
  • Provides a language-independent way for Java and C++ programs throw, catch, and log those exceptions.


  •  DATA FLOW DIAGRAM

    The ESD Software Exception Application Programming Interface (API) that is used by Java and C++ programs is encapsulated in a class called Err. The Err class method called Err.log() is used by programmers to log exceptions into CMLOG via the CORBA Event service. The way the system is designed it is relatively easy to to replace CMLOG with some other error logger in the future.

    Language APIs

    Java API

    There is an Example/Test program for logging exceptions here: $CD_PKG/err/test/SaLogTest.java. It is a useful programming example, but you should also be aware of the guidelines and details on this web page.

    JAVADOC

    Import statements

    Two packages are required for the Java exceptions API, except, and err. err defines an API class Err, which you will use to log exceptions. First import the following packages:
    import edu.stanford.slac.except.*;  // exceptions are kept here 
    import edu.stanford.slac.err.*;     // exception logging class Err.class def

    Err API instantiation

    Exceptions are logged through the Err class. One instance of the Err class must be available to log an exception, so somewhere in your code you must instantiate an Err object, and it must be in scope wherever you want to use it. It is instantiated giving a free format string which describes the standalone program which is issuing the errors (for instance the name of your program):
            Err err = new Err("AIDA Magnet Server");   // Instantiate with your facility name.

    Throw/Catch and Logging

    Since ESD exceptions are subclassed from Java Throwable, they are thrown and caught just as are any other Java exceptions. So, to throw an ESD exception, simply throw one of the exceptions defined in edu.stanford.slac.except. To log the exception, call Err.log() giving the exception, plus some supplementary information:
            try {
                    ...
                    throw new NoDataSourceException("for LB60:DCCT:SUNY");
            } 
            catch (Exception ex) {
                    err.log(ex, "when attempting to acquire the LER current" );  
            }
    In that case, the text that gets logged into CMLOG looks like this:
    "NoDataSourceException for LB60:DCCT:SUNY when attempting to acquire the LER current"

    Alternative pattern

    Err.log returns an exception, so you can log and throw an exception in one statement like this:
           throw err.log(new NoDataSourceException("for LB60:DCCT:SUNY"), " when starting ca service");
    In this case, you might take some different action in the catch block; perhaps additionally logging a different exception appropriate to the higher level of abstraction of the catch block.

    However, if you want to throw back to a calling method, then you must perform a narrowing cast of the return value of Err.log to the exact exception you are returning. That necessary because Err.log returns Throwable or Exception.
           static int myFunc() throws NoDataSourceException
           {
             throw (NoDataSourceException)err.log
               (new NoDataSourceException("for LB60:DCCT:SUNY")," when starting ca service");
           }

    Logging Only Text

    If you would like to log some text that is not specifically associated with an error condition, a special "no error" exception has been defined in except.idl, called TextOnly. This is like err_text() on the SLC system.
            TextOnly ex = new TextOnly("TEXT GOES HERE");
            err.log(ex, "when attempting to acquire LER current");
    Additionally, Err.log() has been overloaded with a no-exception signature for logging just text:
            err.log("TEXT GOES HERE");

     

    A simple Java demo and test program

    See the Err System Admin Guide for the Example/Test program called SaLogTest.java. It contains several programming examples.

     

    Guidelines for Java programs

    A logged exception consists of three strings which are concatenated to form the logged message text:

        EXCEPTION_NAME   +  REASON STRING  SUPPLEMENTAL STRING

    new NoDataSourceException("for LB60:DCCT:SUNY");
    Together, These three strings provide context information and a poor-man's form of exception chaining.  Using the example strings above, the logged message text would be:
    "NoDataSourceException for LB60:DCCT:SUNY when attempting to acquire the LER current"

     

    C++ API

    There is an Example/Test program for logging exceptions here: $CD_PKG/err/test/Tdriver.cc. It is a useful example, but you should also be aware of the guidelines and details on this web page

    Include statements

    Two subsystems are required for logging ESD exceptions in C++, except and err. err defines the API class.  except defines the exceptions.  First, include the following header files:
            #include "except.h"    // ESD exceptions are kept here.  Feel free to add new ones.
            #include "err.h"       // ESD exception logging class err is kept here.

    Err API instantiation

    Exceptions are logged through the Err API class. One instance of the Err class must be available to log an exception, so somewhere in your code you must instantiate an Err object, and it must be in scope wherever you want to use it. It is instantiated giving a free format string which describes the standalone program which is issuing the errors (for instance the name of your program):
            Err err("AIDA Magnet Server");     // Instantiate with your facility name

    Throw/Catch and Logging

    To throw an ESD exception, do the following.  Remember, there is no "Reason" string supplied to the exception when we instantiate in C++ like there is is Java.  So, to throw an exception, simply throw one of the exceptions defined in "except". To log an exception, call Err.log() giving the exception plus some supplementary information.
            try {
                 throw except::MissingResourceException();
            }
            catch (CORBA::Exception ex) { 
                  ...            
                 // Log the exception with 'Reason and Supplemental' string).
                 err.log(ex, "for QUAD:LI01 while moving magnet"); 
            }
    In that case, the text that gets logged into CMLOG looks like this
    "except::MissingResourceException for QUAD:LI01 while moving magnet"

    Logging Only Text


    In C++, your last catch clause often looks like catch (...). If you use this form of catch catch statement, you can not log the exception because you don't have an instance of it (or a reference to it). So, the best you can do is log some text message.

            catch (...) {
                 err.log("This is a text-only message.");   
            }

    Alternate Pattern

    Err.log returns an exception.  So, you can log and throw an exception in one statement like this:
            throw (&err.log(except::NoDataSourceException(), "for LB60:DCCT:SUNY while doing trim"));
    This is how you log some text only (not specifically an exception).  This is like err_text() on the SLC system.
            err.log("This is a text-only messages log text");

     

    The Err class does it's own ORB_init() call. Is it a problem if your application does one too?

    The case I'm talking about is where you're writing an application that does it's own ORB_init() call and it also calls the Err class, which does an ORB_init() call itself. The call you make to ORB_init could be done by you explicitly, or could be done by some utility routine you call which does it on your behalf.

    This is not a problem if you do things right. ORB_init() implements the singleton design pattern. So, if you call ORB_init() in your applicaition first, and then, call the Err constructor, Err will be using the ORB that you created in your first call. That's fine. You just need to make sure you started your ORB with the correct event service properties so that Err can connect to the Event Service to which it sends messages. One way to accomplish this is to support starting your application with this argument:
    -ORBconfig /afs/slac.stanford.edu/package/aida/slaconly/errEvent.conf

    That way, the correct Event service properties are read in from that file. If you're perfer to use another way of setting properties, just look inside that file to see what you need to set.

    I tested and implemented such an application called dpTestHistServer.cc.

     

    A simple C++ demo and test program

    You can run this program to test that the Error logging system is working. You can also look at how exceptions are thrown and logged. The source, makefile, and the executable are all in the same directory. You can run it from any AFS unix node (assuming you have the environment set up). Here's how you run it.
            cd $CD_PKG/err/test
            Tdriver

     

    Guidelines for C++ programs

    How to Define New ESD Exceptions

    This section describes how to add new ESD exception definitions and how to do the 'make' on Solaris.

    ESD exceptions are defined in the except.idlfile:

            $CD_SOFT/ref/package/except/idl/except.idl

    To add new Exceptions

    First, Checkout the except package into your development directory:
            cd ~/dev/test
            cvs checkout package/except

    Then, use your favorite editor add new exceptions to that file following
    the format used by all other exceptions in the file.

            cd package/except/idl
            edit except.idl here.


    Then  'make' the except package in your development directory like this:
            cd  ~/dev/test/package/except/common/script 
            gmake -f Makefile.sun4
    Then, test the java classes and c++ library just created by changing your CLASSPATH and LD_LIBRARY_PATH to point to the files you just created in your development directory. Run some test program you create to test the exceptions.

    After you are satisfied with your changes to except.idl, CVS commit your except.idl back to CVS and clean up your development area like this:
            cd ~/dev/test/package/except/idl
            cvs commit
     
    Then, Make the production except package like this and you're done:
            addUserRefWrite
    cd  $CD_SOFT/ref/package/except/common/script
            gmake -f Makefile.sun4
    removeUserRefWrite

    The new exceptions are now available for you and the rest of ESD to use. Don't forget to remove your development directory from your CLASSPATH and LD_LIBRARY_PATH.
            cd ~/dev/test
            cvs release package/except
    rm -fr package

     

    Exceptions Guidelines

    This section provides guidelines that apply to both C++ and Java. Guidelines are provided above for language-specific issues.

    General Exception Guidelines

    ESD Exception Guidelines



    [Aida Home Page][SLAC
    Controls Software Group]
    [ SLAC Home Page]

    Author:  Ron MacKenzie, 03-Jul-2002
    Modified by:
    Ron MacKenzie,

    13-Aug-2002 Added C++ guidelines

    Ron MacKenzie,
    20-Aug-2002 Use Greg's format recommendations and incorporate his changes.

    Ron MacKenzie,
    22-Aug-2002 Added C++ and java test program how_to.

    Ron MacKenzie,

    07-May-2004 Fixed local links.