finbin
finbin

Reputation: 301

Spring Boot @PreDestroy annotation not working

I'm new to Spring Boot, and I've got a Spring Boot application that seems to be ignoring the @PreDestroy annotation - when I run from command line or via Eclipse, I'm never seeing the @PreDestroy code being run when application is shutdown (e.g. via ctrl-c)

Code is below ...

Application.java:

@SpringBootApplication
public class Application {

    @Autowired
    private MessageProcessor messageProcessor;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @PostConstruct
    public void init() {    
        messageProcessor.run();
    }

}

Message Processor Config:

@Configuration
public class MessageProcessorConfiguration {

    @Bean
    public MessageProcessor messageProcessor() {
        return new MessageProcessorImpl();
    }
}

Message Processor:

public class MessageProcessorImpl implements MessageProcessor {

    @Override
    public void run() {

        while (isActive()) {
           …
        }
    }


   @PreDestroy
   public void shutdown() { 
       System.out.println("MessageProcessorImpl - shutting down");
   }

}

Upvotes: 9

Views: 20611

Answers (4)

John Smith
John Smith

Reputation: 96

The @PreDestroy will not be called because the application is not fully initialized yet. This is due the usage of the @PostConstruct on the init method, which is called as part of the initializing of Spring.

This can be fixed by using the CommandLineRunner, which is called after Spring is fully initialized:

@Component
public class Initializer implements CommandLineRunner {

    private final private MessageProcessor messageProcessor;

   public Initializer(MessageProcessor messageProcessor) {
       this.messageProcessor = messageProcessor;

    @Override
    public void run(String[] args) {
        messageProcessor.init();
    }
}

Upvotes: -1

Madhusudan N
Madhusudan N

Reputation: 177

The @PreDestroy does not work when the Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE) is used on the bean since the bean's spawned with this method is not completely managed by the IOC container.

The @PreDestroy works when the Scope(value=ConfigurableBeanFactory.SCOPE_SINGLETON) is used on the bean.

Upvotes: 5

user12059843
user12059843

Reputation: 1

Try adding this line in your xml.

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

Upvotes: -1

MeetJoeBlack
MeetJoeBlack

Reputation: 2924

Spring Boot register shutdown hook during context creation see org.springframework.context.support.AbstractApplicationContext#registerShutdownHookmethod. As result context must be closed on crtl+c combination (if you run your app through java -jar app.jar cmd) and which in turn triggers your @Predestroy method. This works for me.

I don't see any remarks in your code. I can suggest annotating your MessageProcessorImpl bean with @Component annotation instead of a manual @Bean declaration.

Upvotes: 3

Related Questions