Archimedes Trajano
Archimedes Trajano

Reputation: 41750

How do I know if a Spring boot application is shutting down?

I have some @Scheduled events in my app and I was wondering how can I determine whether a request to shut down the Spring boot app was triggered so I don't bother doing extra work?

That is I want to avoid errors like this e.g.


java.lang.IllegalStateException: Shutdown in progress
        at java.base/java.lang.ApplicationShutdownHooks.add(ApplicationShutdownHooks.java:66) ~[na:na]
        at java.base/java.lang.Runtime.addShutdownHook(Runtime.java:214) ~[na:na]
        at org.xbill.DNS.NioClient.selector(NioClient.java:57) ~[dnsjava-3.5.0.jar:na]
        at org.xbill.DNS.NioUdpClient.sendrecv(NioUdpClient.java:158) ~[dnsjava-3.5.0.jar:na]
        at org.xbill.DNS.SimpleResolver.sendAsync(SimpleResolver.java:371) ~[dnsjava-3.5.0.jar:na]
        at org.xbill.DNS.SimpleResolver.sendAsync(SimpleResolver.java:338) ~[dnsjava-3.5.0.jar:na]
        at org.xbill.DNS.lookup.LookupSession.lookupWithResolver(LookupSession.java:477) ~[dnsjava-3.5.0.jar:na]
        at org.xbill.DNS.lookup.LookupSession.lambda$lookupWithCache$6(LookupSession.java:472) ~[dnsjava-3.5.0.jar:na]
        at java.base/java.util.Optional.orElseGet(Optional.java:364) ~[na:na]
        at org.xbill.DNS.lookup.LookupSession.lookupWithCache(LookupSession.java:472) ~[dnsjava-3.5.0.jar:na]
        at org.xbill.DNS.lookup.LookupSession.lookupUntilSuccess(LookupSession.java:448) ~[dnsjava-3.5.0.jar:na]
        at org.xbill.DNS.lookup.LookupSession.lookupAsync(LookupSession.java:385) ~[dnsjava-3.5.0.jar:na]
        at org.xbill.DNS.lookup.LookupSession.lookupAsync(LookupSession.java:367) ~[dnsjava-3.5.0.jar:na]
        at net.trajano.swarm.gateway.discovery.Util.getIpAddresses(Util.java:93) ~[classes/:na]
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:273) ~[na:na]
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na]
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na]
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
        at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312) ~[na:na]
        at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na]
        at net.trajano.swarm.gateway.discovery.DockerServiceInstanceLister.refresh(DockerServiceInstanceLister.java:77) ~[classes/:na]
        at net.trajano.swarm.gateway.discovery.DockerEventWatcher$DockerEventWatcherEventCallback.onNext(DockerEventWatcher.java:81) ~[classes/:na]
        at net.trajano.swarm.gateway.discovery.DockerEventWatcher$DockerEventWatcherEventCallback.onNext(DockerEventWatcher.java:49) ~[classes/:na]
        at com.github.dockerjava.core.exec.AbstrAsyncDockerCmdExec$1.onNext(AbstrAsyncDockerCmdExec.java:41) ~[docker-java-core-3.2.13.jar:na]
        at com.github.dockerjava.core.DefaultInvocationBuilder$JsonSink.accept(DefaultInvocationBuilder.java:315) ~[docker-java-core-3.2.13.jar:na]
        at com.github.dockerjava.core.DefaultInvocationBuilder$JsonSink.accept(DefaultInvocationBuilder.java:298) ~[docker-java-core-3.2.13.jar:na]
        at com.github.dockerjava.core.DefaultInvocationBuilder.lambda$executeAndStream$1(DefaultInvocationBuilder.java:275) ~[docker-java-core-3.2.13.jar:na]
        at java.base/java.lang.Thread.run(Thread.java:831) ~[na:na]

Upvotes: 0

Views: 1914

Answers (2)

SKO
SKO

Reputation: 50

As you might have noticed, it has a problem of duplicating a status. So it has been fixed, and you can autowire ConfigurableApplicationContext and use boolean isClosed() to achieve your goal very easily.

Upvotes: 0

Allen D. Ball
Allen D. Ball

Reputation: 2026

You can catch the ContextClosedEvent:

...
import org.springframework.context.event.ContextClosedEvent;
...
@RestController
public class Application {
    ...
    boolean isShuttingDown = false;
    ...
    @EventListener({ ContextClosedEvent.class })
    public void onApplicationEvent(ContextClosedEvent event) {
        isShuttingDown = true;
    }
    ...
}

Upvotes: 3

Related Questions