| ![]() |
|
||||||
|
![]() | Package de.qfs.lib.log | ![]() |
![]() |
Even though the API reference for the
Let's start with some of the basics. Every log message has an associated level of importance. There are five major levels, each with a sublevel for details. The following constants for the levels are provided with the Log class:
In addition to the level and the message itself, a timestamp, the acive thread and the class and method that created the messages are provided. The output of a log message is formatted as follows: level (timestamp) thread class.method: message The timestamp, thread and class are created automatically. Unfortunately Java doesn't provide the means to determine the currently executing method, so it has to be passed by hand. Creation of log messages
Lets take a look at how log messages are created. This should
always be done through the use of a
When creating a
Example 1 illustrates three common
calls of the
This call is protected with a check of
The method log (lines 12-16) is similar to the call in line 19,
except for an additional check. The parameter
Unfortunately Configuration of the logging system
Next we'll concern ourselves with some configuration issues. What
happens to the log messages after they are created? Details about
the various kinds of filters being applied can be found in the
API reference for the class
With qflib version 0.98.0 the
The most trivial case is output to
Creating a log file is best done with the method
All that is needed to use the log server qflog with your program is
shown in line 22. You'll find the details about this call in the
API reference for
Upon termination of your program it is wise to make sure the
logging system is shut down cleanly (lines 30-32). First the call
Setting the
|
|
Example 3: Setting the level of a
Logger |
Example 3 shows two of the possible
ways of configuring log message generation: by explicitly setting
levels in the source code and through command line arguments. In
line 12 the level for all classes is increased to
Log.MSGDETAIL
. Line 13 constrains messages from
qflib to errors. Lines 14 and 15 allow messages up to level
Log.MTD
for all classes from mypackage
,
for the class mypackage.NewClass
even up to
Log.DBGDETAIL
. The dot ('.') at the end of the
package name in lines 13 and 14 is essential. The order in which
these calls are executed has no effect.
While this method illustrates how levels work it is not very elegant, since modification of the settings can only be achieved through recompilation. A better way is to read the settings from a property file and pass them directly to Logger.setLogLevels at program startup.
In a similar way the ArgsParser class from the de.qfs.lib.util
package of the qflib
can be used to read the settings from the command line, as shown
in lines 17-23. Settings similar to those from lines 12-15 are
obtained through the call
|
Most convenient is the use of the log server qflog with which the settings can be edited through a graphical interface even during the runtime of your program. The necessary steps on your side were already explained in example 2. For installation and use of qflog see the qflog manual.
The log window from qflog can be embedded directly into your program. This is quite simple, as the following example demonstrates:
|
Example 4: Embedding the LogView
component |
The LogView
component is initialized in line 12 and
that's already all there is to it. For real use you probably don't
want to open the log window right at program startup, as shown in
line 13, but rather via a menu item or a button.
![]() | Logging and applets | ![]() |
![]() |
Writing an applet that runs in all common browsers is about as hard as designing an interesting web page that looks the same everywhere. There are quite a few hidden incompatibilities between the Java VM implementations in Netscape Navigator, Microsoft Internet Explorer and the Java plugin from SUN which is available in versions ranging from 1.1 to 1.3. An additional problem is the sandbox which restricts an applet's capabilities for security reasons. While a signed applet is able to break out of the sandbox, signing is not easy and, of course, the procedure is different for the three major VMs. The "Hello world" applet revisitedAll that doesn't make writing and debugging applets any easier, so logging would come in very handy. Unfortunately qflib used to suffer (and still does a bit) from just the same problems, but we tried to work around them starting with version 0.97.0.
The worst problem used to be that many versions of Internet
Explorer were released without RMI support. Since there was an
indirect RMI dependence in the Nevertheless the RMI classes are still necessary to connect to qflog. Fortunately, Microsoft at least provide them as an add-on that can be downloaded from their Java resources page. It is enough to install this package on your development system, it is not needed for deployment of the applet.
The next problem qflib suffers from is the sandbox-imposed
restriction on network connections. A non-trusted applet may only
talk to the server from which is was loaded and may not listen for
connections on its own. This means that qflog has to be run on
the machine on which the weserver is hosted and that RMI callbacks
don't work, which are needed to control the log levels of the
Applet's Here is an example applet that has all the necessary elements to use logging as far as possible:
As you can see in line 9, you must not import any RMI dependent
classes directly, otherwise applet initialization will fail with a
The rest of the applet is quite straightforward and doesn't
introduce any new concepts, though a look at lines 32-36 and the
|
![]() | Package de.qfs.lib.util | ![]() |
![]() |
Here we will take a look at how some of the most useful classes of
the Parsing command line arguments with an
|
|
i.e. it expects the options version
, dir
and option
, where dir
and
option
need parameters and option
may
occur multiple times. Beyond that the logging system will be
configured through options starting with log-
(see example 3 for the de.qfs.lib.log
package). Following the options a file name argument is expected.
|
Example 1: Parsing command line arguments with an
ArgsParser |
Calling MyMainClass
from the above examples like
|
will result in filename
having the value
"myfile"
and the Hashtable
options
be filled as follows:
Key | Value |
---|---|
"dir" |
"/home" |
"option" |
["opt1", "opt2"] |
Version 0.98 introduces the new LogSetup
class which
sets up the logging system based on command line options read from
an ArgsParser
. You can use it to set most of the
parameters of the Log
class (output level, etc.) and
the levels of the Loggers
as well as to redirect log
messages to one or multiple logfiles, contact the log server
qflog and even to integrate the LogView
component
of the log server directly into your application.
Please see the API
reference for LogSetup
for the available
options and their use. The following example demonstrates the
ease of use of the LogSetup
class:
|
Example 2: How to use LogSetup
|
MapResourceBundle
Java offers reasonable localization support through the
ResourceBundle
mechanism. The class
MapResourceBundle
extends this by adding some useful
features:
jar
archivesIcons
|
Example 3: Localization via a
MapResourceBundle |
First the MapResourceBundle
is filled with the
properties provided with qflib (line 12). In line 13 properties
from mypackage
are added, which may well override
some qflib values. The classes passed as parameters are used to
locate the property files in jar
archives. The class
files must reside in the same archive as the property files.
The MapResourceBundle
thus initialized can now
e.g. be passed to the Message
class from
the de.qfs.lib.gui
package to get
localized dialogs for errors and other messages.
Line 17 shows how to query the MapResourceBundle
for a
value from its properties. The default value passed as an argument
will be returned in case the resource is not available. This eases
the use of resources compared to handling exceptions.
For the code in line 18 that fetches an Icon
to work,
the resource "myicons.arrow"
in the property file
mypackage/resources/myproperties
must have as a value
the path for the Icon's
file, e.g.
"/mypackage/myicons/arrow.gif"
![]() | Package de.qfs.lib.gui | ![]() |
![]() |
Ceating a table with automatic sorting
Among other things the
Example 1 shows how to create a sorted
table that exhibits the default behaviour: no filtering and using
the default sort order for each column class (determined with
There is a more complex demo that includes filtering as well as
sorting, available as The sort order can be changed by clicking once on a column header. Clicking on the same header again will reverse the direction. A little arrow in the column header indicates the current sort order. Addititonally you can resize a column so that it fits the currently displayed values by double-clicking its header.
The sorted table will keep its selected rows even when the sort
order changes as you can verify by selecting some rows and then
changing the sort order. If you change the
You can use the ComboBox at the top of the window to chosse between different filter settings.
There is one thing about the implementation of a sorted table that
you have to be aware of: The |