Spring Boot: LoggingApplicationListener interfering with Application Server logging

戏子无情 提交于 2019-12-30 06:07:41

问题


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?


回答1:


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);
    }



回答2:


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 a LoggingSystem implementation. You can also disable Spring Boot’s logging configuration entirely by using a value of none.

For Tomcat, for example, set the environment variable JAVA_OPTS:

JAVA_OPTS="-Dorg.springframework.boot.logging.LoggingSystem=none"


来源:https://stackoverflow.com/questions/29609996/spring-boot-loggingapplicationlistener-interfering-with-application-server-logg

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!