How to use log4j.xml for spring boot + log4j2 dependency - java

I have a log4j.xml with a customized appender like:
<appender name="console" class="com.example.MyAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m (%c{1}:%L)"/>
</layout>
</appender>
Recently I upgraded log4j dependency to log4j2, but still using this log4j.xml and it works.
Now, I add a Spring Boot module in my project. Following Spring doc, I set my pom.xml as
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.6.4</version>
</dependency>
And I also add arguments -Dlogging.config=log4j.xml -Dlog4j.configuration=log4j.xml -Dlog4j1.compatibility=true for it.
But my Spring application shows the error and no log output:
ERROR StatusLogger Unknown object "logger" of type org.apache.logging.log4j.core.config.LoggerConfig is ignored: try nesting it inside one of: ["Appenders", "Loggers", "Properties", "Scripts", "CustomLevels"].
Seems log4j2 lib cannot recognize log4j.xml, which means -Dlog4j1.compatibility=true does not work for Spring Boot I think.
Any related config can be utilized or any workaround? Thanks.

TL;DR: The problem is that Log4j2 has two XML configuration factories (for the Log4j 1.x and Log4j 2.x formats), with the 2.x format having higher priority. You need to explicitly set the ConfigurationFactory to use:
-Dlog4j2.configurationFactory=org.apache.log4j.xml.XmlConfigurationFactory
When a Spring Boot application starts Log4j2 is configured twice:
at the very beginning using Log4j2 automatic configuration. For this round you just need to set -Dlog4j1.compatibility=true and call the config file log4j.xml or call the file differently and set -Dlog4j.configuration.
when Spring's environment is ready, Spring reconfigures Log4j2 programmatically using only a subset of Log4j2 automatic configuration. That is why this phase requires many manual settings:
-Dlogging.config=log4j.xml: Spring does not look for a file named log4j.xml,
-Dlog4j1.compatibility=true to activate the Log4j 1.x configuration factories,
-Dlog4j2.configurationFactory=org.apache.log4j.xml.XmlConfigurationFactory to increase the priority of the Log4j 1.x XML configuration factory.
Remark: Using a native Log4j 1.x custom appender exposes you to all the problems (synchronization and performance) of the original Log4j 1.x. For example Log4j 1.x looses events during reconfiguration (as the one performed by Spring Boot), whereas Log4j 2.x does not.

Related

Spring Boot and Logging with External Tomcat

I am deploying my Spring Boot Application on an external Tomcat Server. I can't seem to make my eclipse console display the log messages that I write in my code:
private static final Logger log = LoggerFactory.getLogger(PersonServiceImpl.class);
...
log.info("Running...");
I managed to log all hibernate trace but still can't show the log messages I am adding to my code:
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
logging.level.root=INFO
logging.level.org.springframework.web=INFO
And the catalina log folder doesn't contain the logged infos I am needing.
What should I do?
I think, you deploy your spring boot application in an external tomcat, you package it as war file.
You can check this configuration :
In your pom.xml
<!-- mark the embedded tomcat server as provided -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
and in the packaging value :
<packaging>war</packaging>
In the dependencies, if you use the Web starter :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
it's depends transitively on the logging starter, that means we can only add the starter web dependecy, no more logging component to provide.
And In the application.properties file, add the following lines :
logging.level.org.springframework.web=INFO
logging.level.org.hibernate=INFO
After that, using maven, you can type :
mvn clean package
And move it to your external tomcat :
cp target/project.war apache-tomcat-8.X.X/webapps/project.war
./apache-tomcat-8.X.X/bin/startup.sh
Please configure your application.properties or application.yml
file
application.properties
#Logging pattern for file.
logging.pattern.file= "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
#output to a file
logging.file=/path_to_file/file_name.log
#Logging pattern for console and output.
logging.pattern.console= "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

ERROR StatusLogger No log4j2 configuration file found. While updating the version 2.5.12 of Struts

As per the requirement and for security purpose I am updating Struts project. Before the Struts version is 2.3.24 and now I am updating it to 2.5.12. I have downloaded all the required jar files of Struts and applied to project but I am getting the below error
ERROR StatusLogger No log4j2 configuration file found. Using default
configuration: logging only errors to the console. Set system property
'org.apache.logging.log4j.simplelog.StatusLogger.level' to TRACE to
show Log4j2 internal initialization logging.
But I am not using any logger in my project. I have added all the dependency jar files and I am not using Maven, but added related libraries in lib folder. Any suggestions please.
Struts framework is using a logging framework log4j second version.
Struts 2.3 to 2.5 migration
Please be aware that the framework is using Log4j2 now as a main logging layer, the existing old logging layer is deprecated and will be removed soon. Log4j2 supports many different logging implementations, please check documentations for more details.
The file log4j2.xml is required to bootstrap the logging framework. But it's missing from the classpath. It's also missing from the Struts framework.
You should find some log4j2.xml, i.e. from the struts-showcase application or read a step 4 in this tutorial How To Create A Struts 2 Web Application
Step 4 - Add Logging
To see what’s happening under the hood, the example application for this tutorial uses log4j2. You’ll need to add a dependency node for log4j2 to the pom:
pom.xml log4j dependency node
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
Using both log4j-core and log4j-api allows to use the latest version of Log4j2 without a clash with version provided by the framework. Setup a log4j2.xml configuration in the src/main/resources folder which contains the following
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.opensymphony.xwork2" level="debug"/>
<Logger name="org.apache.struts2" level="debug"/>
<Root level="warn">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
Note the above log4j2 configuration specifies the console as the log target.
No log4j2 configuration file found means log4j2.xml configuration file is not in your classpath.
Check your project jar contains log4j confuguration file or not.
Otherwise you can set log4j confuguration file path as system property in your build script.
<sysproperty key="log4j.configurationFile" value="file:///${basedir}/src/log4j2.xml" />
Check https://logging.apache.org/log4j/2.x/manual/configuration.html for log4j configuration

How to make java.util.logging send logs to Logback?

I'm working on an app that logs using the slf4j api:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
private static final Logger LOG = LoggerFactory.getLogger(FreemarkerEmailPreviewGenerator.class);
...
LOG.error("Error generating email preview", e);
(Code above posted to show classes and packages in use, but pretty standard stuff.)
We use logback configured as follows:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{HH:mm:ss.SSS}] [%thread] [%-5level %logger{26} - %msg]%n
</pattern>
</encoder>
</appender>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
Some of our code makes use of 3rd party libraries that logs with java.util.logging - specifically freemarker. As you can see from the following console log entries, both logback and j.u.l are logging to the console, but they are not using the same config (the logback entries use our pattern, the j.u.l ones don't)
[12:24:38.842] [pool-2-thread-19] [INFO u.o.n.r.l.s.e.t.TemplateLoaderFromService - Finding template workflow/mail/templates/common/workflow-macros.ftl]
[12:24:38.859] [pool-2-thread-19] [INFO u.o.n.r.l.s.e.t.TemplateLoaderFromService - Loaded template workflow/mail/templates/common/workflow-macros.ftl as /workflow/mail/templates/common/workflow-macros.ftl from RegistryMailTemplateService.]
11-Jan-2017 12:24:38 freemarker.log.JDK14LoggerFactory$JDK14Logger error
SEVERE:
Expression domainContact is undefined on line 9, column 74 in workflow/mail/templates/common/workflow-macros.ftl.
The problematic instruction:
----------
==> ${domainContact.name} [on line 9, column 72 in workflow/mail/templates/common/workflow-macros.ftl]
Is it possible to make j.u.l logging use the logback config so that we have a single consistent logging config for the whole app?
Your application needs to have the following jars:
Application -> Freemarker -> java.util.logging -> SLF4J Api: jul-to-slf4j.jar
Application -> SLF4J API: slf4j-api.jar
SLF4J API -> logback: logback-classic.jar and logback-core.jar
Since your application already contains slf4j-api.jar and logback-classic.jar, you probably only have to add the jul-to-slf4j.jar
If you use maven:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.22</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.8</version>
</dependency>
logback classic will transitively add logback-core and slf4j-api

Log4j seems not to work in Spring Boot

I tried to add Spring and Maven to one of my existing project, and I find that no matter how I configure, the logging seems to be out of my control.
I tried putting the log4j.properties in src/main/java and src/main/resources(Actually I am not sure where to put).
But when I use Log4j to log, the log displays in the console only, though I configure it into a file.
My log4j.properties is like:
log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.FileAppender
log4j.appender.A1.encoding=utf-8
log4j.appender.A1.File=E:\Programminglog\debug.log
log4j.appender.A1.Threshold = DEBUG
log4j.appender.A1.Append=true
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
I am not sure if I miss something or Spring overrides some settings, since I am new to Maven and Spring.
PS: Before I add dependencies of Log4j in pom.xml,no compile errors though I use org.apache.log4j.Logger
This is how my application.java looks like:
#Configuration
#EnableAutoConfiguration
#ComponentScan({"hello","wodinow.weixin.jaskey"})
public class Application extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
LogUtil.info("Application Boots!");// here this line does not show in the file
}
#Bean
public CommandService commandService(){
return CommandService.getInstance();
}
}
If you are using log4j with spring-boot then you have to add dependency with "exclusions" in your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.3.3.RELEASE</version>
**<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>**
</dependency>
**<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>**
Please follow this. It will resolve your problem.
http://www.atechref.com/blog/maven/spring-boot-using-log4j-logging/
UPDATE
By default, If you use the ‘Starter POMs’, Logback will be used for logging
(From: Spring Boot Reference, Chapter 25 Logging)
So either you configure your logging via logback logback.xml or you include the log4j libs. (when you need more help with including the lib then please post your pom.xml)
I reccomend to use logback (and slf4j)
OLD:
put the log4j.properties file in src\main\resources (not in ...\java)
make sure that it is named log4j.properties (in your question you named the file log4j.propertie)
add this lines to your web.xml
web.xml:
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
(#see Initializing Log4J with Spring?)
I ran into this exact problem, it turned out that spring boot includes Spring Boot Starter Logging and will ignore anything you add while that is still there. I was able to fix it by double clicking on my pom and clicking on Spring-Boot-Starter-Logging and then selecting "edit starters" then removing the spring boot starter logging.
If you are using some other kind of dependency management system the idea is the same, just carefully review anything that spring boot included in your project and make sure that log4J is the only logging system included.

How to configure hibernate logging using log4j2.xml?

I recently switched to Apache log4j2, and still can not find a way to configure hibernate logging using log4j2.xml.
Because I can not find a way around this problem I still use log4j.properties file explicitly for hibernate. This is not the best solution since my log4j2.xml uses JPA appender (writes logs to db). I do not want to write separate logic for hibernate.
Is there a way to configure hibernate logging using log4j2?
As suggested in
https://issues.apache.org/jira/browse/LOG4J2-172
you can add system property to force hibernate use slf4j
-Dorg.jboss.logging.provider=slf4j
also log4j-slf4j-impl should be added to classpath
My custom solution:
with Spring you can place
org.jboss.logging.provider=slf4j
in property file
(envConfigLocation is file url)
<bean id="propertyConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location" ref="envConfigLocation" />
<property name="order" value="1"/>
</bean>
I found an answer to this question at: How to redirect all logs from hibernate and spring to log4j2?
Basically log4j2 doesn't work with Hibernate so you have to use log4j. But you still use your log4j2 configuration. You need the following dependencies and then the magic happens in the background.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<!--HIBERNATE LOGGER (log4j)-->
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.6</version>
</dependency>
It is possible to redirect calls to the log4j-1.x API to the log4j-2.0 implementation. The FAQ about which jars to include explains how to do this. You probably need to remove the old log4j-1.x jar from the classpath when you do this.

Categories

Resources