SpringBootPropertySource

because of it's hard code.

private final Map<String, String> properties = Collections
  .singletonMap(ShutdownCallbackRegistry.SHUTDOWN_HOOK_ENABLED, "false");

please first check system.properties ? thanks for your help.

Comment From: takeseem

my fix:

  • in main() try {} finally { log4j2 shutdown }
public static ConfigurableApplicationContext run(String[] args, Class<?>... sources) {
    Properties props = UtilSys.loadProperties("takeseem-framework/application.properties");
    try {
        return new SpringApplicationBuilder(sources).bannerMode(Mode.OFF).properties(props).run(args);
    } catch (RuntimeException e) {
        LogManager.shutdown();
        throw e;
    }
}
  • create my self log4j2 PropertySource in META-INF/services/org.apache.logging.log4j.util.PropertySource
public class Log4j2PropertySource implements PropertySource {
    private String v = "true".equals(System.getProperties().getProperty(ShutdownCallbackRegistry.SHUTDOWN_HOOK_ENABLED)) ? "true" : null;

    @Override
    public int getPriority() {
        return -201;
    }

    @Override
    public String getProperty(String key) {
        return ShutdownCallbackRegistry.SHUTDOWN_HOOK_ENABLED.equals(key) ? v : null;
    }

}

Comment From: takeseem

now I understood must to try { SpringApplication.run() } catch { shutdown log4j2 } in my main(). because of spring context shutdown hook is work fine.

but SpringBootPropertySource, i think it's can not hard code. mybe it's googd:

private final Map<String, String> properties = Collections
  .singletonMap(ShutdownCallbackRegistry.SHUTDOWN_HOOK_ENABLED, 
    "true".equals(System.getProperties().getProperty(ShutdownCallbackRegistry.SHUTDOWN_HOOK_ENABLED)) ? "true" : "false"
  );

Comment From: wilkinsona

Why do you want to use Log4j’s shutdown hook? It is disabled in Spring Boot’s integration because we want to control the shutdown ordering and cannot do that when Log4j is using a separate hook.

Comment From: takeseem

@wilkinsona You are right.

My application uses a mixed stack of Vert.x and Spring Cloud.

  • my case SpringApplication.run() throw a runtime exception. SpringApplication use logger.error the exception, but no time to do logger.shutdown, because of main thread is done.
  • the case may be in product env because of some reasong, but the ELK can not collect the error, sometimes we had to login and tailf the console.log to find why application can't start.

It’s frustrating that despite following the official Log4j2 documentation and trying various methods to set SHUTDOWN_HOOK_ENABLED=true, I was unsuccessful. After spending hours troubleshooting, I discovered the issue was hard coded.

I believe a better approach would be to use the -Dlog4j.shutdownHookEnabled property if the user explicitly sets it, as this would indicate that the user knows what they are doing.

Comment From: wilkinsona

I believe a better approach would be to use the -Dlog4j.shutdownHookEnabled property if the user explicitly sets it, as this would indicate that the user knows what they are doing.

Unfortunately, I'm not sure that we can make that assumption. The user may be setting the property for a couple of different reasons:

  1. They don't know that Boot will shutdown Log4j as part of it's own shutdown processing
  2. They want to override Boot's behavior and are happy with the race condition between Boot's shutdown processing and Log4j's shutdown processing

Let's take a step back and see if we can determine why the exception isn't being logged. To help with that, please provide a minimal sample that reproduces the problem you're seeing.

Comment From: takeseem

I agree with what you said. The exception scenario occurs when SpringApplication.run initializing context.

org.springframework.boot.SpringApplication.run(String...)

at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118) ~[spring-boot-3.4.3.jar:3.4.3]
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112) ~[spring-boot-3.4.3.jar:3.4.3]
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63) ~[spring-boot-3.4.3.jar:3.4.3]
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:353) ~[spring-boot-3.4.3.jar:3.4.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:313) ~[spring-boot-3.4.3.jar:3.4.3]
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:149) ~[spring-boot-3.4.3.jar:3.4.3]
at com.takeseem.framework.spring.boot.UtilBoot.run(UtilBoot.java:22) ~[classes/:?]

Image

I will close the issue, I no longer stick to my mind. Thank you very much for your help.