| = Logging |
| :jbake-type: page |
| :jbake-status: published |
| |
| == Logging for Users |
| |
| All logging in OpenEJB is done using the openejb.base/conf/logging.properties file. |
| When you download and extract OpenEJB, you will not find this file under the openejb.base/conf directory. |
| However, when you start the server, this file magically appears. |
| So what does this give you as a user of OpenEJB? |
| Here are some of the benefits: |
| |
| . You do not have to author a logging.properties from scratch. |
| You get one with sensible defaults. |
| . If you did modify the default file, and you wanted to revert back to the default file generated by OpenEJB, all you have to do is |
| . {blank} |
| + |
| = Delete or rename the file e.g. rename it to logging.properties.BAK . |
| . {blank} |
| + |
| = Restart the server |
| |
| |
| OpenEJB will find that the logging.properties file is missing from the openejb.base/conf directory and it will automatically create a new one with the default configuration. |
| The good thing is that if you modify the logging.properties file, OpenEJB will *NOT* over-write it. |
| |
| The default logging configuration created by OpenEJB uses RollingFileAppender's. |
| The log files are located under the openejb.base/logs directory. |
| By default it writes to just two files , openejb.log and transaction.log |
| {info:title=Embedded Testing} When running tests using embedded OpenEJB, the logging.properties will be ignored. |
| You need to use a file named embedded.logging.properties instead. |
| Place this file under src/test/resources \{info} +++<a name="Logging-Loggingforcontributors/committers">++++++</a>+++ |
| |
| == Logging for contributors/committers |
| |
| The org.apache.openejb.util.Logger class is the one which is used for logging. |
| This class is a wrapper around log4. |
| |
| +++<a name="Logging-LogCategory">++++++</a>+++ |
| |
| === LogCategory |
| |
| Each Logger instance belongs to a category represented by a org.apache.openejb.util.LogCategory instance. |
| Here is what the LogCategory class looks like |
| |
| .... |
| public final class LogCategory { |
| private final String name; |
| public static final LogCategory OPENEJB = new LogCategory( "OpenEJB"); |
| public static final LogCategory OPENEJB_ADMIN = OPENEJB.createChild("admin"); |
| public static final LogCategory OPENEJB_STARTUP = OPENEJB.createChild("startup"); |
| public static final LogCategory OPENEJB_STARTUP_CONFIG = OPENEJB_STARTUP.createChild("config"); |
| public static final LogCategory OPENEJB_STARTUP_VALIDATION = OPENEJB_STARTUP.createChild("validation"); |
| // other categories removed for code brevity |
| private LogCategory(String name){ |
| this.name = name; |
| } |
| public String getName() { |
| return name; |
| } |
| /** |
| * Creates a child category of this category. <B>Use this method sparingly</B>. This method is to be used in only those circumstances where the name of the |
| * category is not known upfront and is a derived name. If you know the name of the category, it is highly recommended to add a static final field |
| * of type LogCategory in this class |
| * @param child |
| * @return - LogCategory |
| */ |
| public LogCategory createChild(String child){ |
| return new LogCategory(this.name+"."+child); |
| } |
| |
| } |
| .... |
| |
| Notice carefully how each LogCategory instance is created. |
| The objective here is that each LogCategory should be a child of the OPENEJB category. |
| If you need to add a new category and you know the name of the category upfront, simply open the LogCategory class and add another category. |
| For example, if you needed to add a category named SHUTDOWN, here is the recommended way to add it |
| |
| public static final LogCategory OPENEJB_SHUTDOWN = LogCategory.OPENEJB.createChild("shutdown"); |
| |
| Sometimes you may want to create a category whose name is "generated" at runtime. |
| In that case you can use the "createChild" method of the LogCategory class to create this new category. |
| For example, if you wanted to create a category of Logger for every deployed module, then assuming you have the moduleId information you could do something as follows to create a category: |
| |
| String moduleId = "mymodule"; |
| LogCategory generatedCategory = LogCategory.OPENEJB.createChild(moduleId); |
| |
| +++<a name="Logging- Logger">++++++</a>+++ |
| |
| === Logger |
| |
| The preference is to externalize all logging messages in properties file. |
| Typically each package should have a file called Messages.properties. |
| This file should have all the keys and the corresponding messages. |
| Here are the steps you would follow to log a message: |
| |
| * For each message you need to log, you would open the Messages.properties file in the corresponding package and add a key-value pair for the message. |
| For example, if you were authoring a class called org.apache.openejb.util.Connect, then you would add a key-value pair to the Messages.properties file located in the org.apache.openejb.util package. |
| * Obtain a Logger instance in one of the following ways: |
| |
| |
| |
| |
| |
| _Using the package name_ |
| |
| Logger logger = Logger.getInstance (LogCategory.OPENEJB, "org.apache.openejb.util"); |
| |
| |
| |
| |
| __ |
| Using the Class__ |
| |
| Logger logger = Logger.getInsance(LogCategory.OPENEJB, Connect.class); |
| |
| |
| _Get a child Logger for an existing Logger instance_ |
| |
| Logger logger = Logger.getInsance(LogCategory.OPENEJB, Connect.class); |
| Logger child = logger.getChildLogger("shutdown"); |
| |
| |
| _Get a child Logger of an existing Logger using a LogCategory_ |
| |
| LogCategory childCategory = LogCategory.OPENEJB.createChild("shutdown"); |
| Logger logger = Logger.getInstance(childCategory,Connect.class); |
| |
| * Call one of the following methods passing in the key as an argument ** debug ** error ** fatal ** info ** warning |
| + |
| Logger logger = Logger.getInstance(LogCategory.OPENEJB,Connect.class); |
| logger.info("error.file"); |
| |
| |
| The Messages.properties file under org.apache.openejb.util must have the "error.file" key in it with the corresponding message. |
| |
| +++<a name="Logging-LoggerInheritance ">++++++</a>+++ |
| |
| === Logger Inheritance |
| |
| Another interesting feature of the Logging framework is inheritance. |
| Here is how it works: |
| |
| Say you have the following Messages.properties files in the classpath. |
| |
| . |
| org/apache/openejb/Messages.properties |
| . |
| org/apache/openejb/core/Messages.properties |
| . |
| org/apache/openejb/core/stateless/Messages.properties |
| |
| |
| |
| Then you have a class such as org.apache.openejb.core.stateless.StatelessContainer (+note the package+) If that class referenced a message key "classNotFound" for example, the Logger would look for the message first in Messages.properties 3, then 2, then 1 and so on until it found the required message. |
| This would allow better reuse of messages, more flexibility in where we put the Message.properties |
| files, as well as the added bonus in that we no longer need to pass in the location of where our Message.properties file is |
| |
| +++<a name="Logging-Loggingforintegrators">++++++</a>+++ |
| |
| === Logging for integrators |
| |
| If you want to embed OpenEJB in your application and need to control the logging configuration of OpenEJB, simple set the openejb.logger.external system property to true. |
| Now, its your applications' responsibility to configure logging, OpenEJB will simply use your configuration. |
| |
| +++<a name="Logging- OriginationoftheLoggingIdea">++++++</a>+++ |
| |
| === Origination of the Logging Idea |
| |
| There has been a long discussion for this logging idea. |
| Its going to be worth it to read the discussion at http://www.nabble.com/i18n-and-logging-tf3962134s2756.html[i18n and logging] |
| |
| +Here is a extract from an email from David Blevins which talks about the existing logging framework. |
| The current framework is more or less the same as this one, just some added features and a rewrite of the API+ |
| |
| Each module has a file called default.logging.conf. |
| This file contains the definition of all Loggers, their appenders and warning levels. |
| However, we do not use default.logging.conf first. |
| The basic idea is that first we look for say conf/logging.conf in the openejb.base directory. |
| If we don't find it there, we look for default.logging.conf in the classpath. |
| If we did find default.logging.conf (which we should) and there is an openejb.base/conf/ directory then expand the default.logging.conf to openejb.base/conf/logging.conf where we expected to find the file in the first place. |
| If there was no openejb.base/conf/ directory, then it's safe to assume we're running embedded (in a test case perhaps) and just use the default.logging.conf and do no extra work. |
| |
| We have default.logging.conf which we use this way as well as default.openejb.conf and now more recently users.properties and groups.properties. |
| We search on disk for the resource in openejb.base/conf/ if we don't find them we unpack the default one we stuffed in openejb-core jar and extract it to disk in the openejb.base/conf directory if there is one -- if there isn't one we just use the default file. |
| |
| The basic ideas behind the pattern are that: 1. |
| If you've messed up your configuration, just delete or rename the respective files in your conf/ directory and new (working) ones will magically appear. |
| 2. |
| When upgrading its nice that our zip file won't overwrite any existing files in conf/ 3. |
| If you're running embedded you don't have to setup any directories or have any config files, we can run on defaults. |
| |
| The _ConfUtils.getConfResource_ utility to do that pattern generically , but so far we're only using it for the users.properties and groups.properties files. |
| We should be using it everywhere. |
| Having the code in multiple places has lead to some inconsistencies such as we expand the default.openejb.conf file to conf/openejb.xml (not even the same file extension). |
| We really don't need the "default" part in our file names and the lingering usage of the "conf" file extension is something that needs to go bye-bye -- we should use properties for properties files and xml for xml files, etc. |