Initializing Log4j within Web Context(tomcat)? - java

I checked log4j setup in my tomcat environment. Although there is no log4j-web.jar file in my webapp or in "common libs" folder, log4j is initialized properly. I only added log4j.properties in my classpath. And that's it, log4j is working.
I am using spring mvc, sl4j-api.jar and sl4j-jcl.jar are in my classpath.
My question is : How does log4j work properly and pickup the configuration?

You say that you used log4.properties so I will be assuming you are using log4j 1.2.x (log4 2 use log4j2.properties)
Log4 perform default initialization when log4j classes are loaded into memory within the static initializer of the LogManager class.
See the section: Default Initialization Procedure in the manual
As soon as you dropped log4j.properties into your classpath it trigger log4j logging.
This procedure will be executed in any environment (tomcat container or other).
if you want to skip this procedure please note item 1 in the procedure:
Setting the log4j.defaultInitOverride system property to any other
value then "false" will cause log4j to skip the default initialization
procedure (this procedure).
Log4Web is an extension for depending on log4j 2 so It's irrelevant in your case.
sl4j-api.jar and sl4j-jcl.jar requires log4j-over-slf4j if you what to migrate existing code to use SLF4J without changing the code itself.
If you are not interest in such migration you may ignore them.

Related

Java System Logger on WildFly

Since JDK 9 we have a new Java Logging API:
https://docs.oracle.com/javase/9/docs/api/java/lang/System.Logger.html
https://www.baeldung.com/java-9-logging-api
https://blog.frankel.ch/system-logger/
It's more like a facade, without real logging implementation, but relying on existent logging framework.
We can use this API on Wildfly (with JDK 11), but it binds on JUL (Java Util Logging, default bind on JDK 11), giving log outputs levels from JUL as SEVERE or FINE instead of ERROR or INFO, respectively.
So, I would like to change this, making Java System Logger binds to JBoss Logging Framework (the default on Wildfly).
Following tutorials, I created a custom LoggerFinder and a System.Logger implementation that points to JBoss Logger.
Then I have tried to create a META-INF/services/java.lang.System$LoggerFinder file pointing to my LoggerFinder implementation, as stated on 3rd link above, but with no luck. Tried to put this file on lib jar, app war, app ejb jar and app ear.
Resuming:
Actual: System.Logger -> JUL
Needed: System.Logger -> JBoss Logger
Update 1
I see that WF has a LogManager lib that should handle this (jboss-logmanager-1.1.18.Final.jar):
https://github.com/jboss-logging/jboss-logmanager/blob/2.1.18.Final/src/main/java9/org/jboss/logmanager/JBossLoggerFinder.java
https://github.com/jboss-logging/jboss-logmanager/blob/2.1.18.Final/src/main/resources/META-INF/services/java.lang.System%24LoggerFinder
But it appears that this LogManager is not loaded.
Update 2
Documentation on LoggerFinder says that:
A logger finder is a concrete implementation of this class that has a zero-argument constructor and implements the abstract methods defined by this class. The loggers returned from a logger finder are capable of routing log messages to the logging backend this provider supports. A given invocation of the Java Runtime maintains a single system-wide LoggerFinder instance that is loaded as follows:
First it finds any custom LoggerFinder provider using the ServiceLoader facility with the system class loader.
So, I think that org.jboss.logmanager is not loaded on system class loader. How can I add org.jboss.logmanager to system class loader, and, it's safe to do this?
Update 3
So, I tried to follow some posts on Internet to enable org.jboss.logmanager, changing -Djboss.modules.system.pkgs (I don't know what it does), adding -Djava.util.logging.manager and adding -Xbootclasspath/a:.... Tried multiple combinations of those startup parameters, but it always failed with error or not changing log level names. JBoss LogManager is a multi release jar, so maybe there is something related to it.
Then I build my own custom LoggerFinder implementation, much the same like JBoss LogManager, and tested it in Eclipse with success. In Eclipse I added my jar into classpath user entries of the WF run configuration (don't know what this reflects on WF startup). Now I need to know how to add this jar to WF system class path, I have tried -Xbootclasspath/a:... parameter, but this works partially, my LoggerFinder is loaded, but log messages do not hit log handlers (messages are lost).

log4j1 to log4j2 bridge autoconfiguration is not being created

I followed steps for migrating log4j1 to log4j2 using bridge, https://logging.apache.org/log4j/2.x/manual/migration.html
The thing is it doesn't create automatic configuration even if I set the system property of log4j1.compatibility = true. I don't have idea what is happening because the console doesn't even show any errors that configuration file is missing.
Extra information:
It stopped logging when I replaced log4j 1.2.16 by these three jars
log4j-1.2-api-2.17.1
log4j-api-2.17.1
log4j-core-2.17.1

Not able to print logs to Tomcat's CATALINA_BASE by using log4j2

I have update our code from log4j to log4j 2.17.1 And I want to stored the log file to servers under the Apache tomcat. I am using the log4j2.properties mentioned below.
When I run the code, then the logs file is printed in under code structure(see in below attached screenshot)but I want to print the logs file in QA-Servers under apache tomcat.
Please help me to solve the issue.
TL;DR: use ${sys:catalina.base}.
The property substitution in Log4j 2.x differs from Log4j 1.x (cf. documentation). The most prominent change is that:
in Log4j 1.x ${catalina.base} is looked up in Java system properties and, if the system property does not exist, in the configuration file,
in Log4j 2.x ${catalina.base} is looked up only in the configuration file.
In both cases if the property can not be resolved the placeholder is left unchanged.
In Log4j 2.x all external property lookups must be prefixed using an appropriate prefix. The exact equivalent of Log4j 1.x behavior is ${sys:catalina.base}. Therefore you can use:
# Fallback
property.catalina.base=.
appender.rolling.fileName=${sys:catalina.base}/logs/aseq_wiptmobile_qa-1.applog

Does depedent project in java take log4j config of parent project?

I am having project A and project B, A has jar dependency of project B. I have defined log4j.xml in project A but I am not able to see logs of sub-project(B.jar) in file appender as well as tomcat server console. Does project B will take log4j.xml form parent project A or not then which config does it use?
There is one log4j config for your entire JVM (unless you're working in a containerized environment using class loaders and.... that's not what's described).
Missing log messages implies that the configuration from log4j either (a) isn't what you think it is (i.e. a different log4j.xml is being used) or (b) doesn't have the right settings for the missing log lines.
Adding the following to the JVM at startup may help:
-Dlog4j.debug
It may also be possible to browse the log4j settings via MBeans in jconsole.
If you want all apps (WAR files) in a Tomcat instance to have the same logging configs, the simple solution is to arrange that all WAR files have a copy of the same config file.
If you want the apps to share a common logging framework (with a single configuration), then you should consider using Context Selectors, as described in the Log4j 2 documentation.
Using Context Selectors
There are a few patterns for achieving the desired state of logging separation using ContextSelectors:
Place the logging jars in the container's classpath and set the system property log4j2.contextSelector to org.apache.logging.log4j.core.selector.BasicContextSelector. This will create a single LoggerContext using a single configuration that will be shared across all applications.
Place the logging jars in the container's classpath and use the default ClassLoaderContextSelector. Follow the instructions to initialize Log4j 2 in a web application. Each application can be configured to share the same configuration used at the container or can be individually configured. If status logging is set to debug in the configuration there will be output from when logging is initialized in the container and then again in each web application.
Follow the instructions to initialize Log4j 2 in a web application and set the system property or servlet context parameter log4j2.contextSelector to org.apache.logging.log4j.core.selector.JndiContextSelector. This will cause the container to use JNDI to locate each web application's LoggerContext. Be sure to set the isLog4jContextSelectorNamed context parameter to true and also set the log4jContextName and log4jConfiguration context parameters.
The exact method for setting system properties depends on the container. For Tomcat, edit $CATALINA_HOME/conf/catalina.properties. Consult the documentation for other web containers.
I don't think there is a direct equivalent in Log4j 1.x.

Hibernate log4j not recognizing log4j.properties

I have a hibernate standard java application (not a webapp). Logging already works by default. I would like to see the parameters passed in the sql queries. I have researched that in order to that I need to enable logging. It seems as if hibernate uses slf4j. I have downloaded that jar and its accompanying slf4j-log4j jar. I have added these jars to the classpath. I have also added a log4j.properties to the root of the eclipse project.
I can't seem to have the project recognize that it needs to use slf4j and its properties file.
Do I need to add a reference in my hibernate.cfg.xml?
Make sure you have the property hibernate.show_sql set to true.
format_sql set to true will make the SQL be formatted a bit more pretty.
You may also need to log on TRACE level.
For more details have a look here or here.

Categories