I'm trying to convert XML configuration for using Spring's tasks framework into purely code configuration. I'm able to reproduce the functionality but whenever I shut down the war on the Tomcat server the task scheduler lives on, it hangs (it doesn't hang with XML configuration). I've debugged to inspect the instances of scheduler and executor but I'm not seeing a difference so I'm not sure what could be causing it to hang.
Here is the XML configuration that works:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd">
<task:executor id="com.work.gwx.pix.executor"
pool-size="${pix.job.executor.pool.size:1-40}"
queue-capacity="${pix.job.executor.queue.capacity:0}"
rejection-policy="CALLER_RUNS"/>
<task:scheduler id="com.work.gwx.pix.scheduler" pool-size="${pix.job.scheduler.pool.size:4}" />
<task:annotation-driven executor="com.work.gwx.pix.executor" scheduler="com.work.gwx.pix.scheduler" />
<bean id='queueProcessor' class="com.work.gwx.queueing.QueueProcessor" />
</beans>
Here is the code configuration:
@EnableAsync
@EnableScheduling
@Configuration
public class TaskConfiguration implements AsyncConfigurer, SchedulingConfigurer {
@Value("${pix.job.executor.max.pool.size:1}")
private int executorMaxPoolSize;
@Value("${pix.job.executor.queue.capacity:0}")
private int executorQueueCapacity;
@Value("${pix.job.scheduler.pool.size:4}")
private int schedulerPoolSize;
@Bean(destroyMethod = "shutdown")
public Executor pixTaskScheduler() {
final ScheduledThreadPoolExecutor ex = new ScheduledThreadPoolExecutor(schedulerPoolSize, new ThreadPoolTaskExecutor());
// ex.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
return ex;
}
@Bean
public Executor pixExecutor() {
final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(executorMaxPoolSize);
executor.setQueueCapacity(executorQueueCapacity);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setThreadFactory(new ThreadPoolTaskExecutor());
executor.initialize();
return executor;
}
@Override
public void configureTasks(final ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(pixTaskScheduler());
}
@Override
public Executor getAsyncExecutor() {
return pixExecutor();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
}
When I use setExecuteExistingDelayedTasksAfterShutdownPolicy(false)
in code configuration it does shut down but I'm worried that might have adverse effects as that is set to true when done via XML configuration. Also, I should note, the QueueProcessor class is doing the work I want and I don't mind if delayed executions get cancelled -- I just don't want currently executing threads to be abruptly cancelled.
This is the message I get when it hangs:
SEVERE: The web application [/pix-queue-processor] appears to have started a thread named [ThreadPoolTaskExecutor-1] but has failed to stop it. This is very likely to create a memory leak.
Any ideas on what might be causing the hanging? Or, would using that commented out method let me do what I want (won't kill a running task but will cancel delayed tasks)?
Annotations have their use, but they are not the one silver bullet to kill XML configuration. I recommend mixing the two! For instance, if using Spring, it is entirely intuitive to use XML for the dependency injection portion of your application.
java - The Spring Boot Application class generated with Spring Initializer. This class acts as the launching point for application. pom. xml - Contains all the dependencies needed to build this project.
Is it possible to avoid using xml in Spring or better to mix xml files and annotations? Yes, it is. Spring now promotes Java configuration, and it's perfectly doable (I'm doing it) and even easy to only use Java to configure your Spring app. Even without using Boot.
In this spring bean XML configuration example, learn to create define and create spring beans and populate application context in any spring application. This example uses xml config to define beans. We will use maven to manage the spring dependencies and eclipse to build and run the code.
Here are simple steps to create Spring XML configuration example. 1. Create a simple java maven project. 2. Maven dependency 3. Create Bean class Create a bean class called Country.java in package org.arpit.java2blog.model .
In this post, we will see how to create Spring hello world XML based configuration example. Here are simple steps to create Spring XML configuration example. 1. Create a simple java maven project. 2. Maven dependency 3. Create Bean class Create a bean class called Country.java in package org.arpit.java2blog.model .
This still provides you a decoupling of configuration from code(like XML), but also provides other benefits like compile time checking of typos... @Configuration is your friend. Spring almost came back a full circle and moved(or intends to move) configuration from XML back to code.
Getting error in spring config file error : The value of attribute "xmlns" associated with an element type "beans" must not contain the '<' character 3 Solace Connectivity issue using Spring 4.x
Your Java based configuration isn't really a representation of the the XML configuration. There are at least 2 things that are different.
TaskExecutor
has another TaskExecutor
wired as a ThreadFactory
this isn't the case in XML and also starts another TaskExecutor
.TaskScheduler
uses a new TaskExecutor
whereas the xml configuration use the one configured.The have your task finished on shutdown you can set the waitForTasksToCompleteOnShutdown
property on the TaskExecutor
to true
then any pending tasks will be completed and no new tasks will be accepted.
Also the call to initialize
shouldn't be needed as the afterPropertiesSet
method will be called by Spring which in turn calls initialize
.
The following 2 bean definitions are more in line with the XML configuration (and you now have a single TaskExecutor
instead of 3 and it will first finish tasks before shutdown.
@Bean(destroyMethod = "shutdown")
public Executor pixTaskScheduler() {
final ScheduledThreadPoolExecutor ex = new ScheduledThreadPoolExecutor(schedulerPoolSize, pixExecutor());
// ex.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
return ex;
}
@Bean
public Executor pixExecutor() {
final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(executorMaxPoolSize);
executor.setQueueCapacity(executorQueueCapacity);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With