Introduction To MoMELog Logging Framework

or Does Final J2ME Application need Logging Facility?



This article is the description of what, in my humble option, J2ME logging framework should be. It's purpose, requirements, features and how MoMELog fits to them. It is also an explanation of ideas that led to development of this project and the answer to the question: "Does final J2ME application need logging facility?".


Does final J2ME application need logging facility?

First of all a couple of words about all known features and specificities of J2ME architecture and it's differences from J2SE. It is not a secret, that J2ME is much more modest, small and a subject to a lot of restrictions and boundaries in comparison to J2SE. Only one J2ME application can be executing at one time and this application is definitely not a server or complex standalone application. It doesn't need to be administered or monitored by analyzing logging information. Users of J2ME application are definitely not interested in exploring logging, even if this application is a business application (say some mail agent or browser) and not a game. Of course, it is nice, if the application sends feedbacks to the developers in a case of an error. Besides, such feature is useful, user may be not too glad, when some application notifies him/her about it's internal error and that it wants to send some information via http, email or even sms. To my mind, users are caring much more about security of phone than a personal computer. Taking above into consideration, in my humble option, the answer to the question "Does final J2ME application need logging facility?" is "mostly not".

The reverse situation is at development time. While developing, J2ME application is mostly executed on emulators and definitely is probed on devices. Debugging (tracing) of application executed on emulator is, of course, possible but cumbersome. Debugging (tracing) of application executed on device is (almost) impossible. Here logging facility (like with server applications) is not just helpful but required. Developers just need logging facility as debugging tool.

I am not stating, that using of logging framework in final J2ME application is inadvisable.. I just want to tell, that the main aim of J2ME logging framework should be it's use in development process as debugging tool. And this is the aim of this project.


Requirements, that J2ME logging framework should follow and features should have.

Because of restrictions and boundaries of J2ME platform, such framework should be as simple and extensible as possible. The core of such logging framework should consist of only few classes. The other classes should be the implementations that realize particular formatted method or make logging information accessible to the developer via some particular mean (e.g. show on a screen, append to a file, send via http/https as email or sms or save in RMS).

In my humble option, while debugging, there is no need to distinguishing logging events by priority. We don't need different treatment of logging events of priorities say ERROR, FATAL or WARNING. All logging should be of priority of DEBUG. In other words, there should be no priority at all. All logging events must be even. Of course, it should be possible to filter logging events based on existence of not-null error. For example, mentioned above feature of sending feedbacks can be realized using this.

Developers while debugging also don't need different treatment of logging events issued by different loggers. Of course, possibility to suppress logging of group of loggers or vice versa to allow logging only of group of loggers is needed. But, at development time we don't need to format logging events from one logger using one method and logging from another - some other method, or to show logging of some group of loggers on the screen and logging information from others to be appended to a file. All logging events should be formatted using one method and presented via one mean (except, that some of them can be filtered out). In other words, it should be only one formatter and one implementation to present logging information via some particular mean. The above said, makes maintaining of hierarchy of loggers needless. Disallowing and/or allowing logging of group of loggers can be realized by matching categories to some allowed or disallowed patterns.

J2ME logging framework should provide two ways to configure it and it's extensions: declarative and programmatical. Declarative should be based on character sequence supplied to the framework (e.g. file contained in application jar archive). Programmatical configuration is based on inserting some code in J2ME application. J2ME logging framework and it's extensions should provide meaningful default values for their properties to minimize needed configuration. As such logging framework is intended to be used at development time and by developers some programming work to setup some artifacts of framework (i.e. extensions) should be not considered as huge problem.


How MoMELog logging framework fits to the above requirements?

MoMELog logging framework is very simple. It consists of three parts: Logger, Formatter, LogListener.

Fig-1. MoMELog Framework.

Logger is the main part of MoMELog framework. It generates logging events on user request and directs them to the configured LogListener. LogListener converts these events to formatted strings using configured Formatter and makes obtained strings available to the user (e.g. shows on screen, puts in RMS, sends via http/https, appends to a file or any other way).

MoMELog logging framework doesn't maintain the hierarchy of loggers. All loggers are even. Loggers are distinguished by categories, that are the case-sensitive identification strings. It is possible to suppress logging of group of loggers or allow logging of only group of loggers, by specifying disallowed categories and allowed categories lists respectively. They are a comma separated lists of patterns. Logger can only log it's events, if it's category matches one of the patterns in allowed categories list and not in disallowed categories list. If any of the lists is empty, it is not considered. It is recommended to use structural categories. This can be very helpful in formatting logging events and gives better possibilities to suppress or allow logging of a group of loggers. It is also possible to specify group of loggers that will generate logging event only if user request contains not-null error. This feature is realized by onlywitherror categories list, that is also the list of patterns.

MoMELog framework doesn't support the notion of priority. All logging events are even. The feature of filtering out logging events based on their properties (except not-null error) can be built in a particular LogListener implementation and is not realized by the core of the framework. Developers have only two methods to request logging of a message and/or error: Logger.log(String message) and Logger.log(String message, Throwable error).

In MoMELog framework logging events have the following properties:

MoMELog framework can be configured declaratively and/or programmatically. Declarative configuration is done by supplying initialization file .momelog.txt (don't omit preceding dot ;-)) in the application jar archive. This is a text properties file, where lines are separated by new-line characters and empty lines and lines that start with hash (#) (preceding spaces are allowed) are ignored. Framework can be also configured programmatically by using static methods of Logger class. Programmatical configuration of LogListener and/or Formatter can be done by using instance methods of respective implementation. Declarative configuration occurs at Logger class loading time and programmatical one, of course, overrides it.

The core framework provides means to set the type of LogListener used for presenting logging to the developer, type of Formatter used for converting logging events to strings and allowed categories, disallowed categories and onlywitherror categories lists. MoMELog is preconfigured with PatternFormatter, no LogListener and empty allowed categories, disallowed categories and onlywitherror categories lists. MoMELog is not preconfigured with some LogListener, because in J2ME platform there is no regular mean where to put formatted logging information. Of course, it is possible to put logging in RMS. But, it is impossible to execute application and analyze logging simultaneously. Not all devices support FileConection API. Sending logging information via http/https, email or sms can be a solution for a final applications (developers feedback), but at development time can be cumbersome. Presenting logging information on a screen requires from developer some programming work. In other words the choice of mean to use for presenting logging information depends on application and/or device used and relies on developer.

Some MoMELog extensions can require from developers programming work to be done to use them (especially when dealing with presenting logging information on a screen). As mentioned above, this is not considered as big problem.


Classes that comprise MoMELog framework.

The core of the MoMELog framework consists of 5 classes.

MoMELog framework now consists also of three extensions


Usage

Usage of MoMELog framework is similar to other logging frameworks.

Developer needs to obtain Logger instance by invoking one of static factory methods of Logger class

  1. Logger.getLogger(String category)
  2. Logger.getLogger(Class clazz)
  3. Logger.getLogger()

The first method returns Logger instance of the specified category. In the second case category will be set to the name of the given class (like from Class.getName() method). The last convenient Logger.getLogger() method returns Logger instance of default category, that is a slash (/). I mentioned default but not root, because there is no hierarchy of loggers and there is no root (besides, the category is the same ;-)). If somebody likes to call it root category, I have nothing against. Although, the same Logger instance is returned for the same category, it is recommended to save this instance in a static variable.

Developers can use one of two methods log(String message) or log(String message, Throwable error) of Logger instance to request logging of messages and/or errors. For example

  public class SomeClass
  {
    // obtaining logger of SomeClass category.
    private static final Logger log = Logger.getLogger( SomeClass.class);

      ...

    public method someMethod()
    {
      // logging a message.
      log.log( "logging the message");

        ...

      try
      {

          ...

        // logging another message.
        log.log( "logging another message");
      } catch( Throwable err)
      {
        log.log( "logging message with error", err);

        ...
      }
    }

      ...
}


Sergio Morozov, 2007