I found a solution. It is not perfect but it works.
Man, I miss the old days of simple log4j-tomcat configurations.
Feel free to use, reproduce, modify (especially if you have
improvements) as you wish.
*Configuring Tomcat for log4j2 logging*
*NOTES*:
·A simpler configuration might be possible.
·This configuration is focused on *Windows* and routes *BOTH Tomcat’s
logging and the web applications logging* to the Tomcat log4j2 config
file.Most examples on the internet are only for one or the other, and
are usually described in Linux/Unix terms.
·This configuration does not prevent the following exception when Tomcat
is stops:
Handler error
java.lang.ClassCastException: class
org.apache.logging.log4j.jul.LogManager cannot be cast to class
java.util.logging.Handler (org.apache.logging.log4j.jul.LogManager is in
unnamed module of loader 'app'; java.util.logging.Handler is in module
java.logging of loader 'bootstrap')
*Environment variables*
·%CATALINA_HOME% refers to the environment variable that Tomcat
instructs you to create.
*Tomcat Configuration*
·Create log4j2 folder structure in the tomcat folder
%CATALINA_HOME%\log4j2
.\conf
.\lib
·Place log4j2-tomcat.xml in *.\conf*
·Place the desired version of jars in *.\lib*.Include log4j-api,
log4j-core, log4j-appserver, log4j-jul, log4j-web.
·Edit logging.properties:
oComment the handlers line and replace it with:
handlers=org.apache.logging.log4j.jul.LogManager
·Create setenv.bat with the following content.Edit the location of the
configuration file to match the one you are using.NOTE that we are *NOT
using %CATALINA_HOME% for the configurationFile location*, we are
explicitly spelling it out.This is to avoid conflicts between Windows’s
path format and Java’s.
set "CLASSPATH=%CATALINA_HOME%\log4j2\lib\*;%CATALINA_HOME%\log4j2\conf"
set CATALINA_OPTS=%CATALINA_OPTS%
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
-Dlog4j.configurationFile=file:/D:/work/soft/tomcat-10.1.7-j17corretto/log4j2/conf/log4j2-tomcat.xml
*Webapp Configuration*
(this example was tested with a simple SpringBoot REST service that
deploys as a WAR on Tomcat, but should also work for web applications)
·Maven POM should include the following in the appropriate locations
·<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jakarta-web</artifactId>
<version>${log4j2.version}</version>
<scope>runtime</scope>
</dependency>
·And note the <exclusions> portion of spring-boot-starter.It is
necessary to avoid the default spring boot logging mechanism so that
log4j can be used instead.
·<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId> </exclusion>
</exclusions> </dependency>
·Include the class Log4jContextListener below into the project.You may
drop the System.out output, but I found them to be convenient for
troubleshooting.
·@WebListener public class Log4jContextListener implements
ServletContextListener { @Override public void
contextInitialized(ServletContextEvent sce) { String log4jConfigFile =
System./getProperty/("log4j.configurationFile"); if(log4jConfigFile !=
null && log4jConfigFile.startsWith("file:/")) { log4jConfigFile =
log4jConfigFile.substring(6); } File file = new File(log4jConfigFile);
if(!file.exists()) { System./out/.println("Log4j config file "+log4jConfigFile+" does not exist"); }else{
System./out/.println("Log4j config file "+log4jConfigFile+" exists"); }
LoggerContext ctx = (LoggerContext) LogManager./getContext/(false);
ctx.setConfigLocation(file.toURI()); } }
*IntelliJ Configuration*
·With the above configuration there is no longer a need to use a special
IntelliJ Run/Debug configuration for log4j2 to work properly.
·Not only should proper logging end up in the log files, the console
display should also respect the logging levels and be formatted as per
the patterns specified in log4j2-tomcat.xml.
----
On 3/11/2025 6:06 PM, Piotr P. Karwasz wrote:
Hi Mark,
On 11.03.2025 09:46, Mark Thomas wrote:
On 10/03/2025 21:58, Piotr P. Karwasz wrote:
<snip/>
If you are looking for instructions on how to replace Tomcat's
default logging backend with Log4j Core, there is a dedicated
section[2] in our new Integrating Log4j Core with Jakarta EE Guide[3]
[2] https://logging.apache.org/log4j/2.x/jakarta.html#replace-tomcat
Thanks for this. I have added this link to Tomcat's logging
documentation and it will be in the April release round.
Thanks!
If someone from the Tomcat team could review the "Integrating with
Jakarta EE"[1] page, I would appreciate it. For example I would like
to hear your thoughts about the log separation section[2]. Tomcat
documentation says:
"Keep in mind that the alternative logging framework will need to be
capable of working in an environment where different loggers with the
same name may exist in different class loaders."
However these days only a few logging frameworks support separate
loggers for each class loader. Logback disabled support for multiple
logger contexts a couple of years ago.
The main problem is that libraries in the common classloader often use
static logger fields instead of having a different logger per web
application. Tomcat's own libraries seem to be an exception to this
rule and each Valve uses a per-application logger, but implementations
of many Jakarta specifications (e.g. Hibernate) do not follow this
pattern.
It seems rather useless to fix those libraries, so my personal
recommendation is to use a single logger context for the entire JVM
and just add some context data to the logs.
Piotr
[1] https://logging.apache.org/log4j/2.x/jakarta.html
[2] https://logging.apache.org/log4j/2.x/jakarta.html#log-separation
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org