Does spring have a shutdown process to put cleanup code? - java

When my spring web app shuts down, is there an event I can wireup to somehow that I can perform some cleanup code to empty out some pools etc.

You Could use the following
destroy-method as #amir75 recommends
#PreDestroy annotation
Implement DisposableBean and override destroy method.
All the deatails about these can be found at Disposable Callbacks.

Spring beans have a 'destroy-method' attribute, which will be invoked when you 'close' your context.
<bean id="bean1"
destroy-method="stop"
class="com.example.Bean" />
In order to close it, you'd call the close() method:
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/AbstractApplicationContext.html#close%28%29
(or just shut down the container if appropriate)
Hope that helps..

Based on the JSR-250 specification the best practice to use in modern spring application is the #PreDestroy annotation since using this approach will decouple your beans from Spring.

The non-Spring way to handle this is to write a class that implements ServletContextListener and do your cleanup in its contextDestroyed method. You'd add your class as a context listener in web.xml.

According to the Spring Boot logback example project, you should close the context to clean up the logging system: https://github.com/spring-projects/spring-boot/commit/10402a651f1ee51704b58985c7ef33619df2c110
Example:
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleLogbackApplication.class, args).close();
}

Related

How to integrate a self-test into Spring-Integration?

I want to start a selftest after spring-integration is started. My first approach was to start it after the setup of the integration flow:
#Configuration
#EnableIntegration
#EnableIntegrationManagement
#IntegrationComponentScan
public class FlowConfig {
...
#PostConstruct
public void startSelfTest() {
SelfTest selfTest = new SelfTest(rezeptConfig, dataSource, archiveClient);
selfTest.run();
}
...
}
This does not work because when the test was started the tables in the database were missing because liquibase was not yet started. I guess the liquibase scripts would be started after initialization.
Any ideas what is the best place to start a selftest?
Well, the best practice to do low-level resources interaction is when everything is initialized in the application context already. And that is the phase when beans are started according their SmartLifecycle implementation.
So, what I suggest to revise your solution to be done from some SmartLifecycle.start().
That's exactly what we do everywhere around in Spring Integration.
(Be sure that we talk exactly about the same Spring Integration: https://spring.io/projects/spring-integration)
See more info in docs: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-lifecycle-processor
just guessing, what about onApplicationEvent event in ApplicationListener ? This is called when Spring is initialized and ready.
E.g. check this one How to add a hook to the application context initialization event?
The Liquibase bean which is responsible to create and update the DB tables are started after my Selftest. One solution is to use #DependsOn togehther with the #Bean annotation:
#Bean
#DependsOn("liquibase")
public SelfTest startSelfTest() {
SelfTest selfTest = new SelfTest(rezeptConfig, dataSource, archiveClient);
selfTest.run();
return selfTest;
}
Now the Selftest is started after Liquibase.

How to always intercept a Spring 4.x transaction

We're using Spring 4.x, Hibernate 5.x, Spring-Data 1.11 and we currently have a SQL interceptor that extends org.hiberate.EmptyInterceptor and we basically manually hook that up at the start of the web request using HibernateInterceptor.setInterceptor. We also have jobs that run in the background via Spring task scheduler. These start their own transactions that obviously don't get the interceptor attached to them. What I'm trying to do at this point is to find a way to intercept Spring's #Transactional in all cases.
I've looked into TransactionInterceptor, and #TransactionalEventListener and so far haven't gotten any of them to work, and it's hard to figure out what is currently considered best practice with Spring.
So basically the problem we're trying to solve is that a the end of a transaction we need to know if it failed or succeeded.
So what is the current best practice with Spring to always get pre/post commit events so we can respond as needed?
edit
Realized that the #TransactionalEventListener wouldn't work as we're not using Spring events so it was just a misunderstanding on my part of what that really did.
One way you could do it is to create a simple aspect, something like:
#Aspect
#Component
public class AfterTransactionalAspect {
#After("#annotation(Transactional)")
public void cleanupAfterTransaction(JoinPoint joinPoint) throws Throwable {
// ... Do cleanup work here
}
Another good way to go (if you're using Spring-destined events) would be to use the #TransactionalEventListener.
Are you sure you're using an ApplicationEventPublisher to publish the events? Do you for sure have #EnableTransactionManagement on your config, #TransactionalEventListener is on a public method, TransactionTemplate is set, using #Transactional on the method the publish event occurs?

Spring boot with #RefreshScope #PostConstruct #PreDestroy

In my Spring boot application, we utilize #RefreshScope for dynamic reloading of beans after configuration changes. It works, but I have encountered an issue when combining the #RefreshScope on beans with methods annotated #PostConstruct and #PreDestroy. It seems the #PostConstruct is not called after refresh.
When booting the app, the #PostConstruct method is called normally. When invoking refresh, the #PreDestroy method gets invoked normally as well, and I would expect #PostConstruct to be called on the new proxied bean instance, but it is not. There is important init/destroy-logic going on in these methods, so not having them called is a problem.
Anyone encountered the same problem, and is this a bug or a "feature"? Is there a way to make this work?
Best regards
I faced the same problem today and was able to solve it by calling a method on the #RefreshScope'd bean after the refresh. To accomplish this, I added an event handler for the RefreshScopeRefreshedEvent to the affected bean:
#EventListener
public void onRefreshScopeRefreshed(final RefreshScopeRefreshedEvent event) {
getClass();
}
As you can see it's a quite meaningless implementation, but nevertheless this method call on the bean triggers its initialization (the #PostConstruct method).
This behaviour conforms to the documentation:
Refresh scope beans are lazy proxies that initialize when they are used (i.e. when a method is called),
But still I think that it's really a bug and that #PostConstruct should be called automatically after a refresh.

How to properly shutdown executor services with Spring?

I have a command line application that uses a Spring-managed bean that's composed of a java ExecutorService created with:
ExecutorService service = Executors.newFixedThreadPool(4);
Now, I want my service to shutdown when my application shuts down, so I made my bean implement the DisposableBean interface and have a destroy method such as:
public void destroy(){
service.shutdown();
}
Then I might be tempted to do something like register a shutdown hook on the Spring context. However I found out (the hard way, i.e., in a pre-production release) that this doesn't work: the shutdown hook doesn't get called before the ExecutorService.shutdown() method is called, causing a classic catch 22 problem (it does get called on interruption, i.e., if I hit Ctrl-C while the application is running). This escaped my unit tests because for some reason it seems to work fine from within JUnit, which is still puzzling me: what does JUnit do differently?
The solution I found so far is to explicitly call ApplicationContext.close() right before I exit my main function. I was wondering if there was a better solution to this and what are the best practices for having flexible thread pools managed by Spring. Also what if my bean is not directly managed by Spring but is created by a bean managed by Spring? Should I just cascade the calls to destroy()? Wouldn't this be very error prone?
I appreciate any comments, suggestions, further reading, RTFMs, magic recipes.
Thanks!
Are you aware that this:
ExecutorService service = Executors.newFixedThreadPool(4);
can be replaced with this:
<bean id="service" class="java.util.concurrent.Executors"
factory-method="newFixedThreadPool" destroy-method="shutdown">
<constructor-arg value="4"/>
</bean>
The spring context then manages, more directly, the shutdown of your executor service--and it can be more easily reused.
Per official Spring documentation, when using annotation-based configuration, for destroyMethod field of #Bean, Spring's default behavior is to automatically invoke public, no-arg methods named close or shutdown when the application context is being closed.
As a convenience to the user, the container will attempt to infer a
destroy method against an object returned from the #Bean method. For
example, given an #Bean method returning an Apache Commons DBCP
BasicDataSource, the container will notice the close() method
available on that object and automatically register it as the
destroyMethod. This 'destroy method inference' is currently limited to
detecting only public, no-arg methods named 'close' or 'shutdown'. The
method may be declared at any level of the inheritance hierarchy and
will be detected regardless of the return type of the #Bean method
(i.e., detection occurs reflectively against the bean instance itself
at creation time).
To re-iterate, this is the default behavior for annotation-driven configuration when a destroy method is not explicitly set. If this behavior is undesired explicitly setting destroy method to an empty string will disable this "feature":
To disable destroy method inference for a particular #Bean, specify an
empty string as the value, e.g. #Bean(destroyMethod=""). Note that the
DisposableBean and the Closeable/AutoCloseable interfaces will
nevertheless get detected and the corresponding destroy/close method
invoked.
On the other hand, when using XML configuration, this is not the default behavior... To achieve parity, destroy-method can be explicitly set to (inferred). Refer to the Destruction callbacks and Default initialization and destroy methods sections in the official docs for details.
Consider using Spring's TaskExecutor, which can be configured with a thread pool.
http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html
Just want to add the config based ExecutorService bean creation to #Keith's answer
#Bean("fixedThreadPool")
public ExecutorService fixedThreadPool() {
return Executors.newFixedThreadPool(THREAD_POOL_SIZE);
}

Executing a Java class at application startup using Spring MVC [duplicate]

This question already has answers here:
Execute method on startup in Spring
(13 answers)
Closed 6 years ago.
What is the best way to execute a Java class at application startup using Spring MVC ?
There's not necessarily a "best" way. As usual, there are many ways to do it, and the "best" is whichever fits into your project the best:
Use init-method="..." on a bean element in XML, as cjstehno mentioned
Implement Spring's InitializingBean interface. When deployed in an ApplicationContext, the afterPropertiesSet() method will be called when the bean is created.
Annotate a method on a bean with #PostConstruct. Again, if deployed to an ApplicationContext, the annotated method will be called when the bean is created.
If your bean is more of an infrastructure bean to be tied into the Spring lifecycle, implement ApplicationListener<ContextRefreshedEvent>. The onApplicationEvent(..) method will be called during Spring's startup, and you can do whatever work you need there.
Assuming your context is loaded on startup, create a bean in your spring application context with an init method explicitly called out in the XML config (or implement Springs InitializingBean). If you have lazy-loading enabled you will need to make sure this bean is not lazy.
<bean name="starter" init-method="start" class="com.my.StarterBean" lazy="false" />
(please double-check the params in the docs).
If your context is not loaded on startup you can register an server context listener (part of Servlet API, not Spring).
You can use either implementations:
1) Implement interface InitializingBean. This approach is granted load all your beans then call afterPropertiesSet method.
#Override
public void afterPropertiesSet() throws Exception {
init();
}
2) Using JSR-250's Annotation #PostConstruct. This approach will not wait for spring beans to load.
#PostConstruct
public void init() {
}

Categories