Spring Boot automatically initializes the underlying logging system using the LoggingApplicationListener
. This is a nice thing if the application I'm developing runs isolated or standalone.
However I'm developing a web application that will be deployed into the WSO2 Application Server, which offers unified logging (using log4j), with features like central log level management (at runtime via web interface), business reporting etc.
If I use Spring Boot "as is", it logs everything completely on its own. My first shot was, to remove spring-boot-starter-logging
and manually add slf4j-api
as provided
. This works to some extent, since the LoggingApplicationListener
now overrides settings of the global logmanager provided by WSO2 (and even causes global appenders to be closed).
The only "solution" I came up with is to remove the listener via reflection. Then Spring Boot starts to behave exactly as it should (logging via the global logger and not overriding the pre defined log levels, output formats, appenders, etc.)
That "solution" looks like this:
@SpringBootApplication
public class MyApp extends SpringBootServletInitializer {
public static void main(String... args) {
SpringApplication.run(MyApp.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
try {
Field appField = SpringApplicationBuilder.class.getDeclaredField("application");
appField.setAccessible(true);
SpringApplication app = (SpringApplication)appField.get(builder);
Field listenersField = SpringApplication.class.getDeclaredField("listeners");
listenersField.setAccessible(true);
List<ApplicationListener<?>> listeners = (List<ApplicationListener<?>>) listenersField.get(app);
for (int i = listeners.size() - 1; i >= 0; --i) {
if (listeners.get(i) instanceof LoggingApplicationListener) {
listeners.remove(i);
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return builder.sources(MyApp.class);
}
}
Is there any better solution to my problem that's maybe less hacky which I may have overlooked during my research and code analysis?
thank you for you post it is very helpful. I had the same problem with Websphere Aplication Server: After spring boot context initialized I had no more logs. This solution is equivalent but less dirty by overriding the run method of SpringBootServletInitializer:
@Override
protected WebApplicationContext run(SpringApplication application) {
Collection<ApplicationListener<?>> listeners =
new ArrayList<>();
for (ApplicationListener<?> listener: application.getListeners()) {
if (!(listener instanceof LoggingApplicationListener)) {
listeners.add(listener);
}
}
application.setListeners(listeners);
return super.run(application);
}
Since Spring Boot 1.4 the LoggingSystem autoconfiguration can be disabled.
Take a look at the Custom Log Configuration section of the Spring documentation:
You can force Spring Boot to use a particular logging system by using the
org.springframework.boot.logging.LoggingSystem
system property. The value should be the fully qualified class name of aLoggingSystem
implementation. You can also disable Spring Boot’s logging configuration entirely by using a value ofnone
.
For Tomcat, for example, set the environment variable JAVA_OPTS
:
JAVA_OPTS="-Dorg.springframework.boot.logging.LoggingSystem=none"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With