pglezen 01/06/03 23:15:22 Modified: src/java/org/apache/log4j/examples/appserver AppServerCategory.java AppServerCategoryFactory.java package.html Removed: src/java/org/apache/log4j/examples/appserver AppServerPropConfigurator.java Log: These changes are the result of a belated understanding of Anders' PropertySetter class. About 100 lines of configuration voodoo was replaced by adding a few lines to PropertyConfigurator and some other minor adjustments. One should now be able to change from using Category to AppServerCategory with NO changes in source code; only the property file needs to change. 1. AppServerCategory - static init was removed. The Category static init does the job now. 2. AppServerCategoryFactory - added default constructor and overloaded the setMessageBundle to allow the PropertySetter introspector to set the message bundle. 3. AppServerPropConfigurator - removed since PropertyConfigurator does its job now. 4. package.html - revised docs. (Look Ceki. No javadoc warnings!) Revision Changes Path 1.8 +16 -62 jakarta-log4j/src/java/org/apache/log4j/examples/appserver/AppServerCategory.java Index: AppServerCategory.java =================================================================== RCS file: /home/cvs/jakarta-log4j/src/java/org/apache/log4j/examples/appserver/AppServerCategory.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- AppServerCategory.java 2001/06/02 09:49:43 1.7 +++ AppServerCategory.java 2001/06/04 06:15:21 1.8 @@ -41,29 +41,28 @@ * * <p>Rather than set all these attributes for each * <code>AppServerCategory</code> instance, it is usually more - * convenient to set them on <code>AppServerCategoryFactory</code> - * and associate this factory statically with - * <code>AppServerCategory</code> using the static - * <code>setFactory</code> method. The - * <code>AppServerCategory.getInstance(String)</code> method can then - * be used to create <code>AppServerCategory</code> instances. - - * <p> A special {@link AppServerPropConfigurator} subclass of {@link - * org.apache.log4j.PropertyConfigurator PropertyConfigurator} is - * provided to facilitate complete factory configuration at class - * load time. This is useful in application server environments - * where a variety of entry points may exist for an application. - * Check the package level documentation for details on how to set - * this up. <p> + * convenient to set them once on {@link AppServerCategoryFactory}. + * The factory can then be associated with the + * <code>AppServerCategory</code> class via {@link #setFactory} + * or with the entire hierarchy via + * {@link org.apache.log4j.Hierarchy#setCategoryFactory}. In the + * former case, you should use {@link AppServerCategory#getInstance} + * to create new categories. In the latter case, you would use + * {@link org.apache.log4j.Category#getInstance(String)}. The former + * method allows finer granularity of control; the latter is more + * convenient. Reliance on the + * {@link org.apache.log4j.PropertyConfigurator} will employ the + * latter. + * + * <p>More convenient still is to rely on the + * {@link org.apache.log4j.Category} static initializer. See the + * package level documention for details. * * @author Paul Glezen */ public class AppServerCategory extends Category { private static String FQCN = AppServerCategory.class.getName(); - public static final String APPSERVER_INIT_OVERRIDE_KEY = - "log4j.appserverInitOverride"; - /** The name of the component using this category. */ protected String component; @@ -82,51 +81,6 @@ instances. */ private static CategoryFactory factory = new AppServerCategoryFactory(null, null, null); - /** - * This static initializer will configure over the one used by - * <code>Category</code> if the <code>log4j.appserver.factory</code> - * property is defined in the configuration file (and the default - * init override key is not set to true). - */ - static { - String override =OptionConverter.getSystemProperty( - APPSERVER_INIT_OVERRIDE_KEY, - null); - - // If there is no appserver init override, then get the resource - // specified by the user or the default config file. - if(override == null || "false".equalsIgnoreCase(override)) { - String resource = OptionConverter.getSystemProperty( - DEFAULT_CONFIGURATION_KEY, - DEFAULT_CONFIGURATION_FILE); - LogLog.debug("Running AppserverDefaultInit"); - URL url = null; - try { - url = new URL(resource); - } catch (MalformedURLException ex) { - // So resource is not a URL; attempt to get the resource - // from the classpath - url = ClassLoader.getSystemResource(resource); - if(url == null) { - // Is it under anywhere in the classpath? - url = Category.class.getResource("/" + resource); - } - if(url == null) { - // Is it under org/apache/log4j somewhere in the classpath? - url = Category.class.getResource(resource); - } - } - // If we have a non-null url, then delegate the rest of the - // configuration to the AppServerPropConfigurator class. - if(url != null) { - LogLog.debug("Configuring with AppServerPropConfigurator"); - new AppServerPropConfigurator().doConfigure(url, defaultHierarchy); - } else { - LogLog.debug("Could not find resource: ["+resource+"]."); - } - } - } - /** * Construct a new AppServerCategory with the provided * attributes. The constructor is protected because the only 1.5 +31 -0 jakarta-log4j/src/java/org/apache/log4j/examples/appserver/AppServerCategoryFactory.java Index: AppServerCategoryFactory.java =================================================================== RCS file: /home/cvs/jakarta-log4j/src/java/org/apache/log4j/examples/appserver/AppServerCategoryFactory.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- AppServerCategoryFactory.java 2001/03/05 04:52:39 1.4 +++ AppServerCategoryFactory.java 2001/06/04 06:15:21 1.5 @@ -1,9 +1,11 @@ package org.apache.log4j.examples.appserver; import java.util.ResourceBundle; +import java.util.MissingResourceException; import java.net.InetAddress; import java.net.UnknownHostException; +import org.apache.log4j.helpers.LogLog; import org.apache.log4j.Category; import org.apache.log4j.spi.CategoryFactory; @@ -71,6 +73,15 @@ component = componentName; version = versionName; } + + /** + * The default constructor merely calls the three-argument + * constructor with null values. + */ + public AppServerCategoryFactory() + { + this(null, null, null); + } /** * Get the name of the component for which this category is logging. @@ -152,6 +163,26 @@ */ public void setMessageBundle(ResourceBundle bundle) { messageBundle = bundle; + } + + /** + * Set the message bundle using the bundle filename. This name + * should not include the "<code>.properties</code>" extension. + * Care should be taken to ensure the bundle file is somewhere + * in the system classpath or loadable by this class's class + * loader. + * + * @param filename name of the bundle file + */ + public void setMessageBundle(String filename) + { + try { + messageBundle = ResourceBundle.getBundle(filename); + LogLog.debug("Message bundle [" + filename + "] retrieved."); + } + catch(MissingResourceException mre) { + LogLog.warn("Failed to find [" + filename + "] message bundle."); + } } /** 1.5 +69 -93 jakarta-log4j/src/java/org/apache/log4j/examples/appserver/package.html Index: package.html =================================================================== RCS file: /home/cvs/jakarta-log4j/src/java/org/apache/log4j/examples/appserver/package.html,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- package.html 2001/06/02 09:49:43 1.4 +++ package.html 2001/06/04 06:15:22 1.5 @@ -13,81 +13,57 @@ </ol> <p> <h2>Configuration</h2> -Using this package in your programs differs little from using the -corresponding classes in <code>org.apache.log4j</code>. Because of some -internal difference in the initialization sequence, this package -contains its own property configurator. A static initializer is also -provided in the category subclass that works in much the same way as -the <code>Category</code> static initializer. In this initial version, +Using this package in your programs differs little from using +{@link org.apache.log4j.Category}. In this initial version, only property file initialization is supported. -<p> -The following properties serve to configure the -<code>AppServerCategoryFactory</code>. + +<h3>Automatic Configuration</h3> +The following properties serve to configure the {@link +org.apache.log4j.examples.appserver.AppServerCategoryFactory}. <p> <table border=1> <tr><th>Property<th>Description -<tr><td><code><b>log4j.appserver.factory</b></code> - <td>The fully qualified class name of the factory implementation. -<tr><td><code><b>log4j.appserver.factory.server</b></code> +<tr><td><code><b>log4j.categoryFactory</b></code> + <td>The {@link org.apache.log4j.spi.CategoryFactory} + implementation to use. +<tr><td><code><b>log4j.factory.server</b></code> <td>The value assigned to the server attribute. -<tr><td><code><b>log4j.appserver.factory.component</b></code> +<tr><td><code><b>log4j.factory.component</b></code> <td>The value assigned to the component attribute. -<tr><td><code><b>log4j.appserver.factory.version</b></code> +<tr><td><code><b>log4j.factory.version</b></code> <td>The value assigned to the version attribute. -<tr><td><code><b>log4j.appserver.factory.msgfile</b></code> +<tr><td><code><b>log4j.factory.messageBundle</b></code> <td>The name of bundle file to populate the message <code>ResourceBundle</code>. Because the <code>ResourceBundle.getBundle</code> method is used to load the message file, the <code>".properties"</code> extension should <b>not</b> be included as part of this property. </table> -<p> -The property names are defined in {@link -org.apache.log4j.examples.appserver.AppServerPropConfigurator}. -<p> -<h3>Automatic Configuration</h3> -In application servers, it is difficult to predict which code -will be the first to run. There is no <code>main</code> method -the application programmer can grab hold of and populate with -initialization method calls. This complicates the initialization -of a log4j hierarchy, an essentially static structure, by various -transient objects such as servlets, EJBs or CORBA objects. -<p> -The simplest way to achieve the log4j configuration is to allow -the configuration to occur at class load time of the -<code>AppServerCategory</code>. The static initializer of -<code>AppServerCategory</code> is very similar to that of its -parent class, <code>Category</code>. -<p> -For the static <code>AppServerCategory</code> to perform properly, -it is best to disable the configuration attempted by the -<code>Category</code> static initializer. This is done by defining -the system property <code>log4j.defaultInitOverride</code> to be -<code>true</code> (or anything else but <code>false</code>). If -you run your program from the command line, you do this with the -<code>-D</code> option; as in -<p> -<center> -<code>java -Dlog4j.defaultInitOverride=true my.class.with.main</code> -</center> -<p> -If you are logging from an application server, you will need to -consult the vendor's documentation on how to set system properties. -<p> -Like the <code>Category</code> static initializer, the -<code>AppServerCategory</code> static initializer expects to find -the name of the property file in a system property called -<code>log4j.configuration</code>. If this system property is not -defined, an attempt is made to load <b>log4j.properties</b>. -<p> -Since all the actions described above are triggered by the loading -of the <code>AppServerCategory</code> class, they will likely -happen at the first occurence of a statement like <p> -<code>Category cat = AppServerCategory.getInstance("some.cat");</code> +A sample configuration might look like this. <p> -There is no need to take special measures to ensure the appropriate -configurator was run beforehand. +<table border=1> +<tr><td><pre> +log4j.categoryFactory=org.apache.log4j.examples.appserver.AppServerCategoryFactory +log4j.factory.server=TestServer +log4j.factory.component=TestComponent +log4j.factory.version=SomeVersion +log4j.factory.messageBundle=app_messages + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.examples.appserver.AppServerPatternLayout +log4j.appender.stdout.layout.ConversionPattern=[%h:%s:%b:%v] %m%n +</pre></table> +<p> +There is <b>no</b> need to change your source code to go from using +<code>Category</code> to <code>AppServerCategory</code> if you are +using property files to configure your logging infrastructure. +Simply specifying the <code>AppServerCategoryFactory</code> +as the {@link org.apache.log4j.spi.CategoryFactory} implementation +does the trick. It installs the factory +as the default factory for the hierarchy so that +{@link org.apache.log4j.Category#getInstance(String)} always returns +the proper <code>Category</code> subclass. <h3>Manual Configuration</h3> You can manually invoke the configuration much like the static @@ -96,13 +72,12 @@ <table border=1> <tr><td><pre> import org.apache.log4j.Category; -import org.apache.log4j.examples.appserver.AppServerCategory; -import org.apache.log4j.examples.appserver.AppServerPropConfigurator; +import org.apache.log4j.PropertyConfigurator; ... -AppServerPropConfigurator.configure("test.properties"); -Category cat = AppServerCategory.getInstance("some.cat"); +PropertyConfigurator.configure("test.properties"); +Category cat = Category.getInstance("some.cat"); ... @@ -111,16 +86,19 @@ <p> <h3>Very Manual Configuration</h3> If you want complete control over the configuration process, you -can leave <code>AppServerPropConfigurator</code> out of it all -together. +can leave <code>PropertyConfigurator</code> out of it all +together. This could be useful if you want only some of your +categories to be <code>AppServerCategory</code> instances. <p> After creating an appropriate <code>AppServerCategoryFactory</code> -instance, set a static reference to it using the -<a href="AppServerCategory.html#setFactory"> -<code>AppServerCategory.setFactory</code></a> method. This -sets everything up for acquiring an -<a href="AppServerCategory.html"><code>AppServerCategory</code></a> -reference whenever you need one. +instance, set a static reference to it using {@link +org.apache.log4j.examples.appserver.AppServerCategory#setFactory}. +This sets everything up for acquiring an <code>AppServerCategory</code> +reference whenever you need one. When you use this method of +configuration, the hierarchy's default factory is left alone. So +you should use {@link +org.apache.log4j.examples.appserver.AppServerCategory#getInstance(String)} +to acquire a reference to an <code>AppServerCategory</code> instance. <p> <table border=1> <tr><td><pre> @@ -142,20 +120,28 @@ </pre> </table> <p> +Do <b>not</b> use {@link +org.apache.log4j.examples.appserver.AppServerCategory#getInstance(String)} +to acquire an <code>AppServerCategory</code> instance if you used +<code>PropertyConfigurator</code> to do the configuration. While the +introspection mechanism used by <code>PropertyConfigurator</code> is good, +it doesn't know to set a link from <code>AppServerCategory</code> to +the factory. Misusing the <code>getInstance</code> method in this manner +will result in categories produced that have host name defined but all +other attributes set to null. +<p> <h4>A Note on Configurators</h4> -Using <code>AppServerCategory</code> with -<a href="../../PropertyConfigurator.html"> -<code>PropertyConfigurator</code></a> or -<a href="../../xml/DOMConfigurator.html"> -<code>DOMConfigurator</code></a> -requires a note of caution. By default these configurators -do not know that -<a href="../../Category.html"><code>Category</code></a> -has been subclassed. Upon +Using the <i>very manual</i> approach to configure +<code>AppServerCategory</code> with +<code>PropertyConfigurator</code> or <code>DOMConfigurator</code> +requires a note of caution. Since the <i>very manual</i> method +does not provide the <code>log4j.categoryFactory</code> property, +these configurators do not know that <code>Category</code> has +been subclassed. Upon constructing a configuration from a set of properties, it will construct <code>Category</code> instances rather than instances -of the desired subclass. There at least two ways to work around -this. +of the desired subclass. One way to around this is decribed +below. <p> By instanciating any anticipated <code>AppServerCategory</code> instances before calling a configurator, the configurator will @@ -165,16 +151,6 @@ dynamic nature is the reason for externalizing their configuration in the first place. This drawback is limited to category names explicitly defined in the configuration. -<p> -Another work-around is to take advantage of a recently added feature -allowing you to specify the type of factory used for creating -<code>Category</code> instances to a <code>DOMConfigurator</code> -or a <code>PropertyConfigurator</code>. The consequence -is that only the default constructor is used to create -the factory instance. For <code>AppServerCategoryFactory</code>, -this will only populate the hostname attribute. The server name, -component name and version name will be blank. For many cases -this may be satisfactory. <p> <h2>Remote Usage</h2> Including attributes such as hostname and server are only relevant --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]