RE: Trying log4j3 with java24 (virtual threads)

<[email protected]> Tue, 28 Jan 2025 17:23:47 +0100
Newsgroups gmane.comp.jakarta.log4j.user
Message-ID <[email protected]>
Hi Piotr,

Thanks for the quick response. I'm trying to remove my initialization of =
log4j and delegate it to the log4j-jakarta-web. When I add the =
dependency, maven requires me to add a version tag, so I set:

    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-jakarta-web</artifactId>
      <version>2.24.3</version>
      <scope>runtime</scope>
    </dependency>

But when I start my application, this error occurs:

Caused by: java.lang.NoSuchMethodError: 'boolean =
org.apache.logging.log4j.core.util.Loader.isClassAvailable(java.lang.Stri=
ng)'
        at =
org.apache.logging.log4j.web.Log4jWebInitializerImpl.<clinit>(Log4jWebIni=
tializerImpl.java:57)
        at =
org.apache.logging.log4j.web.WebLoggerContextUtils.getWebLifeCycle(WebLog=
gerContextUtils.java:84)
        at =
org.apache.logging.log4j.web.Log4jServletContainerInitializer.onStartup(L=
og4jServletContainerInitializer.java:56)
        at =
org.apache.catalina.core.StandardContext.startInternal(StandardContext.ja=
va:4426)
        at =
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164)


Should I use another version? The 3.0.0 is in alpha1 yet.

Thanks,

Joan.



-----Original Message-----
From: Piotr P. Karwasz <[email protected]>=20
Sent: Tuesday, January 28, 2025 3:49 PM
To: [email protected]
Subject: Re: Trying log4j3 with java24 (virtual threads)

Hi Joan,

On 28.01.2025 14:58, [email protected] wrote:
> 0. Using these java version and log4j3, and taking into account that =
3.0.0-beta1 already includes support for virtual threads, will the fact =
of pinning a thread for log output no longer happen?
If you are referring to the usage of `synchronized` blocks, not all such =
blocks were removed in 3.x, although it should be a rather easy PR. Note =
that Java 24 removed thread pinning if `synchronized` blocks are used.
> 1. You told me to set up "log4j-core" with scope =3D runtime, but I'm =
using it on my code to load the log4j xml config file:
>
> 	import org.apache.logging.log4j.core.LoggerContext;
> 	( . . . )
> 	LoggerContext context =3D (LoggerContext) =
LogManager.getContext(false);
> 	context.setConfigLocation(Paths.get(servletRealPath + =
"WEB-INF/log4j.xml).toUri());
> =09
> 	Is this the correct way to do this? Or is there any other way that =
does not need to directly use log4j-core?

Loading the appropriate configuration file from the WAR archive is the=20
job of `log4j-jakarta-web`. See the description of the=20
`log4jConfiguration` servlet init parameter[1]. If you don't set the=20
parameter, `/WEB-INF/log4j2.xml` will be loaded (not=20
`/WEB-INF/log4j.xml`). I haven't checked, but version `3.0.0-alpha1` or=20
even `2.24.3` of `log4j-jakarta-web` should be compatible with beta 3 of =

`log4j-core`.

[1] https://logging.apache.org/log4j/2.x/jakarta.html#log4jConfiguration

> 	b) Imported "log4j-api" (that adds the "log4j-api-2.24.1.jar" to our =
war file)

As a transitional measure, you could bump the version of `log4j-api` to=20
`2.24.3`. We had a critical bug that sometimes returns `null` loggers,=20
so we do not recommend `2.24.1` of the Log4j API (see release notes=20
[2]). Obviously we'll fix the dependency version in beta 4.

[2]=20
https://logging.apache.org/log4j/2.x/release-notes.html#release-notes-2-2=
4-1

> 	c) Imported "log4j-slf4j2-impl", otherwise when our app starts I get =
the following warning:
> 	=09
> 		INFO: SLF4J: Failed to load class =
"org.slf4j.impl.StaticLoggerBinder".
> 		INFO: SLF4J: Defaulting to no-operation (NOP) logger implementation
> 		INFO: SLF4J: Seehttp://www.slf4j.org/codes.html#StaticLoggerBinder =
for further details.
> 	=09
> 		Question: is it possible this warning is coming from any of our =
external libraries that we are using?
This is a side-effect of Maven's breadth-first conflict resolution=20
algorithm: `log4j-slf4j2-impl` requires `slf4j-api` version 2.x or=20
higher, while other dependencies might requires SLF4J 1.x. Those=20
dependencies probably come first in your dependency tree.
> 3. We have not included "log4j-jakarta-web", everything seems to be =
working fine without it. Is it really necessary to include it in when =
using app webs like ours executing in a tomcat container?

The purpose of `log4j-jakarta-web` is to synchronize Log4j's lifecycle=20
with the lifecycle of the container. Basically it pick the right=20
configuration file at startup and shuts down the appenders, when the=20
application shuts down. See the documentation[3] for more info.

[3]=20
https://logging.apache.org/log4j/2.x/jakarta.html#log4j-jakarta-web-insta=
llation

> 4. We have programatically added:
> 		System.setProperty("log4j.loggerContext.selector", =
"org.apache.logging.log4j.core.selector.BasicContextSelector");
> 		-->	This is to use synchronous loggers, I understand it is correct.

Yes, `BasicContextSelector` creates a single logger context and=20
synchronous loggers. However, since you bundle Log4j Core with your=20
application and web application libraries are not shared between=20
applications, you would have the same effect with the default value=20
`ClassLoaderContextSelector` (theoretically it gives one logger context=20
per classloader, but since it can not be accessed from other=20
classloaders=E2=80=A6 you effectively have one logger context)

[4]=20
https://logging.apache.org/log4j/2.x/manual/systemproperties.html#log4j2.=
contextSelector

> 		Question: if the config is reloaded due to some change and, at the =
same time, there was a change in the ${sys:log.buffer} env. variable, =
will log4j be able to get the new value of ${sys:log.buffer}?
Yes, variables are interpolated again at each reconfiguration.
> 5. Finally, if I enable the log4j debug, how should I look at to check =
I'm really using synchronous loggers?

In Log4j Core 3 the asynchronous logger implementation is in the=20
`log4j-async-logger` artifact. You can be pretty sure your loggers are=20
synchronous.

Piotr