0

I have a very simple Java Weld SE application. According to docs the Weld registers a should hook to shutdown the containers properly. I would expect it tries to shutdown all managed beans properly, but instead it seems the container finishes immediately.

Simple CDI bean:

@ApplicationScoped
public class CDIBean {
    private static final Logger logger = Logger.getLogger(CDIBean.class.getName());
    private AtomicBoolean keepRunning;
    private CountDownLatch threadFinished;

    public void start(@Observes ContainerInitialized event) {
        logger.log(Level.INFO, "start");
    }

    @PostConstruct
    public void postConstruct() {
        logger.log(Level.INFO, "postConstruct");
        keepRunning = new AtomicBoolean(true);
        threadFinished = new CountDownLatch(1);
        new Thread(() -> {
            while (keepRunning.get()) {
                try {
                    logger.log(Level.INFO, "Still running...");
                    Thread.sleep(200);
                } catch (InterruptedException ie) {
                    throw new RuntimeException(ie);
                }
            }
            threadFinished.countDown();;
        }).start();
    }

    @PreDestroy
    public void preDestroy() {
        logger.log(Level.INFO, "preDestroy");
        keepRunning.set(false);
        try {
            threadFinished.await();
        } catch (InterruptedException ie) {
            throw new RuntimeException(ie);
        }
    }
}

And main:

public class Main {
    public static void main(String[] args) {
        Weld weld = new Weld();
        WeldContainer container = weld.beanClasses(CDIBean.class)
                .disableDiscovery().initialize();
    }
}

the console output (app ended by CTRL+C or kill -15, both have the same result):

INFO: WELD-000900: 3.1.3 (Final)
INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
INFO: WELD-ENV-002003: Weld SE container 07a30136-de8f-47f9-ad5f-fbdf85cc5b60 initialized
INFO: postConstruct
INFO: start
INFO: Still running...
INFO: Still running...
INFO: Still running...
INFO: Still running...
INFO: Still running...
INFO: Still running...
^CWeld SE container 07a30136-de8f-47f9-ad5f-fbdf85cc5b60 shut down by shutdown hook

But if the container is shutdown programatically using container.close() the termination works fine:

.
.
.
INFO: Still running...
INFO: Still running...
INFO: preDestroy
INFO: WELD-ENV-002001: Weld SE container 999543ef-ae42-4617-8536-329412f3a9c7 shut down

So my question is: how to make the container shutdown gracefully when SIGTERM is received? The built-in shutdown hook doesn't do that...

bambula
  • 365
  • 1
  • 12

1 Answers1

3

Well, well, well - not Weld but logger made me to be confused. The built-in shutdown hook works as expected, but the logger stops logging into console after the SIGTERM is received. So if I change the body of @PreDestroy method to simple System.out.println("preDestroy"); then it appears in the console as a charm.

bambula
  • 365
  • 1
  • 12
  • Well yes. Most logging libraries have their own shutdown hooks too. – Roddy of the Frozen Peas Dec 06 '19 at 14:51
  • Yes. You're being bitten by https://bugs.openjdk.java.net/browse/JDK-8161253. Specifically, your `Handler`s are being `close()`d in parallel with the container going down, preventing them from outputting your log records. The bug description contains a cumbersome and smelly but effective workaround. – Laird Nelson Dec 13 '19 at 17:38