Saturday, June 16, 2018

registerShutdownHook() Method in Spring Framework

In the post Spring Bean Life Cycle we have already seen that you can provide destroy methods for your beans to do clean up. One problem is that these destroy callback methods are not executed automatically you do have to call AbstractApplicationContext.destroy or AbstractApplicationContext.close before shutting down the IOC container. There is another option to ensure graceful shutdown, you can register a shutdown hook with the JVM using registerShutdownHook() method in Spring.

Note that this problem is only with non-web applications. Spring’s web-based ApplicationContext implementations already have code in place to shut down the Spring IoC container gracefully when the relevant web application is shut down.

registerShutdownHook() method in Spring

In Java programming language you can create shutdown hooks, where you create a new thread and provide logic that is executed when the JVM is shutting down. Then you can register your thread class instance as a shutdown hook to the VM using Runtime.getRuntime().addShutdownHook(Thread class instance); method.

That is what Spring framework does in the registerShutdownHook() method, it spawns a new thread and in the run() method of the thread call doClose() method. You can check the code in AbstractApplicationContext class.

 public void registerShutdownHook() {
  if (this.shutdownHook == null) {
   // No shutdown hook registered yet.
   this.shutdownHook = new Thread() {
    @Override
    public void run() {
     doClose();
    }
   };
   Runtime.getRuntime().addShutdownHook(this.shutdownHook);
  }
 }

doClose() method in turn calls destroyBeans() method to destroy all cached singletons in the context and closeBeanFactory() method to close the state of the context itself. That ensures a graceful shutdown and calls the relevant destroy methods on your singleton beans so that all resources are released.

Spring registerShutdownHook() method example

There is a class PayServiceImpl which has initialization and destroy methods (methods annotated with @PostConstruct and @PreDestroy).

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class PayServiceImpl implements IPayService{
 
 private IPayment payment;
 private int amount;
 
 public PayServiceImpl(){
  
 }
 public PayServiceImpl(IPayment payment){
  this.payment = payment;
 }
 
 public void performPayment() {
  System.out.println("performPayment Method called");
 }
 
 @PostConstruct
 public void initMethod(){
  System.out.println("Calling InitMethod for PayServiceImpl");
 }
 
 @PreDestroy
 public void destroyMethod(){
  System.out.println("Calling destroyMethod");
 }
 
 public IPayment getPayment() {
  return payment;
 }

 public void setPayment(IPayment payment) {
  this.payment = payment;
 }
}

XML Configuration

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    
    <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
   
    <bean id="payServiceBean" class="org.netjs.exp.Spring_Example.PayServiceImpl">
    </bean>
  
</beans>

Class used to run the code, note that registerShutdownHook(); method is used at the end that will ensure that the destroy method is called.

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main( String[] args ){
        AbstractApplicationContext context = new ClassPathXmlApplicationContext
             ("appcontext.xml");
     IPayService payBean = (IPayService)context.getBean("payServiceBean");

     context.registerShutdownHook();   
    }  
}

Output

Calling InitMethod for PayServiceImpl
Mar 14, 2018 10:30:33 AM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@6193b845: startup date [Wed Mar 14 10:30:32 IST 2018]; root of context hierarchy
Calling destroyMethod

That's all for this topic registerShutdownHook() Method in Spring Framework. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Different Bean Scopes in Spring
  2. ApplicationContextAware And BeanNameAware Interfaces in Spring Framework
  3. Injecting Inner Bean in Spring
  4. Bean Definition Inheritance in Spring
  5. BeanPostProcessor in Spring Framework

You may also like-

  1. How to Read Properties File in Spring Framework
  2. Setter-Based Dependency Injection in Spring
  3. Dependency Injection Using factory-method in Spring
  4. Autodiscovery of Bean Using component-scan in Spring
  5. Serialization in Java
  6. Type Erasure in Java Generics
  7. Covariant Return Type in Java
  8. Literals in Java