I'm trying to run a Spring Boot project and aws lambda at the same time.
According to .html , the following dependency should be included to make it work:
implementation(".apache.logging.log4j:log4j-slf4j2-impl:VERSION")
.
However, when including the dependency I get the following issue/error from my SAM CLI
SLF4J(W): Class path contains multiple SLF4J providers.
SLF4J(W): Found provider [.apache.logging.slf4j.SLF4JServiceProvider@3c09711b]
SLF4J(W): Found provider [ch.qos.logback.classic.spi.LogbackServiceProvider@5cc7c2a6]
SLF4J(W): See .html#multiple_bindings for an explanation.
SLF4J(I): Actual provider is of type [.apache.logging.slf4j.SLF4JServiceProvider@3c09711b]
Error loading class playground.WebhookEntry: java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Unknown Source)
at java.base/java.lang.Class.forName(Unknown Source)
Caused by: .apache.logging.log4j.LoggingException: log4j-slf4j2-impl cannot be present with log4j-to-slf4j
at .apache.logging.slf4j.Log4jLoggerFactory.validateContext(Log4jLoggerFactory.java:67)
at .apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:49)
at .apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:32)
at .apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:52)
at .apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:32)
at .slf4j.LoggerFactory.getLogger(LoggerFactory.java:432)
at .apache.logging.slf4j.SLF4JLoggerContext.createLogger(SLF4JLoggerContext.java:57)
at .apache.logging.slf4j.SLF4JLoggerContext.getLogger(SLF4JLoggerContext.java:51)
at .apache.logging.slf4j.SLF4JLoggerContext.getLogger(SLF4JLoggerContext.java:40)
at .apache.logging.log4j.spi.LoggerContext.getLogger(LoggerContext.java:46)
at .apache.logging.log4j.LogManager.getLogger(LogManager.java:555)
at playground.WebhookEntry.<clinit>(WebhookEntry.java:15)
... 3 more
I already tried to exclude log4j-to-slf4j
from all the spring dependencies via:
implementation("some.spring.dependency:version) {
exclude(group = ".apache.logging.log4j", module = "log4j-to-slf4j")
}
However, this only resulted in Spring throwing errors instead. I also checked what happens if I do not use the .apache.logging.log4j:log4j-slf4j2-impl dependency. The result is the usage of standard logging or in other words ignoring my log4j2.xml, therefore making a trace log level or policy impossible.
Is there any way to make spring and aws lambdas compatible with the log4j2 logging? And by compatible I mean a way that both (Spring and aws) make use of my log4j2.xml config file.
The minimum code to reproduce the error is the following:
Lambda Entry Point:
package playground;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import .apache.logging.log4j.LogManager;
import .apache.logging.log4j.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class WebhookEntry implements RequestStreamHandler {
private static final Logger LOGGER = LogManager.getLogger(WebhookEntry.class);
@Override
public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
LOGGER.trace("RECEIVED TRACE MESSAGE");
LOGGER.info("RECEIVED INFO MESSAGE");
}
}
Spring App Class:
package playground;
import .springframework.boot.SpringApplication;
import .springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringApp {
public static void main(String[] args) {
SpringApplication.run(SpringApp.class, args);
}
}
build.gradle.kts:
plugins {
id("java")
id(".springframework.boot") version "3.4.1"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
}
repositories {
mavenCentral()
}
dependencies {
testImplementation(platform(".junit:junit-bom:5.10.0"))
testImplementation(".junit.jupiter:junit-jupiter")
implementation(".springframework.boot:spring-boot-starter")
implementation(".springframework.boot:spring-boot-starter-web")
implementation(".springframework.boot:spring-boot-starter-security")
implementation(".springframework.boot:spring-boot-starter-validation")
implementation(".springframework.boot:spring-boot-starter-actuator")
// AWS
implementation("com.amazonaws:aws-lambda-java-core:1.2.3")
implementation("com.amazonaws:aws-lambda-java-events:3.14.0")
implementation("software.amazon.awssdk:sqs:2.30.17")
runtimeOnly("com.amazonaws:aws-lambda-java-log4j2:1.6.0")
// Logging
implementation(".apache.logging.log4j:log4j-core:2.24.3")
implementation(".apache.logging.log4j:log4j-slf4j2-impl:2.24.3")
}
log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n"/>
</Console>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/app-%d{yyyy-MM-dd}.log">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="TRACE">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
I've had a look at the post suggested by Piotr P. Karwasz: Caused by: .apache.logging.log4j.LoggingException: log4j-slf4j-impl cannot be present with log4j-to-slf4j
I tried to solve the issue by the approaches which are mentioned there. However the result is the same as if I would simply exclude log4j-to-slf4j
dependency, which I already tried as stated above. Perhaps I should include the resulting error here as well:
2025-02-21T13:38:18.815452773Z main ERROR Unable to create file logs/app.log java.io.IOException: Could not create directory /var/task/logs
at .apache.logging.log4j.core.util.FileUtils.mkdir(FileUtils.java:129)
at .apache.logging.log4j.core.util.FileUtils.makeParentDirs(FileUtils.java:143)
at .apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory.createManager(RollingFileManager.java:863)
at .apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory.createManager(RollingFileManager.java:844)
at .apache.logging.log4j.core.appender.AbstractManager.getManager(AbstractManager.java:146)
at .apache.logging.log4j.core.appender.OutputStreamManager.getManager(OutputStreamManager.java:112)
at .apache.logging.log4j.core.appender.rolling.RollingFileManager.getFileManager(RollingFileManager.java:307)
at .apache.logging.log4j.core.appender.RollingFileAppender$Builder.build(RollingFileAppender.java:144)
at .apache.logging.log4j.core.appender.RollingFileAppender$Builder.build(RollingFileAppender.java:65)
at .apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:124)
at .apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1180)
at .apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:1099)
at .apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:1091)
at .apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:695)
at .apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:270)
at .apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:319)
at .apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:673)
at .apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:762)
at .apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:784)
at .apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:300)
at .apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:153)
at .apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:46)
at .apache.logging.log4j.LogManager.getContext(LogManager.java:138)
at .apache.logging.log4j.LogManager.getLogger(LogManager.java:555)
at de.trinext.ih_nf_mapper.aws.WebhookEntry.<clinit>(WebhookEntry.java:28)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Unknown Source)
at java.base/java.lang.Class.forName(Unknown Source)
at com.amazonaws.services.lambda.runtime.api.client.HandlerInfo.fromString(HandlerInfo.java:34)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.findRequestHandler(AWSLambda.java:116)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:215)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:180)
2025-02-21T13:38:18.838210717Z main ERROR Could not create plugin of type class .apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile: java.lang.IllegalStateException: ManagerFactory [.apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory@306f16f3] unable to create manager for [logs/app.log] with data [.apache.logging.log4j.core.appender.rolling.RollingFileManager$FactoryData@702b8b12[pattern=logs/app-%d{yyyy-MM-dd}.log, append=true, bufferedIO=true, bufferSize=8192, policy=CompositeTriggeringPolicy(policies=[TimeBasedTriggeringPolicy(nextRolloverMillis=0, interval=1, modulate=true)]), strategy=DefaultRolloverStrategy(min=1, max=7, useMax=true), advertiseURI=null, layout=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n, filePermissions=null, fileOwner=null]] java.lang.IllegalStateException: ManagerFactory [.apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory@306f16f3] unable to create manager for [logs/app.log] with data [.apache.logging.log4j.core.appender.rolling.RollingFileManager$FactoryData@702b8b12[pattern=logs/app-%d{yyyy-MM-dd}.log, append=true, bufferedIO=true, bufferSize=8192, policy=CompositeTriggeringPolicy(policies=[TimeBasedTriggeringPolicy(nextRolloverMillis=0, interval=1, modulate=true)]), strategy=DefaultRolloverStrategy(min=1, max=7, useMax=true), advertiseURI=null, layout=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n, filePermissions=null, fileOwner=null]]
at .apache.logging.log4j.core.appender.AbstractManager.getManager(AbstractManager.java:148)
at .apache.logging.log4j.core.appender.OutputStreamManager.getManager(OutputStreamManager.java:112)
at .apache.logging.log4j.core.appender.rolling.RollingFileManager.getFileManager(RollingFileManager.java:307)
at .apache.logging.log4j.core.appender.RollingFileAppender$Builder.build(RollingFileAppender.java:144)
at .apache.logging.log4j.core.appender.RollingFileAppender$Builder.build(RollingFileAppender.java:65)
at .apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:124)
at .apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1180)
at .apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:1099)
at .apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:1091)
at .apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:695)
at .apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:270)
at .apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:319)
at .apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:673)
at .apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:762)
at .apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:784)
at .apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:300)
at .apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:153)
at .apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:46)
at .apache.logging.log4j.LogManager.getContext(LogManager.java:138)
at .apache.logging.log4j.LogManager.getLogger(LogManager.java:555)
at de.trinext.ih_nf_mapper.aws.WebhookEntry.<clinit>(WebhookEntry.java:28)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Unknown Source)
at java.base/java.lang.Class.forName(Unknown Source)
at com.amazonaws.services.lambda.runtime.api.client.HandlerInfo.fromString(HandlerInfo.java:34)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.findRequestHandler(AWSLambda.java:116)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:215)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:180)
2025-02-21T13:38:18.839409423Z main ERROR Unable to invoke factory method in class .apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile: java.lang.IllegalStateException: No factory method found for class .apache.logging.log4j.core.appender.RollingFileAppender java.lang.IllegalStateException: No factory method found for class .apache.logging.log4j.core.appender.RollingFileAppender
at .apache.logging.log4j.core.config.plugins.util.PluginBuilder.findFactoryMethod(PluginBuilder.java:268)
at .apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:140)
at .apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1180)
at .apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:1099)
at .apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:1091)
at .apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:695)
at .apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:270)
at .apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:319)
at .apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:673)
at .apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:762)
at .apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:784)
at .apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:300)
at .apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:153)
at .apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:46)
at .apache.logging.log4j.LogManager.getContext(LogManager.java:138)
at .apache.logging.log4j.LogManager.getLogger(LogManager.java:555)
at de.trinext.ih_nf_mapper.aws.WebhookEntry.<clinit>(WebhookEntry.java:28)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Unknown Source)
at java.base/java.lang.Class.forName(Unknown Source)
at com.amazonaws.services.lambda.runtime.api.client.HandlerInfo.fromString(HandlerInfo.java:34)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.findRequestHandler(AWSLambda.java:116)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:215)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190)
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:180)
According to this documentation: .html#howto.logging.log4j
I also tried to replace the ch.qos.logback.classic.spi.LogbackServiceProvider (ch.qos.logback:logback-classic) with the log4j-slf4j-impl via build.gradle.kts addition:
modules {
module("ch.qos.logback:logback-classic") {
replacedBy(".apache.logging.log4j:log4j-slf4j-impl", "fix conflict")
}
}