How to properly shutdown executor services with Spring? - java

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);
}

Related

Spring transaction not being created when invoking #Transactional method via reflection

I have a class that is invoking a public method on another class via reflection. The invoking class already has an active transaction, and the public method on the invoked class is marked with
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void handleProcess() { ..}
The invocation looks like
Runnable runnable = null;
Method handleMethod = config.handleProcessMethod;
Object handler = autowireHandler(process);
runnable = () -> {
LOGGER.info("executing method {} on {}",handleMethod,handler);
handleMethod.invoke(handler);
};
runnable.run();
The method is called correctly, but the log indicates that it is particpating in the current transaction instead of creating a new one.
08:54:33.452 [process-executor-2] DEBUG o.springframework.orm.jpa.JpaTransactionManager - Found thread-bound EntityManager ... for JPA transaction
08:54:33.453 [process-executor-2] DEBUG o.springframework.orm.jpa.JpaTransactionManager - Participating in existing transaction
Edit: Actually the logs from above are being created within the invoked method, caused by a JPA repository, not prior to it. So it looks like the #Transactional annotation isn't being processed at all.
Is the reflection causing spring to miss the #Transactional annotation? I need the invoked method to use it's own transaction so that it's committed prior to returning from the invocation.
The annotation tells Spring what to wrap with a proxy that implements the transactional behavior. Reflection is bypassing that proxy and calling the wrapped method directly. Looking at the logs should confirm that, you may need to dial up log level for spring stuff.
Don't use reflection for this, because that's going behind Spring's back and it can't help you. You can autowire a list of services that implement a common interface. Your code can go through the list and figure out which one is relevant to what you need to do, then call the method on the chosen service.
If you are submitting tasks to an executor, you are going to have trouble when there is no entitymanager found on the worker thread. If you make these services use Spring async methods instead, that will let Spring handle the transactions, entityManager, etc.

Why has an #ApplicationScoped bean a new instance in the BeforeShutdown phase of my CDI extension ?

I would like to make some clean up on a bean when I shutdown a CDI application. For example, I would like to close an IO connection. Of course, here, the bean is marked as #ApplicationScoped.
To manage this I wrote an extension and observe the BeforeShutdown event, and then I select my bean to call a clean up method :
public void beforeShutdown(#Observes BeforeShutdown beforeShutdown) {
SomeBean obj = CDI.current().select(SomeBean.class).get();
obj.cleanup();
}
My problem is that I have access to a new instance in this method. Not the instance I got in the whole application.
If you want to see this instance problem, I've made a repo on github to show it : https://github.com/hasalex/cdi-extension-demo.
So I have 2 questions :
Why do I get a new instance ?
Is there an other way to cleanup my bean at the end of the application ? (in SE and in WildFly environments)
look here: http://docs.jboss.org/cdi/spec/1.1.EDR1/html/spi.html#provider
11.5.4. BeforeShutdown event
The container must fire a final event after it has finished processing requests and destroyed all contexts.
Maybe you want to use #PreDestroy: http://docs.oracle.com/javaee/6/tutorial/doc/gmgkd.html
Annotate the declaration of the method with the javax.annotation.PreDestroy annotation.
CDI calls this method before starting to destroy the bean.

Global object in Grails

Writing a small web-app in Grails I encountered a problem with global objects. I have a class which runs threads - ExecutorService with queuing.
The problem is where to create an object of this class, to have it available in Controller?
I've tried at init (BootStrap) but there's no chance then of getting its instance anywhere else.
In general - what I need is an object in one single instance for whole application, with access from Model and/or Controller.
In general - what I need is an object in one single instance for whole application, with access from Model and/or Controller.
The standard way to achieve this is to declare the object as a Spring bean in grails-app/conf/spring/resources.groovy
threadPool(java.util.concurrent.Executors) { bean ->
bean.factoryMethod = "newCachedThreadPool"
}
Then in controllers/services/etc. you can inject this bean the same as you would with grails services, i.e.
def threadPool
But in this case you may find it easier simply to use the executor plugin, which defines such a bean for you and handles the intricacies of ensuring there is a valid GORM session available to the background tasks.
Why not wrap your Executorservice inside a Spring Bean, or using something like:
grailsApplication.controllerClasses.each {controller ->
controller.metaClass.executorService = { ->
executorService
}
}
Actually I have come to something before checking answers.
For a given domain class (Example) and controller (ExampleController) create
ExampleService
and simply include all the needed things there. Set behaviour to #Singleton (default).
Then in Controller inject the instance as follows:
def exampleService

Does spring have a shutdown process to put cleanup code?

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();
}

Is it possible to destroy a CDI scope?

I'm working on a Java EE application, primarily JAX-RS with a JSF admin console, that uses CDI/Weld for dependency injection with javax.enterprise.context.ApplicationScoped objects. Minor debugging issues aside, CDI has worked beautifully for this project.
Now I need some very coarse-grained control over CDI-injected object lifecycles. I need the ability to:
Remove an injected object from the application context, or
Destroy/delete/clear/reset/remove the entire application context, or
Define my own #ScopeType and implementing Context in which I could provide methods to perform one of the two above tasks.
I'm fully aware that this is across, if not against, the grain of CDI and dependency injection in general. I just want to know
Is this remotely possible?
If yes, what is the easiest/simplest/quickest/foolproofiest way to get the job done?
Weld Reference Documentation Section 2.1.2
Keep in mind that once a bean is bound
to a context, it remains in that
context until the context is
destroyed. There is no way to manually
remove a bean from a context. If you
don't want the bean to sit in the
session indefinitely, consider using
another scope with a shorted lifespan,
such as the request or conversation
scope.
Custom scope example Porting the veiwscoped jsf annonation to cdi
If you really don't want to take the path of the Custom scope type.. You can use a non-portable method by using BeanManager.getContext method and cast this context in a weld AbstractSharedContext to have access to the beanstore or the cleanUp() method of the context.
Check this thread on how to get a BeanManager instance for your environment
A custom scope which might fit your needs is available at https://github.com/openknowledge/openknowledge-cdi-extensions/tree/master/openknowledge-cdi-scope/src/main/java/de/openknowledge/cdi/scope Maybe you have to adjust the implementation a bit.
Out of the box there is only the Conversation scope that gives you total control on its lifecycle. But you can create your own scope if conversation doesn't suit your needs.
Creating a scope is a tough job, but you can go to weld code and look how conversation was implemented.
In CDI 1.1 there is a javax.enterprise.context.spi.AlterableContext interface, which allows you to individually destroy a bean instance. All normal scopes (request, conversation, session) are alterable.
AlterableContext ctxConversation = (AlterableContext) beanManager.getContext(ConversationScoped.class);
for (Bean<?> bean : beanManager.getBeans(Object.class)) {
Object instance = ctxConversation.get(bean);
if (instance != null) {
ctxConversation.destroy(instance);
}
}
The beanManager here is a javax.enterprise.inject.spi.BeanManager instance. You can get it via JNDI lookup:
InitialContext.doLookup("java:comp/BeanManager");
or via CDI static method:
CDI.current().getBeanManager();
, but be aware of the issues with the static method in some Weld versions:
javax.enterprise.inject.spi.CDI implementation does not support multiple deployments;
CDI.current().getBeanManager() returns a beanmanager from a different deployment.

Categories