Running SpringBootApplication PostConstruct and PreDestroy

14,149

Solution 1

From the documentation:

docker stop

Stop one or more running containers The main process inside the container will receive SIGTERM, and after a grace period, SIGKILL

By executing docker stop you are just killing the java (Spring) process.

So what are the guarantees that Spring context will shutdown properly?

The right way to handle SIGTERM in Spring applications is to add shutdown hook.

The final code should look like this:

package com.pack;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

@SpringBootApplication
public class AnalysisServiceBootstrap {

    @PostConstruct
    public void start() throws Exception {
        // some init code
    }

    @PreDestroy
    public void tearDown() {
       // some destroy code
    }

    public static void main(String[] args) {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                // write here any instructions that should be executed
                tearDown();
            }   
        });


        SpringApplication.run(AnalysisServiceBootstrap.class, args);
    }
}

The process is described in the following questions:

Solution 2

Register a shutdown hook to the application as mentioned here Spring Boot shutdown hook

Each SpringApplication will register a shutdown hook with the JVM to ensure that the ApplicationContext is closed gracefully on exit. All the standard Spring lifecycle callbacks (such as the DisposableBean interface, or the @PreDestroy annotation) can be used.

Share:
14,149
sapwood
Author by

sapwood

Updated on June 23, 2022

Comments

  • sapwood
    sapwood almost 2 years

    I have troubles with running spring application in docker container (both spring and docker have latest versions in my environment). I want to have healthy life cycle for application class AnalysisServiceBootstrap: to run initialization code with method start() right AFTER creation of AnalysisServiceBootstrap and also to run method stop() right BEFORE destruction of AnalysisServiceBootstrap (I want to run stop() code when someone stops the application).

    I have following code:

    package com.pack;
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.context.web.SpringBootServletInitializer;
    
    @SpringBootApplication
    public class AnalysisServiceBootstrap {
    
        // called OK on docker "start <containerId>"
        @PostConstruct
        public void start() throws Exception {
            // some init code
        }
    
        // NOT called on "docker stop <containerId>"
        @PreDestroy
        public void stop() {
           // some destroy code
        }
    
        public static void main(String[] args) {
            SpringApplication.run(AnalysisServiceBootstrap.class, args);
        }
    }
    

    For some reason I can not get method stop() running on docker stop. I tried several ways offered on stackoverflow and other resources, but all of them did not work for me.

    I will be glad to have code that works for you (not just some vogue suggestions).

    Here is almost exact docker file of mine:

    FROM *********:6556/service-jvm
    
    ARG SERVICE_JAR_FILE
    
    ENV SERVICE_NAME service
    ENV HTTP_PORT 603
    ENV HTTPS_PORT 604
    ENV SERVICE_JAR /opt/my/project/${SERVICE_JAR_FILE}
    EXPOSE ${HTTP_PORT} ${HTTPS_PORT}
    COPY ${SERVICE_JAR_FILE} /opt/my/project/${SERVICE_JAR_FILE}
    
    CMD java -Xms1024m -Xmx1024m -dump:"/opt/my/project/dumppath" -javaagent:/opt/my/project/agent.jar -Djav.awt.headless=true -jar ${SERVICE_JAR} 
    

    But you are invited to post here any working docker file that you have.

    Thanks a lot.

  • M. Deinum
    M. Deinum about 7 years
    Spring Boot automatically registers a shutdown hook, so no need to do this. However when a SIGKILL is received no amount of shutdown hooks will help.
  • sapwood
    sapwood about 7 years
    It is not working code. You call there stop() of Thread instead of calling stop of my class.
  • Andrii Abramov
    Andrii Abramov about 7 years
    @M.Deinum regarding SIGKILL you are absolutely right. So what is the workaround for this?
  • M. Deinum
    M. Deinum about 7 years
    You have to properly start your application inside your container (but as you haven't added the Dockerfile to your question that is hard to answer. But the problem probably lies in there.
  • PawelS
    PawelS almost 3 years
    I spent whole day looking for it, maybe someone will found it useful also (thanks M. Deinum for tip): For @PreDestroy and Dockerfile -> ensure to use ENTRYPOINT instead of CMD or RUN - only then you will run application as a main process and SIGTERM will be sent to your application