At first I had a difficult time with the OSID Exception
handling. Exceptions with useful error messages discarded and replaced
with OPERATION_FAILED at the Interface.
Too many of us wrote programs that gathered configuration information in the top of the program and moved it downward while simultaneously collecting status messages and returning them back upward. The OSID then begins to look like a firewall preventing us from reaching our destiny in the programming world of the vt100.
In the last article, Implementation Configuration, configuration was loaded and retrieved entirely below the Interface boundary. So once again, the question is not if the Exceptions can be accessed, but where they can be accessed. And as always, the answer is below the Interface.
Often the phrase from the Interface zealots is heard, what happens inside the Implementation is none of your business, and this is always a scary concept. Actually, what is intended is none of the Application's business. That doesn't mean that system managers, application developers and users can't find out what is going on down there. They just can't do it through the Application code and that's different.
In this article, we're going to examine a simple logging mechanism used within Implementations to capture diagnostic information the using Logging OSID.Yes, Logging. Some might look at the Logging OSID as a less useful alternative to Logs4j and others might be turned off because they don't want a log file. It's still the right answer.
There's no law that says an Implementation of the Logging OSID must write to a log file. You can do whatever you like inside the Implementation. Send an alert. Popup a window. Order pizza. Write to stderr. All or none of the above.
The first problem at hand is instantiating the
LoggingManager. The Three Bears rule applies
here. Instantiating it for every call is too much and having a single
instance stashed in some static class is too little. Different
Implementations may require different Logging Implementations. One
Logging Implementation for every OsidManager instance feels about
right. But we can be a little clever about it.
Once again, the OsidManager Implementation can be
exploited to keep the subclasses a bit cleaner. The subclassed manager
can invoke getLogger() at initialization time.
protected OsidLogger getLogger() {
String impl = getConfiguration("logging_osid");
String logName = getConfiguration("logging_log");
OsidLogger ol = new OsidLogger(impl, logName);
String level = getConfiguration("logging_filter");
if (level != null) {
ol.setFilter(level);
}
return (ol);
}
getLogger() primarily retrieves some properties and
passes the work of loading the Logging Implementation to a static
class, OsidLogger. The feature of accessing the
properties inside OsidManagerWithCascadingProperties is
that the Logging Configuration can be set globally, or overridden on
an OSID or Application basis. Want to just see trace output for a
given AuthenticationManager? No problem.
getLogger() needs to be called from somewhere. In the
previous article, an
initialize() method was created inside the manager which
is intended to only be called by it's own
assignConfiguration() method. As good a a place as any to
get the log rolling.
public class AuthenticationManager
extends OsidManagerWithCascadingPropertiesAndLogging
implements org.osid.authentication.AuthenticationManager {
OsidLogger logger;
protected void initialize()
throws org.osid.OsidException {
logger = getLogger();
logger.logDebug("initializing AuthenticationManager");
...
}
...
}
I tend to name my OsidManager Implementations with painfully descriptive names to indicate what functions they have. There's no rule that says new methods to perform a variety of tasks can't be created here. A given OSID Implementation is inherently tied to the OsidManager Implementation and packaged in the same jar file so no one expects interchangeability here. The new methods introduced are only accessed from within the class instance and is in itself an Implementation detail.
In most cases, there is a need to access the logger
from outside the manager. As it turns out, this is a more general problem
that requires a more general solution.