Simple Strategy for Logging and Monitoring of MIDlets

By Vikram Goyal

Logging and monitoring your MIDlet in development is easy. Just print some lines on the console around critical events, and you know what is happening within your MIDlet. Integrated development environments (IDEs) such as the NetBeans IDE make this even easier by allowing you to do on-device debugging. But this is of no use to you when your MIDlet is actually being run on a client's phone.

How do you monitor your killer MIDlet? Can you receive notification if something critical happens? Can you get an SMS to attend to notifications? Of course, you can. Several APIs make this possible, and this tech tip will show you how to combine them into a single interface.

Simulate Logging Events

To simulate the various events in an actual MIDlet, I have created a simple MIDlet with a random-event generator. The random-event generator simulates activity within the MIDlet and does nothing for normal events. Because informational events in any MIDlet are more likely to occur than warning, error, or critical events, this random MIDlet takes a sliding-scale approach to generating these events. The scale is implemented in the following code:

    // now try and simulate an event within this application
    int rand = random.nextInt(19);

    if (rand > 8) { // no event that needs logging if random no < 9
      if (rand <= 13) { // info
        form.append(midlet.getInfo());
        midlet.doInfoLog("This is an information message.");
      } else if (rand <= 15) { // warn
        form.append(midlet.getWarn());
        midlet.doWarnLog("This is a warning!");
      } else if (rand <= 17) { // error
        form.append(midlet.getError());
        midlet.doErrorLog("Oh, no, an error occurred!");
      } else { // critical
        form.append(midlet.getCritical());
        midlet.doCriticalLog("The sky is falling!");
      }
  }

When you run the MIDlet and start the activity, it will cycle through a clock going from 1 to 15. This is a timer that shows the user that some activity is happening within the MIDlet. During each activity cycle, a random number is generated. As shown in the previous code, if the random number is within the prescribed ranges, it triggers the corresponding logging event. The simple events, and the ones most likely to occur, are the informational messages. The most dire events are the ones that are marked as critical, and they occur only if the random number is exactly equal to 18.

What to Log Where

I have made the assumption that informational messages are to be recorded only, perhaps, as a way for a technical team to audit if they can get their hands on the actual device if something more critical happens. Similarly, I have assumed that warning messages are to be logged to a nearby Bluetooth device, error messages to an Internet server, and critical messages to be sent by way of SMS.

Create a Logging Interface

To keep things simple, the MIDlet makes decisions on the severity of the logging messages and creates loggers based on that assumption (described in the previous section). The following code shows how these decisions are implemented:

    private void createLoggers() {
      infoLog = new RMSLogger();
      warnLog = new BluetoothLogger();
      errorLog = new InternetLogger();
      criticalLog = new SMSLogger();
  }

Each logger is an implementation of the simple Logger interface. This interface is shown in the following code:

    public interface Logger {

      public void doLog(String msg);
    }

With a single method called doLog, the interface defines a minimum contract for the implementations to follow. The actual implementations must then figure out how they will make the logging calls.

Create the Logging Implementations

Now, it is a simple method to figure out what the actual implementations will do. For example, the following code shows what the RMSLogger will do:

    package logger.impl;

    import javax.microedition.rms.RecordStore;
    import logger.Logger;

    public class RMSLogger implements Logger {

      private RecordStore rs;

      public RMSLogger() {
        try {
          rs = RecordStore.openRecordStore("Log_Store", true);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }

      public void doLog(String msg) {
        byte[] rec = msg.getBytes();
        try {
          rs.addRecord(rec, 0, rec.length);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }

As you can see, the constructor does the background work of creating or opening the record store. The doLog() method then does the heavy lifting, by writing the message to the record store.

Similarly, here is the InternetLogger code:

    package logger.impl;

    import java.io.IOException;
    import java.io.OutputStream;
    import javax.microedition.io.Connector;
    import javax.microedition.io.HttpConnection;
    import logger.Logger;

    public class InternetLogger implements Logger {

      // set your destination URL here
      private String destURL = "";

      private HttpConnection conn;

      public InternetLogger() {

        try {
          conn = (HttpConnection) Connector.open(destURL);
          conn.setRequestMethod(HttpConnection.POST);
          conn.setRequestProperty(
            "Content-Type", "application/x-www-form-urlencoded");
        } catch (Exception e) {
          e.printStackTrace();
        }

      }

      public void doLog(String msg) {
        try {
          // The destination URL must be set before doLog is called.

          if(conn == null) {
            System.err.println("DEST URL is not valid.");
            return;
          }
          conn.setRequestProperty("Content-length", "" +
            ("msg=" + msg).getBytes().length);

          OutputStream os = conn.openOutputStream();
          os.write(("msg=" + msg).getBytes());
          os.flush();

        } catch (IOException ex) {
          ex.printStackTrace();
        }
      }
    }

The code here is just a placeholder, and you will need to fill in the destination URL where you want the message to be posted, along with some sort of identification of the sender of the message.

BluetoothLogger and SMSLogger follow similar patterns, and the source code contains the implementations for these.

Resources

Comments:

Have you looked at MicroLog, http://microlog.sourceforge.net/ ? It is a logging framework for mobile devices based on the Log4J API. Several different logging destinations are supported besides the four that you have suggested.

Posted by Mattias on October 13, 2009 at 03:28 AM PDT #

good

Posted by guest on October 16, 2009 at 04:49 PM PDT #

javas technology simply the best.

Posted by daniel kimani on October 23, 2009 at 01:21 AM PDT #

done !

Posted by MILES D. WILSON on October 26, 2009 at 10:48 AM PDT #

Hii..
Java technology is more powerful and best than any other technology.Really you have give me simply method. I am very thankful to you for this. I liked this method.
Thanks again.

Posted by bluetooth freisprecheinrichtun on November 09, 2009 at 04:01 PM PST #

See the technical article about Microlog described in http://blogs.sun.com/mobility_techtips/entry/powerful_logging_in_java_me

Posted by christine on November 09, 2009 at 11:20 PM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Tips for developers who use Java technologies (Java SE, Java ME, JavaFX) for mobile and embedded devices.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today