Clean shutdown Spring Integration and Spring Boot when using ThreadPoolTaskExecutor - spring-integration

I am using Spring Integration and Spring Boot for some development on my location machine based on the Spring Guides. I am using Gradle to build and run the application. The following code is used to bootstrap Spring and I can terminate the application by pressing the enter key.
public class Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = new SpringApplication(Application.class).run(args);
System.out.println("Hit Enter to terminate");
System.in.read();
ctx.close();
}
}
This works fine but when I introduce a ThreadPoolTaskExecutor into the integration flow, the application never terminates. I have to use ^C to kill the application. The code I am using is as follows.
...
channel(MessageChannels.executor(myTaskExecutor()))
...
#Bean
public ThreadPoolTaskExecutor myTaskExecutor() {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
pool.setCorePoolSize(10);
pool.setMaxPoolSize(20);
pool.setWaitForTasksToCompleteOnShutdown(true);
pool.setAwaitTerminationSeconds(1);
pool.initialize();
return pool;
}
I have:
Tried to shutdown the executor (using the shutdown()) method) before and after the context is closed.
Tried the above code also within the onApplicationEvent(ContextClosedEvent event) method.
Temporarily commenting the code which is run in the thread to make sure that is not holding on to the thread in any way.
Is there any anything else I need to do?

ctx.close() will shutdown any executor beans (by calling the destroy() method), so it is likely you have a thread "stuck" somewhere.
Take a Thread dump (jstack) to see what the executor thread is doing.

Related

How to Kill Apache Camel Parent Thread after process complete successfully in Standalone Application?

I start Camel Main Standalone application using Unix Scheduler.
It initiates Routes; But as i have Thread.sleep(time) after context.start().
Now application first execute; whatsoever in routes; and when route finish processing(stop(), application still working and finishes when thread.sleep time over.
Any idea how to completely stop the standalone application after my route finish process?
Following is code snippet for reference:
SimpleRegistry sr = new SimpleRegistry();
sr.put("masterdata", dataSource);
CamelContext context = new DefaultCamelContext(sr);
try {
context.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("timer://alertstrigtimer?period=60s&repeatCount=1")....
from("etc").....
from("etc").....
from("etc").stop()
}})
context.start();
Thread.sleep(30000);
} catch (Exception e) {
LOGGER.warn("configure(): Exception in creationg flow:", e);
}
Is any way within camel or may be in java to kill the thread after camel route stop all processing.
You have different options, here some I would consider:
use camel-main and configure it to shut-down when a certain amount of the exchanges are done
use a route policy and shut-down the camel context according to your own rule

Injection in Quartz Jobs (JSF + CDI) [duplicate]

I would like to know if it's ok to use Timer inside application scoped beans.
Example, lets say that I want to create a timer task that sends out a bunch of emails to every registered member one time per day. I'm trying to use as much JSF as possible and I would like to know if this is acceptable (it sounders a bit weird, I know).
Until now I have used all of the above inside a ServletContextListener. (I don't want to use any application server or cron job and I want to keep
the above things inside my web app.)
Is there a smart JSF way of doing this or should I stick with the old pattern?
Introduction
As to spawning a thread from inside a JSF managed bean, it would only make sense if you want to be able to reference it in your views by #{managedBeanName} or in other managed beans by #ManagedProperty("#{managedBeanName}"). You should only make sure that you implement #PreDestroy to ensure that all those threads are shut down whenever the webapp is about to shutdown, like as you would do in contextDestroyed() method of ServletContextListener (yes, you did?). See also Is it safe to start a new thread in a JSF managed bean?
Never use java.util.Timer in Java EE
As to using java.util.Timer in a JSF managed bean, you should absolutely not use the old fashioned Timer, but the modern ScheduledExecutorService. The Timer has the following major problems which makes it unsuitable for use in a long running Java EE web application (quoted from Java Concurrency in Practice):
Timer is sensitive to changes in the system clock, ScheduledExecutorService isn't.
Timer has only one execution thread, so long-running task can delay other tasks. ScheduledExecutorService can be configured with any number of threads.
Any runtime exceptions thrown in a TimerTask kill that one thread, thus making Timer dead, i.e. scheduled tasks will not run anymore. ScheduledThreadExecutor not only catches runtime exceptions, but it lets you handle them if you want. Task which threw exception will be canceled, but other tasks will continue to run.
Apart from the book quotes, I can think of more disadvantages:
If you forget to explicitly cancel() the Timer, then it keeps running after undeployment. So after a redeploy a new thread is created, doing the same job again. Etcetera. It has become a "fire and forget" by now and you can't programmatically cancel it anymore. You'd basically need to shutdown and restart the whole server to clear out previous threads.
If the Timer thread is not marked as daemon thread, then it will block the webapp's undeployment and server's shutdown. You'd basically need to hard kill the server. The major disadvantage is that the webapp won't be able to perform graceful cleanup via e.g. contextDestroyed() and #PreDestroy methods.
EJB available? Use #Schedule
If you target Java EE 6 or newer (e.g. JBoss AS, GlassFish, TomEE, etc and thus not a barebones JSP/Servlet container such as Tomcat), then use a #Singleton EJB with a #Schedule method instead. This way the container will worry itself about pooling and destroying threads via ScheduledExecutorService. All you need is then the following EJB:
#Singleton
public class BackgroundJobManager {
#Schedule(hour="0", minute="0", second="0", persistent=false)
public void someDailyJob() {
// Do your job here which should run every start of day.
}
#Schedule(hour="*/1", minute="0", second="0", persistent=false)
public void someHourlyJob() {
// Do your job here which should run every hour of day.
}
#Schedule(hour="*", minute="*/15", second="0", persistent=false)
public void someQuarterlyJob() {
// Do your job here which should run every 15 minute of hour.
}
}
This is if necessary available in managed beans by #EJB:
#EJB
private BackgroundJobManager backgroundJobManager;
EJB unavailable? Use ScheduledExecutorService
Without EJB, you'd need to manually work with ScheduledExecutorService. The application scoped managed bean implementation would look something like this:
#ManagedBean(eager=true)
#ApplicationScoped
public class BackgroundJobManager {
private ScheduledExecutorService scheduler;
#PostConstruct
public void init() {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS);
}
#PreDestroy
public void destroy() {
scheduler.shutdownNow();
}
}
where the SomeDailyJob look like this:
public class SomeDailyJob implements Runnable {
#Override
public void run() {
// Do your job here.
}
}
If you don't need to reference it in the view or other managed beans at all, then better just use ServletContextListener to keep it decoupled from JSF.
#WebListener
public class BackgroundJobManager implements ServletContextListener {
private ScheduledExecutorService scheduler;
#Override
public void contextInitialized(ServletContextEvent event) {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS);
}
#Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}

Run Thread in JavafX Service

I'm confused about how to continue writing my program.
Basically, it connects to multiple serial devices, and then updates the javafX Application based on the responses from the devices (I first have to send the machine a message). So what I did was create a thread to run in the service thread, so that my program would not freeze and the Thread could pause until the message is read (there's a delay between sending and receiving a message over the serial device).
service = new Service() {
#Override
protected Task<String> createTask() {
return new Task<String>(){
#Override
protected String call() throws Exception {
new Thread(thread).start();
return null;
}
};
}
};
Where the thread does some loop, continuously sending and reading messages.
#Override
public synchronized void run() {
while(serialOn && isRunning){
sendMessages();
}
}
public synchronized void sendMessages(){
sendSerial1();
this.wait();
sendSerial2();
this.wait();
}
public synchronized void readMessage1(){ // same readMessage2 for the sendSerial2()
getMessage(); // updates variables that are bound to the Javafx App
this.notify();
}
But, I think the service finishes (i.e. succeeds or fails) before it event starts my serial thread. But I want the service to continue running while the program sends and receives messages.
Let me know if you need more code, it's a little long and requires the serial devices to run, but I can include it here if it makes the question easier to understand.
Don't create a new thread in the call() method of the service's Task.
A service automatically creates threads on which the call() will be invoked. If you want control over the thread creation and use, then you can (optionally) supply an executor to the service (though in your case you probably don't need to do that unless you don't want the service to be a daemon thread).
From the Service javadoc:
If an Executor is specified on the Service, then it will be used to actually execute the service. Otherwise, a daemon thread will be created and executed.
So shift the code inside the run() method of your Runnable and put it into the call() method of the Task for the Service (the Task itself is a Callable, which is a Runnable, so having an additional Runnable is both redundant and confusing).

Threading in JBoss

Okay so I have a java app being deployed to JBoss. The application needs to poll an external webservice for jobs. Each job can an should be run on its own thread. This will behave very similar to a jms queue with a pool of mdbs handling the messages. The only real difference is the queue of work is supplied by a restful webservice. So my question is what is the best way to start up my pool of threads or does jboss have a better way of doing this. JMS is not an option.
In theory you shouldn't manage your self thread in Java EE container (in practice it is a bit more relax, if you don't use EJB, JPA or any other container feature).
In Java EE 6 (JBoss 7) you can use Java EE features to do it; you need to leverage the timer feature with the new #Asynchronous EJB call. The only issue is that you don't have persistancy of the async call, if it fails (server crash during processing) the job is lost.
If you need to be sure the job is done, the only Java EE way is persistence JMS (even local one populated with the timer EJB)
Exemple:
#Singleton
#Startup
public class Pool{
#Inject
private AsyncBean aBean;
#Resource
private TimerService timerService;
#Timeout
public void pull(){
try{
// for performance you may get several job and launch several async job
job = getJob() // make your REST call to get the job
// make sure you realy get a job
aBean.async(job)
}finally{
//recreate the timer
timerService.createSingleActionTimer(100, new TimerConfig("timer name", false));
}
}
#PostConstruct
void init(){
timerService.createSingleActionTimer(100, new TimerConfig("timer name", false));
// as timer is created at each start up no need to persist it.
}
}
The async bean:
#Stateless
public class AsyncBean{
#Asynchronous
public void async(Job job){
// do your stuff
}
}

Hibernate Session Threading

I have a problem regarding Hibernate and lazy loading.
Background:
I have a Spring MVC web app, I use Hibernate for my persistence layer. I'm using OpenSessionInViewFilter to enable me to lazy load entities in my view layer. And I'm extending the HibernateDaoSupport classes and using HibernateTemplate to save/load objects. Everything has been working quite well. Up until now.
The Problem:
I have a task which can be started via a web request. When the request is routed to a controller, the controller will create a new Runnable for this task and start the thread to run the task. So the original thread will return and the Hibernate session which was put in ThreadLocal (by OpenSessionInViewFilter) is not available to the new thread for the Task. So when the task does some database stuff I get the infamous LazyInitializationException.
Can any one suggest the best way I can make a Hibernate session available to the Task?
Thanks for reading.
Make your Runnable a Spring bean and add #Transactional annotation over run. You must be warned thou that this asynchronous task won't run in the same transaction as your web request.
And please don't start new thread, use pooling/executor.
Here is a working example on how to use the Hibernate session inside a Runnable:
#Service
#Transactional
public class ScheduleService {
#Autowired
private SessionFactory sessionFactory;
#Autowired
private ThreadPoolTaskScheduler scheduler;
public void doSomething() {
ScheduledFuture sf = scheduler.schedule(new Runnable() {
#Override
public void run() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(scheduler);
final Session session = sessionFactory.openSession();
// Now you can use the session
}
}, new CronTrigger("25 8 * * * *"));
}
}
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext() takes a reference to any Spring managed bean, so the scheduler itself is fine. Any other Spring managed bean would work as well.
Do I understand correctly, you want to perform some action in a completely dedicated background thread, right? In that case, I recommend you not accessing the Hibernates OpenSessionInViewFilter and further session logic for that thread at all, because it will, is you correctly noted, run in a decoupled thread and therefore information loaded in the original thread (i.e, the one that dealt with the initial HttpRequest). I think it would be wise to open and close the session yourself within that thread.
Otherwise, you might question why you are running that operation in a separated thread. May be it is sufficient to run the operation normally and present the user with some 'loading' screen in the meantime?

Resources