Reputation: 3409
I want log4j2-spring.xml to read a property from the application.properties file. But seems log4j2-spring.xml is unable to read this. I have read https://logging.apache.org/log4j/2.x/manual/lookups.html#SpringLookup to implement this.
I have seen this answer on this site. Tried like this as well. But it didn't help me.
My build.gradle is like this:
plugins {
id 'org.springframework.boot' version '2.5.0-SNAPSHOT'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
maven { url 'https://repo.spring.io/snapshot' }
}
ext {
log4j2version = '2.14.1'
}
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.18'
annotationProcessor 'org.projectlombok:lombok:1.18.18'
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-log4j2'
implementation "org.apache.logging.log4j:log4j-spring-cloud-config-client:${log4j2version}"
implementation "org.apache.logging.log4j:log4j-api:${log4j2version}"
implementation "org.apache.logging.log4j:log4j-core:${log4j2version}"
}
configurations {
all {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
exclude group: "ch.qos.logback", module: "logback-classic"
exclude group: "org.springframework.cloud", module: "spring-cloud-bus"
}
}
application.properties file is:
commission.base.path1=C:/Users/user1/Downloads/demo1
logging.config=classpath:log4j2-spring.xml
spring.cloud.config.enabled=false
log4j2-spring.xml is like this:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %-5level %logger{2}:%L - %msg%n"/>
</Console>
<RollingFile name="CATALINA-FILE" fileName="$${spring:commission.base.path1}/logs/catalina.log"
filePattern="$${spring:commission.base.path1}/logs/archived/catalina_%d{yyyy-MM-dd}.log.gz">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{20}:%L - %msg%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="1 GB" />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<root level="debug">
<appender-ref ref="CATALINA-FILE"/>
<appender-ref ref="console"/>
</root>
</Loggers>
</configuration>
But everytime I run the code, I am getting this exception:
2021-05-21 21:28:38,409 main ERROR Unable to create file ${spring:commission.base.path1}/logs/catalina.log java.io.IOException: The filename, directory name, or volume label syntax is incorrect
at java.io.WinNTFileSystem.canonicalize0(Native Method)
at java.io.WinNTFileSystem.canonicalize(WinNTFileSystem.java:428)
at java.io.File.getCanonicalPath(File.java:618)
at java.io.File.getCanonicalFile(File.java:643)
at org.apache.logging.log4j.core.util.FileUtils.makeParentDirs(FileUtils.java:135)
at org.apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory.createManager(RollingFileManager.java:720)
at org.apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory.createManager(RollingFileManager.java:704)
at org.apache.logging.log4j.core.appender.AbstractManager.getManager(AbstractManager.java:113)
at org.apache.logging.log4j.core.appender.OutputStreamManager.getManager(OutputStreamManager.java:100)
at org.apache.logging.log4j.core.appender.rolling.RollingFileManager.getFileManager(RollingFileManager.java:217)
at org.apache.logging.log4j.core.appender.RollingFileAppender$Builder.build(RollingFileAppender.java:146)
at org.apache.logging.log4j.core.appender.RollingFileAppender$Builder.build(RollingFileAppender.java:62)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:122)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1000)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:940)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:932)
at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:551)
at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:241)
at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:287)
at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:627)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:304)
at org.apache.logging.log4j.spring.boot.Log4j2CloudConfigLoggingSystem.loadConfiguration(Log4j2CloudConfigLoggingSystem.java:123)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.loadConfiguration(Log4J2LoggingSystem.java:181)
at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:80)
at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:60)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.initialize(Log4J2LoggingSystem.java:163)
at org.apache.logging.log4j.spring.boot.Log4j2CloudConfigLoggingSystem.initialize(Log4j2CloudConfigLoggingSystem.java:80)
at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:312)
at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:281)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:239)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:216)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:82)
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:63)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:117)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:111)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:62)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:373)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:331)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:144)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.bootstrapServiceContext(BootstrapApplicationListener.java:212)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:117)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:74)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:82)
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:63)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:117)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:111)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:62)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:373)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:331)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1336)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1325)
at com.example.demo1.Demo1Application.main(Demo1Application.java:12)
How to solve this? Thanks in advance.
Upvotes: 3
Views: 4160
Reputation: 3409
I just added
implementation "org.apache.logging.log4j:log4j-spring-boot"
in build.gradle and it is working now.
Implementation of
implementation 'org.springframework.boot:spring-boot-starter-log4j2'
is enough for using log4j2 version 2.14.1 as spring boot version is 2.5.0-SNAPSHOT. No need to add dependencies of org.apache.logging.log4j explicitly for this.
So my final build.gradle is:
plugins {
id 'org.springframework.boot' version '2.5.0-SNAPSHOT'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
maven { url 'https://repo.spring.io/snapshot' }
}
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.18'
annotationProcessor 'org.projectlombok:lombok:1.18.18'
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-log4j2'
implementation "org.apache.logging.log4j:log4j-spring-boot"
}
configurations {
all {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
}
And no need to keep this in application.properties:
spring.cloud.config.enabled=false
And yes, Official Documentation of log4j should add that log4j-spring-boot dependency is enough to implement spring lookup.
Upvotes: 3
Reputation: 19
try this single $ istead of $$
fileName="${spring:commission.base.path1}/logs/catalina.log" filePattern="${spring:commission.base.path1}/logs/archived/catalina_%d{yyyy-MM-dd}.log.gz">
Upvotes: 0
Reputation: 2092
The question is do you need Log4j configuration over Spring Cloud?
Problem
If not, I would say org.apache.logging.log4j:2.14.1 dependency is an overkill. It brings Spring Cloud dependencies that you won't need. In a way that I still didn't figure out, it also interfeeres with spring-boot-starter-log4j2 causing initialization of logging context multiple times and then as a sideffect you have this excpetion at the startup as property from Spring is not resolved.
Solution
Mind you don't need whole log4j-spring-cloud-config-client and even spring-boot-starter-log4j2.
Following dependencies will set up your logging context:
I have put an example program in GitHub repository. Variable names are slightly changed and there are comments explaining what each dependency is for.
Excerpt of Gradle build file
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.18'
annotationProcessor 'org.projectlombok:lombok:1.18.18'
// Spring Boot dependency
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// Logging dependencies
// Base Log4j 2
implementation "org.apache.logging.log4j:log4j-api:${log4j2version}"
// Will resolve spring properties
implementation "org.apache.logging.log4j:log4j-spring-boot:${log4j2version}"
// Log4j 2 to Slf4j binder
implementation "org.apache.logging.log4j:log4j-slf4j-impl:${log4j2version}"
}
Official documentation should say that log4j-spring-boot dependency is enough to resolve lookup variables from Spring configuration files.
But in case you really need to configure Log4J over cloud configurations then again you have to carefully look on how the dependencies are resolved and which ones do you really need.
Upvotes: 2