I have a Spring Boot + Spring Data Redis/KeyValue project. I setup a Spring profile to run the application with all dependencies embedded. So at startup, I launch an embedded Redis Server. Everything works fine when I start it in Eclipse, except that I would like the Redis server to be stopped when I stop the Spring Boot application. So I setup several shutdown hooks, however they are not called when I terminate the application from Eclipse.
They are similar questions on SO, I created this one hoping there would be a Redis solution. Also none of these similar questions are specific to Spring Boot.
I tried many things:
ExitCodeGenerator
; DisposableBean
; @PreDestroy
;None of them are called.
Perhaps there is a Redis option, timeout, keep alive.. something outside the box I am not aware of ? How can I ensure that the Redis Server is stopped when my Spring Boot app is abruptly stopped ?
=> I saw this Embedded Redis for spring boot, but @PreDestroy
is just not called when killing the application unexpectedly.
Here are some of the similar questions:
I also saw this post on eclipse.org discussing how shutdown hook is not called when stopping an application from eclipse: Graceful shutdown of Java Applications
Here's all my relevant code:
Component to start the embedded Redis server at startup (With my attempts to stop it too!!):
@Component
public class EmbeddedRedis implements ExitCodeGenerator, DisposableBean{
@Value("${spring.redis.port}")
private int redisPort;
private RedisServer redisServer;
@PostConstruct
public void startRedis() throws IOException {
redisServer = new RedisServer(redisPort);
redisServer.stop();
redisServer.start();
}
@PreDestroy
public void stopRedis() {
redisServer.stop();
}
@Override
public int getExitCode() {
redisServer.stop();
return 0;
}
@Override
public void destroy() throws Exception {
redisServer.stop();
}
}
application.properties:
spring.redis.port=6379
Spring Boot App:
@SpringBootApplication
@EnableRedisRepositories
public class Launcher {
public static void main(String[] args){
new SpringApplicationBuilder() //
.sources(Launcher.class)//
.run(args);
}
@Bean
public RedisTemplate<String, Model> redisTemplate() {
RedisTemplate<String, Model> redisTemplate = new RedisTemplate<String, Model>();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
return redisTemplate;
}
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName("localhost");
return jedisConnectionFactory;
}
}
Redis server (~ embedded) running:
$ ps -aef | grep redis
... /var/folders/qg/../T/1472402658070-0/redis-server-2.8.19.app *:6379
The embedded Redis maven dependency:
<dependency>
<groupId>com.github.kstyrc</groupId>
<artifactId>embedded-redis</artifactId>
<version>0.6</version>
</dependency>
When using SpringBoot and Eclipse, you can install the STS (Spring Tool Suite) eclipse plugin to achieve graceful shutdown.
Once installed, run the application as a "Spring Boot App" instead of regular "Java application" (Run/debug configurations)
Ensure that the checkbox "Enable Life Cycle Management" checkbox is checked and when you will click on the red square button to stop the application, it will perform a graceful shutdown instead of a hard kill.
Edit:
It's worth noticing that there are two "red square button". One in the "Launch" toolbar and one in the "Console" panel. The one in the launch toolbar still performs hard kill but the one in the console allows the graceful shutdown for spring-boot application (launched with STS)
I had the same problem, though not with Redis. I wanted maximum portability so other developers don't have to add STS if they don't want to. You can add this to any Spring Boot application to offer clean shutdown. Here's what I did, elaborating on the OP's own answer.
Add this to your main class, or any @Configuration
class:
@Bean
public ApplicationRunner systemExitListener() {
return args -> {
if (args.getOptionValues("exitListener") != null) {
System.out.println("Press Enter to exit application");
new Scanner(System.in).nextLine();
System.out.println("Exiting");
System.exit(0);
}
};
}
Then in Eclipse (or in your IDE of choice, or even on the command line), add the argument --exitListener
to activate the code. In Eclipse, that would be in Run Configurations, on the Arguments tab, in the Program Arguments box.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With