Define a Log
Description:
As described in Understand logging, a Log is the representation of the "log file", which only is a real file,
if the specified OutputStream
is the recommended FileOutputstream
.
For a global Log
, you only have to define a GlobalOutputStream
by calling the static method
Log.setGlobalLogOutputStream(OutputStream newOS)
. For local logging, you have to initialize a new instance of
Log
, either by using the constructor, the static method Log.createLog(OutputStream newOS)
or a
LogCreator
.
Used classes:
Related topics:
ToDo:
-
For the initialization find a place at the beginning of your application runtime to make sure, the
LogOutputStream
exists before any logging starts. -
Due to the new
FileOutputStream
, remember to catch the thrownIOException
. -
Use the static method
setGlobalOutputStream
, which will initialize a newLog
and a globally reachableOutputStream
, enabling logging to it anywhere in your application.
Example Source Code:
1 // within the main method, but may be anywhere before any logging starts public static void main(String[] args) { LogShop logShop = new LogShop(); Shop.setTheShop(logShop); 2 // remember to catch the possible IOException of creating a new FileOutputStream try { 3 // the static method will initialize a new Log and set the FileOutputStream global // so it can be used anywhere in the application Log.setGlobalOutputStream(new FileOutputStream("machine.log", true)); } catch(IOException ioException) { System.err.println("Unable to create log file."); } }
Back to:
Define a new LogEntry
Description:
A LogEntry
is what is being put into the LogOutputStream
when logging an event. The information
needed for the Log
is provided by the two methods public String toString()
and
public Date getLogDate()
.
These are the methods to be redefined in order to suit your event log. By default they return
"Object logged: " + getLogDate()
and the present system date at the point of logging.
In our OpenLogEntry
we keep the system date as return of getLogDate
, but redefine the
toString()
method to return the String "Counter opened".
Used classes:
Related topics:
- Log the opening and closing of a SalesPoint
- Define a Log
- Implement the Interface Loggable
- Display log file content
ToDo:
-
Create a new subclass of
LogEntry
. -
Redefine the
toString()
method to return a suitable text for the event. -
Use the
LogEntry
to be returned by the methodgetLogData()
of the implementation ofLoggable
.
Example Source Code:
1 public class OpenLogEntry extends LogEntry { 2 public String toString() { return "Counter opened"; } }
Back to:
Define a new LogEntryFilter
Description:
A LogEntryFilter
is used either to enable logging of certain LogEntries
only or to display / process
certain LogEntries
of a Log
(which is a representation of the "log file").
To "filter" the LogEntries
, set the filter to the LogOutputStream
or LogInputStream
that is being used. It will check wether the handed over LogEntry
suits the condition described in the method
accept(LogEntry logEntry)
of LogEntryFilter
.
The easyest way to decide on the acception is by cheking wether a LogEntry
is an instance of something or not,
but anything that tells LogEntries
from will do.
In this expample we define a LogEntryFilter
that will only accept instances of OpenLogEntry
, which
is another example, defining a LogEntry
for the opening of the a SalesPoint
. (Therefore see:
Define a new LogEntry)
Used classes:
Related topics:
ToDo:
-
Create a new class implementing
LogEntryFilter
. -
Implement
accept(LogEntry logEntry)
to return true if a le is an instance ofOpenLogEntry
. -
Use the
LogEntryFilter
with the designatedLogInputStream
orLogOutputStream
.
Example Source Code:
1 public class OpenLogEntryFilter implements LogEntryFilter { 2 public boolean accept(LogEntry logEntry) { // that will return true if le is an instance of OpenLogEntry return (logEntry instanceof OpenLogEntry); } }
Back to:
Define a new ProcessLogEntry
Description:
The ProcessLogEntry
is a subclass of LogEntry
. The extension consists of the Process being handed
over to the constructor and the redefinition of the toString()
method, which roughly describes the process that
is being logged on by the String "Process \"" + getProcessName() + "\" logged on " + getLogDate() + "."
. There is
also an additonal public method getProcessName()
, which returns the name of the handed over Process.
The reason for this subclass or for subclassing it by yourself might be the need to use the LogEntryFilter
provided by the static field SaleProcess.LOGENTRYFILTER_PROCESSES_ONLY
. It accepts only instances of
ProcessLogEntry
. So if you ever want to filter logs that belong directly to a SaleProcess
, you have
to subclass the ProcessLogEntry
and use the LogEntryFilter
on it.
Used classes:
Related topics:
ToDo:
-
Create a subclass the
SaleProcess.ProcessLogEntry
. -
Add the constructor, call the superclass and hand over the
SaleProcess
. -
Redefine the
toString()
method to suit your log description.
Example Source Code:
1 public class GiveBackLogEntry extends SaleProcess.ProcessLogEntry { String name; String customerId; Object date; 2 public GiveBackLogEntry(SaleProcess process, String name, String customerId, Object date) { super(process); this.name = name; this.customerId = customerId; this.date = date; } 3 public String toString() { return name + " gave back by customer " + customerId + " (ID) at turn " + date; } }
Back to:
Implement the Interface Loggable
Description:
In order to be able to log anything, i.e. to put a LogEntry
into the LogOutputStream
, you have to
implement the interface Loggable
, which hands over the LogEntry
to the Log
. This can be
done within the class, you want to log an event in, but also in an extra class implementing the interface. Such an extra class
may of course be used form anywhere within the application. The second advantage is that you don't have to define conditions
for different events in the getLogData
method, but use seperate Loggable
implementations for each
event to be logged.
The method public LogEntry getLogData()
resolves the LogEntry
that shall be put into the
LogOutputStream
.
The implementation of Loggable
here is used to log the opening of a SalesPoint
by returning the
OpenLogEntry
, which was written for the event of opening a SalesPoint
.
Used classes:
Related topics:
ToDo:
-
Create a new class implementing
Loggable
. -
Implement the
getLogData()
method to return the rightLogEntry
for the logged event. Here it is theOpenLogEntry
. (See: Define a new LogEntry) -
Use the instance with
Log.log(Loggable l)
where you want to put theLogEntry
into theLogOutputStream
.
Example Source Code:
1 public class OpenLoggable implements Loggable { 2 public LogEntry getLogData() { return new OpenLogEntry(); } }
Back to:
Log the opening and closing of a SalesPoint
Description:
It might be quite useful to log events like the opening or closing of a SalesPoint
.
To be able to log these events, the SalesPoint
already has the two methods
protected void logSalesPointOpened()
and protected void logSalesPointClosed()
, which by default are
empty. In order to have the two events logged, you have to make these methods put the right LogEntry
into the
desired Log
.
In this example we only show how to log the opening. For the other logging it is almost the same procedure, but only in the
logSalesPointClosed()
method.
Used classes:
Related topics:
ToDo:
-
Implement the method
protected void logSalesPointOpened()
in your subclass ofSalesPoint
. -
Catch the
LogNoOutputStreamException
thrown by thegetGlobalLog()
method and theIOException
thrown by thesetGlobalOutputStream(OutputStream os)
, which is being called if noOutputStream
exists, in order to create one. -
Get the Global
Log
and put a newLoggable
implementation into it'sOutputStream
by using the methodlog(Loggable l)
. In our case it is a new instance ofOpenLoggable
.
Example Source Code:
1 protected void logSalesPointOpened() { 2 // remember to catch the two Exceptions try { 3 // get the globalLog and put a new OpenLoggable into it // this could also be logged into a local log Log.getGlobalLog().log(new OpenLoggable()); } catch(LogNoOutputStreamException lnose) { System.out.println(lnose); } catch(java.io.IOException ie) { System.out.println(ie); } }
Back to:
Log the opening and closing of a log file
Description:
It might be useful to log events like the opening or closing of a log file.
To be able to log these events, Log
already has the two methods protected void logOpenLog()
and
protected void logCloseLog()
, which by default are empty. In order to have the two events logged, you have to
make these methods put the right LogEntry
into the desired Log
.
This might sound familiar to Log the opening and closing of a SalesPoint, which it indeed is, so this example also shows how to
extend Log
, implement the Loggable
and extend the LogEntry
in one class, so everything
is there when needed.
Used classes:
Related topics:
- Log the opening and closing of a SalesPoint
- Define a new LogEntry
- Define a Log
- Implement the Interface Loggable
- Display log file content
ToDo:
-
Create a subclass of
Log
. -
Don't forget to hand over the
OutputStream
to the super class in order to create or append to the log. -
Implement the method
logOpenLog()
to log the opening of the logfile. -
Catch the two exceptions thrown by
log(Loggable l)
. -
Implement the needed
Loggable
within the log method. -
Subclass the
LogEntry
within the implementation of thegetLogData()
method. -
Overwrite the
toString()
method of theLogEntry
subclass.
Example Source Code:
1 public class LogLog extends Log { 2 public LogLog(OutputStream outputStream) { super(outputStream); } 3 protected void logOpenLog() { 4 try { 5 log(new Loggable() { 6 public LogEntry getLogData() { return new LogEntry() { 7 public String toString() { return "Log file openend"; } }; } }); } catch(LogNoOutputStreamException noStreamException) { } catch(IOException ioException) { } } }
Back to:
Understand logging
Description:
You can log almost anything that happens in your application, from the first start of it to the final shutdown and between
these two, any use of salespoints, databaskets, logons, processes and so on.
Although it is not quite obvious, this is a very useful feature. You may not only create some kind of history file, but also
reconstruct interrupted processes, document buys and sells, resolve statistics, and more.
How it works:
Logs
can be put into any kind of InputStream
, of which a FileInputStream
is the most
suitable. This OutputStream
may be both, locally defined or globally, which, too, is the most common way to use
logging.
The GlobalOutputStream
is being set by the static method Log.setGlobalOutputStream(OutputStream newOS)
,
where newOS mostly is new FileOutputStream(String filename, true)
(true to append the Stream to the file and not
overwrite it), which creates a new file called filename if it doesn't exist.
As said above, it is also possible to create a simple local Log
by using the static method
Log.createLog(OutputStream os)
or use the constructor Log(OutputStream os)
. You may even implement
the interface LogCreator
and use it to create new Logs
, but always remember to specify the
Log
you want to log an event into if you don't use the GlobalLog
. Log
by the way may be
understood as a representation of the log file.
The interface Loggable:
To log an event means to write a LogEntry
to the OutputStream
. This is done by the Interface
Loggable
, to be more precise, the method public LogEntry getLogData()
. Known implementing classes
are DataBasketEntryImpl
and SaleProcess
, but you may find the implementation quite poor and should
feel free to redefine them.
The most important thing for the event you want to log is, to put the right LogEntry
into the
OutputStream
. This might be by implementing the getLogData
method in the class you want to log in
correctly, or by creating a seperate implementing class of Loggable
and use it with
Log.log(Loggable myLoggable)
.
The abstract class LogEntry (which is not really abstract...):
Either way you have to make sure that the myLoggable or the method getLogData
returns the right
LogEntry
. In this class, the method public String toString()
defines what will be seen as the
Description on the LogTableForm
, which is being used to visualize a LogInputStream
(normally the log
file). The method getLogDate
specifies the displayed Date
on that TableForm
. By default,
the Date
will be the present system time and the String will be "Object logged: " + getLogDate()
.
Feel free to redefine these two methods and add anything you want to your implementation in order to create sufficient input
for the log file, but be aware that you allways have to get a String
and a Date
into it. It might
also be useful to implement new LogEntry
classes for each kind of log to be able to work with the
LogEntryFilter
.
The method public boolean accept(LogEntry le)
of that filter returns true, if le suits your specified condition,
which, when implementing new LogEntry
classes, might be the result of the class()
method.
Back to:
Display: Tables | User management |