Thad,
Thanks so much. This looks exactly what I want to do. But somehow I never got your code to work. I finally modified your approach a bit, and now it works for me. I am now able to dynamically set the location of the log4j configuration file in my app. And this works not just when the app is deployed/redeployed, but also when the Tomcat service is restarted after the app has been deployed. I made these changes to your code: 1. LogListener is now a subclass of Log4jServletContextListener, instead of just implementing ServletContextListener. So I’m only declaring a single listener in web.xml. 2. I’m not using the servlet init parameter Log4jWebSupport.LOG4J_CONFIG_LOCATION to set the config file location. Instead, I’m initializing a log4j Configurator from the file. ----------------------------------------------------- LogListener.java: public class LogListener extends Log4jServletContextListener { @Override public void contextDestroyed(ServletContextEvent event) { super.contextDestroyed(event); } @Override public void contextInitialized(ServletContextEvent event) { logConfigPath = … // Determine the path of the log configuration file Configurator.initialize(null, logConfigPath); super.contextInitialized(event); } } web.xml: <listener> <!-- This listener *must* be first for log4j to work. --> <listener-class>com.mycorp.server.rest.listeners.LogListener</listener-class> </listener> ----------------------------------------------------- Your email was instrumental for me being able to find this solution. Thanks again :-) With kind regards Piers -- Piers Uso Walter <piers.wal...@ilink.de> ilink Kommunikationssysteme GmbH Kurfuerstendamm 67, 10707 Berlin, Germany +49 (30) 28526-185 > Am 21.03.2024 um 13:43 schrieb Thad Humphries <thad.humphr...@gmail.com>: > > Piers, > > I've configured two webapps with the log4j2 configuration outside of the > *war files. The approach I'll describe is working in Tomcat 8.5 and Tomcat > 9. > > First I create a LogListener class for the webapp: > > public class LogListener implements ServletContextListener { > > private static final Logger LOGGER = LogManager.getLogger(); > private Log4jServletContextListener listener = new > Log4jServletContextListener(); > > @Override > public void contextDestroyed(ServletContextEvent event) { > listener.contextDestroyed(event); > } > > > @Override > public void contextInitialized(ServletContextEvent event) { > String loggerPath = "WEB-INF/classes/log4j2.xml"; > > ServletContext context = event.getServletContext(); > String fileString = context.getInitParameter("log4jConfiguration"); > if (fileString != null && fileString.length() > 0 > && !fileString.equals("*")) { > if ((new File(fileString)).exists()) { > loggerPath = fileString; > } > } > event.getServletContext().setInitParameter( > Log4jWebSupport.LOG4J_CONFIG_LOCATION, loggerPath); > listener.contextInitialized(event); > LOGGER.info("logging properties from " + loggerPath); > } > } > > > I declare the LogListener in web.xml and add some filtering: > > <listener> > <!-- This listener *must* be first for log4j to work. --> > > <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class> > </listener> > <listener> > <!-- This listener is required to set the log4jConfiguration fallback. > --> > > <listener-class>com.mycorp.server.rest.listeners.LogListener</listener-class> > </listener> > > <!-- See https://logging.apache.org/log4j/2.x/manual/webapp.html --> > <filter> > <filter-name>log4jServletFilter</filter-name> > > <filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class> > </filter> > <filter-mapping> > <filter-name>log4jServletFilter</filter-name> > <url-pattern>/*</url-pattern> > <dispatcher>REQUEST</dispatcher> > <dispatcher>FORWARD</dispatcher> > <dispatcher>INCLUDE</dispatcher> > <dispatcher>ERROR</dispatcher> > <dispatcher>ASYNC</dispatcher> > </filter-mapping> > > <context-param> > <param-name>isLog4jAutoInitializationDisabled</param-name> > <param-value>true</param-value> > </context-param> > > Finally, in the Tomcat context file, META-INF/context.xml, I add the > log4jConfiguration that LogListener wants: > > <Parameter description="Configure Log4j2 logging." > name="log4jConfiguration" override="false" > value="/Users/admin/local/etc/my_logger.xml"/> > > > When I start Tomcat, the first entry in the log is > > 12:23:23.439 INFO LogListener.contextInitialized() - logging properties > from /Users/admin/local/etc/my_logger.xml > > At one time I had this working in Jetty, but I no longer remember where to > set its context. > > We've installed these apps on numerous servers, both Linux (of various > distros) and macOS. AFAIK, they're also running on a number of Windows > servers as well. Logging works everywhere. > > On Wed, Mar 20, 2024 at 12:09 PM Piers Uso Walter <piers.wal...@ilink.de> > wrote: > >> Hi Piotr, >> >> Thanks for your email. >> >> Here is what I’m trying to do: >> The previous version of our app stores the log4j configuration within the >> war file. >> This works fine but is annoying if one wants to change any logging setting >> (unpacking the war, changing the configuration, repacking the war, >> redeploying). >> >> For the next version of our app, I would like to move the log4j >> configuration to a place outside of the war. >> For Tomcat I would like to use $catalina.home/conf/ilink/GW-log4j2.xml >> and for Wildlfy I would like to use >> $jboss.home.dir/conf/ilink/GW-log4j2.xml >> (with $catalina.home and $jboss.home.dir being system properties that are >> defined in the two servers) >> >> Since the configuration file path is only known at runtime I cannot use >> the servlet initialization parameter ‘log4jConfiguration’ in web.xml. >> So I looked at log4j's automatic configuration [1]. >> This led me to the idea to use a ServletContextListener to determine if >> the app is running in WIldFly or in Tomcat and then setting the system >> property $log4j.configurationFile accordingly. >> >> But as you point out, the ServletContextListener is executed too late. >> That explains why it does not work in my case 2 (when the Tomcat service >> is restarted). >> I still don’t understand why it does work in my case 1 (when the app is >> being redeployed in a running Tomcat), but that is not so important as this >> does not seem to be the correct approach anyway. >> >> Also, thanks for pointing out what should have been obvious: that other >> web apps on the same server will be affected when I set the >> `log4j2.configurationFile` property. >> Not a good idea. >> >> Am I trying something unusual here when I attempt to make the app decide >> where the log4j configuration file is located? >> Is there any other way in which I can achieve this? >> Is there an API for this? >> >> Thanks, >> Piers >> >> [1] >> https://logging.apache.org/log4j/2.x/manual/configuration.html#automatic-configuration >> >> >> >>> Am 15.03.2024 um 07:45 schrieb Piotr P. Karwasz <piotr.karw...@gmail.com >>> : >>> >>> Hi Piers, >>> >>> On Thu, 14 Mar 2024 at 14:08, Piers Uso Walter <piers.wal...@ilink.de> >> wrote: >>>> However, what I was trying to achieve by using a servlet context >> listener was to be able to set the location of the log4j configuration file >> at run time. >>>> I’m trying to make the app compatible with different app servers where >> configuration files are typically placed in different locations. >>>> So I’m figuring out at run time which app server the app is running in, >> and based on that I know where to expect the log4j configuration file. >>> >>> Can provide more details as to where the path to the configuration >>> file is actually stored? If you change the `log4j2.configurationFile` >>> property, other web apps on the same server will be affected, which >>> might be an unpleasant surprise to users. There are less invasive ways >>> to do that. >>> >>> I also wonder if maintaining container specific code is worth the >>> effort. Many application servers have a detailed guide to configuring >>> logging (e.g. WildFly[1]). Users might be unwilling to learn yet >>> another way to configure logging. >>> >>> Sure, Tomcat is an exception, that is why I maintain a small set of >>> Log4j Core plugins and Tomcat extensions[2] to help users >>> administering logging at a global level. >>> >>> Piotr >>> >>> [1] https://docs.wildfly.org/31/Admin_Guide.html#Logging >>> [2] https://github.com/copernik-eu/log4j-tomcat >>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: log4j-user-unsubscr...@logging.apache.org >>> For additional commands, e-mail: log4j-user-h...@logging.apache.org >>> >> >> > > -- > "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. 111-13)