In a spring bean is it possible to have a shutdown method which can use transactions?
shutdown, spring
Solution
Interesting Question. I'd say you should be able to do it by letting your bean implement `SmartLifeCycle`.
That way, if your `int getPhase();` method returns `Integer.MAX_VALUE`, it will be among the first to be called when the `ApplicationContext` finally shuts down.
Reference:
- 3.6.1.5 Startup and shutdown callbacks
- `SmartLifeCycle` javadocs
Problem
In the destroy method of a spring bean I want to execute some queries to clean up some stuff in the database. Spring doesn't seem to allow this by any means I can find. The error is always something like: Invocation of destroy method failed on bean with name 'someBean': org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'transactionManager': Singleton bean creation not allowed while the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!) The following will tell spring to call shutdownDestroy after the bean is no longer needed. But, I get the above error when trying to use transactions. ``` <bean id="someId" name="someName" class="someClass" destroy-method="shutdownDestroy"/> ``` The same is true when I enable common lifecycle annotations using: ``` <bean class="org.springframework. ... .CommonAnnotationBeanPostProcessor"/> ``` and then mark the method with `@PreDestroy`. That method can't use transactions either. Is there any way to do this? EDIT: Thanks! I had the bean implement SmartLifecycle and adding the following and it works very nicely. ``` private boolean isRunning = false; @Override public boolean isAutoStartup() {return true;} @Override public boolean isRunning() {return isRunning;} /** Run as early as possible so the shutdown method can still use transactions. */ @Override public int getPhase() {return Integer.MIN_VALUE;} @Override public void start() {isRunning = true;} @Override public void stop(Runnable callback) { shutdownDestroy(); isRunning = false; callback.run(); } @Override public void stop() { shutdownDestroy(); isRunning = false; } ```