Debug/Logging

J2ME Polish provides a logging framework for debugging purposes.
The goals for the framework are:
- Enable and disable different logging levels for specific classes or packages
- Leave no traces, when disabled
- Extensible: define your own logging levels, add your own log handlers
- Allow to process and view log messages on real devices
- last but not least: simplicity!
Programming
To create a log entry in your, a simple
System.out.println() is used combined with the #debug preprocessing directive:
try {
doSomething();
//#debug
System.out.println("doSomething() succeeded");
} catch (Exception e) {
//#debug error
System.err.println("doSomething() failed" + e);
}
If the last logged parameter is an exception, the logging framework will automatically print its stacktrace:
//#debug error
System.err.println("doSomething() failed" + e);
You can also tag a debug message with a log level as shown above. There are 5 predefined log levels, but you can also create your own log levels:
- debug < info < warn < error < fatal < [userdefined]
Using the Log Framework for Debugging
As you will see below you can activate specific log levels for a class or a package. You can also check for a specific
log level in your code using the #if directive:
//#if polish.debug.info
int startTime = System.currentTimeMillis();
//#endif
doComplexCall();
//#debug info
System.out.println("complex call took "
+ (System.currentTimeMillis() - startTime)
+ " ms." );
In the above example we check if the info logging level is activated for this class. If that's the case we
measure and log the duration of the call. You can check for any log level by querying for the preprocessing symbol
polish.debug.${level}, and yes this includes user specified ones:
- polish.debug.debug
- polish.debug.info
- polish.debug.warn
- polish.debug.error
- polish.debug.fatal
- polish.debug.${userdefined}
Configuration
To activate the logging for your application, edit the <debug> section in your build.xml.
Log Filters and Levels
<debug verbose="false" level="error" if="test" > <filter package="com.company.mail" level="info" /> <filter class="com.company.mail.IMapServer" level="debug" /> </debug>
The example above will show log messages with the level info or higher in all classes of the package com.company.mail
and log messages with the level debug or higher of the class com.company.mail.IMapServer. You can use any number
of <filter> elements to finetune your log levels.
For all other classes the error log level will be active, as this is specified in the level
attribute (<debug level="error" ...).
In the above example the logging is only active when the Ant property test is set to true, since we are using the if
attribute: <debug if="test" .... Alternatively you might also want to use the unless attribute.
Custom Log Levels
You can define and activate your own log levels using the levels attribute of the <debug> element:
<debug verbose="false" level="error" levels="memory,performance" if="test" > <filter package="com.company.mail" level="info" /> <filter class="com.company.mail.IMapServer" level="debug" /> </debug>
You can now use such log levels like the predefined ones in your application:
//#debug memory
System.out.println("Free memory: " + Runtime.getRuntime().freeMemory() );
//#if polish.debug.performance
long startTime = System.currentTimeMilis();
//#endif
...
Log Handlers
By default log entries are logged to the standard output stream - this is useful in an emulator, but only in few other circumstances.
Use log handlers for sending logged entries to other places as well.
display Handler
The display log handler shows logged entries on top of the screen. This handler requires that you use the J2ME Polish user interface:

After some time without new log entries, the log will be hidden. Even when the log is shown, you can work normally with the application. You can influence the appearance and behavior with some optional parameters:
<debug verbose="false" level="error" if="test or log" >
<handler name="display">
<!-- hide entries after 10 seconds: -->
<parameter name="timeout" value="10s" />
<!-- show maximum 30 log entries: -->
<parameter name="max-entries" value="30" />
<!-- specify used colors: -->
<parameter name="background-color" value="#a333" />
<parameter name="font-color" value="yellow" />
<parameter name="shadow-color" value="rgb(0,0,0)" />
</handler>
</debug>
bluetooth Handler
Send log entries directly to your Bluetooth enabled Desktop PC with the bluetooth log handler.
For receiving the log entries you can use ${polish.home}/bin/enough-j2mepolish-bluetoothlogger.jar
(call it from the command line using java -jar enough-j2mepolish-bluetoothlogger.jar).
Note that you need to have support for L2CAP connectivity, which is not supported on Windows when using the Microsoft Bluetooth stack.
If that's the case for please deactivate that stack and use Widcomm or similar instead. On Linux and Mac OS X L2CAP is always supported (when Bluetooth is active).
<debug verbose="false" level="error" if="test or log" > <handler name="bluetooth" /> </debug>
http Handler
You can also send log entries to a remote server using HTTP GET requests thanks to Vera Wahler's contribution:
<debug verbose="false" level="error" if="test or log" >
<handler name="http">
<-- optional parameters -->
<parameter name="server" value="http://www.j2mepolish.org/loghandler" />
</handler>
</debug>
This log handler will create a GET request for each log entry. The following example is a simple Ruby script that reads received log entries:
#!/usr/bin/ruby require 'webrick' include WEBrick s = HTTPServer.new( :Port => 8100) class LogServletStack Traces
Emulator stacktraces usually only give the bytecode offset of an exception:
at com.company.product.ClassName.method(+20);J2ME Polish can resolve such offsets automatically:
at com.company.product.ClassName.java:200For making this possible, please install the jad decompiler from http://www.kpdus.com/jad.html to ${polish.home}/bin.
Last but not least don't forget to add a catched exception as the last parameter to a log entry in this way:
} catch (Exception e) { //#debug error System.err.println("doSomething() failed" + e); }