wood burning stoves 2.0*
The moose likes Tomcat and the fly likes Changing log4j.properties in unexploded WAR file Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Products » Tomcat
Bookmark "Changing log4j.properties in unexploded WAR file" Watch "Changing log4j.properties in unexploded WAR file" New topic
Author

Changing log4j.properties in unexploded WAR file

Thad Humphries
Greenhorn

Joined: Feb 04, 2011
Posts: 14

I'm trying to discover if there is a way to put the log4j.properties in some place other than WEB-INF/classes. Is there a way to do this in Tomcat? Is there a solution that is generic to other servlet containers as well?

I'm anticipating a customer or support tech who wants unpackWARs="true" but also wants the log written to someplace other than ${java.io.tmpdir}, say a home directory or a local log directory (which will certainly differ between sites based on various Linux distros, Windows, local admin procedures, etc.).

Using the Log4jInit servlet in "Default Initialization under Tomcat" (in http://logging.apache.org/log4j/1.2/manual.html) as a guide, I've tried to find a way to set the log4j-init-file parameter in my app's META-INF/context.xml. However it seems that <load-on-startup>1</load-on-startup> preempts whatever I my set in the app context.

Assuming I can't change the location of log4j.properties to outside of my WAR and in a manner that can account for different server configurations, what is the merit of using a initialization servlet? What benefits does a servlet provide? Do I need it, say, for rereading log4j.properties (with doGet()) if in troubleshooting we need to change the log level?


"Hell hath no limits, nor is circumscrib'd In one self-place; but where we are is hell, And where hell is, there must we ever be" --Christopher Marlowe, Doctor Faustus (v, 121-24)
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18710
    
    8

There is no merit in using an initialization servlet. That's because life-cycle listeners were added to Java EE several years ago, and that's what you should be using now.

However, moving on from that diversion: Initializing log4j doesn't have to use a config file which is automatically searched for in the classpath. You can initialize it by specifying the location of a config file, or you can initialize it by writing code which creates appenders and so on. I believe this is described in the log4j tutorial, but it's a long time since I read the tutorial so it may not be covered as well as I think it is.

As for trouble-shooting, you can certainly use a servlet to modify the log level, but I think it's more common to use JMX to do that sort of thing these days.
Thad Humphries
Greenhorn

Joined: Feb 04, 2011
Posts: 14

Paul Clapham wrote:There is no merit in using an initialization servlet. That's because life-cycle listeners were added to Java EE several years ago, and that's what you should be using now.


Of course, a ServletContextListener. Done. Thanks.

Paul Clapham wrote:As for trouble-shooting, you can certainly use a servlet to modify the log level, but I think it's more common to use JMX to do that sort of thing these days.


As for changing the log level through JMX, how can that be done? When I run jconsole, I don't see my logger. Must I put something into my listener to have jconsole see my logger? How do I connect jconsole and my app that is using log4j.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18710
    
    8

Thad Humphries wrote:As for changing the log level through JMX, how can that be done? When I run jconsole, I don't see my logger. Must I put something into my listener to have jconsole see my logger? How do I connect jconsole and my app that is using log4j.


Sorry, I have used JMX in other contexts but not in Tomcat. All I know is that you can use JMX in Tomcat -- but to tell you the truth I don't even know for sure that you can use it to administer things in a web app, as opposed to just administering the server. So I guess that advice wasn't all that helpful. It might be worth looking into though, to see if it's a possible route for you to take.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16158
    
  21

One of the Great Confusions of Our Time. I went round and round and round on this one myself.

I'm out of practice on the topic, but unless I got totally confused, JMX for webapps is not an issue. The webapps must contain the appropriate MBeans, and (IIRC) they have to register them with the JVM in order to be served up, but whether a given MBean belongs to the server or to a deployed app doesn't matter, as (I think!) the MBean "belongs" to the JVM.


Customer surveys are for companies who didn't pay proper attention to begin with.
Thad Humphries
Greenhorn

Joined: Feb 04, 2011
Posts: 14

Tim Holloway wrote:One of the Great Confusions of Our Time. I went round and round and round on this one myself.

I'm out of practice on the topic, but unless I got totally confused, JMX for webapps is not an issue. The webapps must contain the appropriate MBeans, and (IIRC) they have to register them with the JVM in order to be served up, but whether a given MBean belongs to the server or to a deployed app doesn't matter, as (I think!) the MBean "belongs" to the JVM.


Thanks, Tim. It took some hunting, but I've hit on something that is working, and it is generic enough to use on my next app.

Here's my LogListener. The administrator can use the default properties file from the WAR or define his own. Since the log properties file can be set in the application context, it can be elsewhere--outside of Tomcat--and the WAR remain unpacked. This listener also registers the logger with JMX so that the log level can be set while the app is running (see screenshot).




[Thumbnail for jconsole.png]

Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16158
    
  21

getRealPath() gives me hives. It isn't guaranteed to return a path at all, and especially if the WAR is unexploded.

Personally, I prefer to store parameters like this as env-entry definitions so that they can be set (overridden) from the Tomcat Context definition and retrieved by the webapp via JNDI.

I definitely would avoid using relative path names - they are extremely untrustworthy in a webapp environment. Most likely, I'd expect a general path value and use a "magic" value such as "*" to indicate use of the internal log4j property definitions.

Thad Humphries
Greenhorn

Joined: Feb 04, 2011
Posts: 14

Tim Holloway wrote:getRealPath() gives me hives. It isn't guaranteed to return a path at all, and especially if the WAR is unexploded.

Personally, I prefer to store parameters like this as env-entry definitions so that they can be set (overridden) from the Tomcat Context definition and retrieved by the webapp via JNDI.

I definitely would avoid using relative path names - they are extremely untrustworthy in a webapp environment. Most likely, I'd expect a general path value and use a "magic" value such as "*" to indicate use of the internal log4j property definitions.



You're right, Tim. And as soon as I turn from my Linux box and work a short while on a Windows laptop, I'm reminded that checking for the first character equal to "/" to indicate an absolute path isn't portable across all platforms. Thanks.
 
Consider Paul's rocket mass heater.
 
subject: Changing log4j.properties in unexploded WAR file