Set Thread Priority - spring

I need to kick off a thread to clean up data in the background after a user signs in our application. The data clean-up method is with #Async annotation in Spring. Due to the nature of the thread, I would like to set the thread to a low priority so that it would not complete the resource with the main functionality of the application. I can do so in the getAsyncExecutor method of the AsyncConfiguration class. Is the priority for the particular thread?
BTW, I don't find any methods with #Async annotation.

#Async allows you to configure a qualifier. It will then use the AsyncTaskExecutor bean configured with the same qualifier to start the thread to execute this async method. Most of the AsyncTaskExecutor implementation allows to configure the thread priority.
For example, if the method is defined as :
#Async("backgroundJobTaskExecutor")
public void doJob(){
}
You can then define a AsyncTaskExecutor bean as :
#Bean
#Qualifier("backgroundJobTaskExecutor")
public AsyncTaskExecutor backgroundJobTaskExecutor(){
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setThreadPriority(Thread.MIN_PRIORITY);
return taskExecutor;
}

Threads managed by a ThreadPoolTaskExecutor are released and reused later on demand. So changing their priorities can have unintended consequences. I think it would be better to spawn a dedicated thread in your method once executed and then proceed to fine tune its priority. As in the following example:
public void launchMaintenanceTask(){
Thread thread = new Thread(() -> {
doYourMaintenanceStuffHere();
});
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}

Related

Mutil Consumer means my server using multi thread?

I am working on a simple project in Java.
I want to know that if I write this code, SimpleRabbitListenerContainerFactory.setConcurrentConsumers(2) then my program use multi thread?
Simple answer is yes.
Assuming that you are configuring it inside #Bean annotated method that configures your listener.
According to Spring AMPQ docs it should look somehow similar to that:
#Configuration
#EnableRabbit
public class AppConfig {
#Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setConcurrentConsumers(3);
factory.setMaxConcurrentConsumers(10);
return factory;
}
}
As you can see, there is also max number of concurrent consumers set up which means that you will be using something between min=3 and max=10 consumers.
If you set only .setConcurrentConsumers(3) it will mean that you are using fixed number. No more, no less.
Recommended reads are:
Listener Concurrency
Annotation driven async config

SimpleAsyncTaskExecutor Interceptor - Enable Request Scope in SimpleAsyncTaskExecutor

Is there a way to intercept SimpleAsyncTaskExecutor? Basically I am trying to intercept every time SimpleAsyncTaskExecutor is invoked.
On top of that what I am really trying to do is pass on a RequestScope bean. I found How to enable request scope in async task executor, but the problem is that I cannot reuse threads. I need a new thread created every time.
Any idea how I could forward Request Scoped beans to an async thread or how I could intercept #Async for a SimpleAsyncTaskExecutor?
Thanks,
Brian
I'm not sure this is the best way to accomplish what I am trying to accomplish but it seems to work.
Config:
#Configuration
#EnableAsync
public class Config extends AsyncConfigurerSupport implements WebMvcConfigurer {
#Override
#Bean
public Executor getAsyncExecutor() {
return new SimpleAsyncTaskExecutor(new MyThreadFactory());
}
}
MyThreadFactory:
public class MyThreadFactory implements ThreadFactory {
#Override
public Thread newThread(Runnable r) {
RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(), true);
return new Thread(r);
}
}
So I also tried another solution using ThreadPoolTaskExecutor.
Basically I used this solution: http://www.chrisport.ch/java/2016/10/12/java-spring-context-aware.html and switched MDC context stuff to final RequestAttributes originalContextCopy = RequestContextHolder.getRequestAttributes(); and RequestContextHolder.resetRequestAttributes();

How to fix - Executor is required to handle java.util.concurrent.Callable return values

I have a controller in Spring Boot/Spring Data Rest where my handler downloads a file like this
#RequestMapping(method = GET, value = "/orderAttachments/{id}/download")
#ResponseStatus(HttpStatus.OK)
public ResponseEntity<StreamingResponseBody> downloadAttachment(#PathVariable("id") Long attachmentID, HttpServletRequest request)
throws IOException {
InputStream inputStream = fileManager.getInputStream(orderAttachment);
StreamingResponseBody responseBody = outputStream -> {
int numberOfBytesToWrite;
byte[] data = new byte[1024];
while ((numberOfBytesToWrite = inputStream.read(data, 0, data.length)) != -1) {
outputStream.write(data, 0, numberOfBytesToWrite);
}
inputStream.close();
};
return ResponseEntity
.ok()
.contentLength(orderAttachment.getFileSize())
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + orderAttachment.getFileName()+ "\"")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(responseBody);
}
I got this error in the console
!!!
An Executor is required to handle java.util.concurrent.Callable return values.
Please, configure a TaskExecutor in the MVC config under "async support".
The SimpleAsyncTaskExecutor currently in use is not suitable under load.
-------------------------------
Request URI: '/api/v1/orderAttachments/163/download'
!!!
But everything works, I can download the file from calling the API
For starters it is a warning and not an error. If it was an error your application wouldn't start or work. It is a warning telling you that the default used SimpleAsyncTaskExecutor shouldn't be used in production.
The SimpleAsyncTaskExecutor creates a new Thread when something needs to be processed asynchronously. Each thread takes up 1MB of memory by default (and some processing power). Now imagine someone issuing 100000 calls to this API. This would also mean 100000 threads (times the memory and each a little cpu power). It would cripple your application and maybe even kill it.
NOTE: If you are on Spring Boot 2.1.x or higher a default TaskExecutor will be configured and used for you. However if you have something in your configuration that disables the auto-configuration (like an #EnableWebMvc on an #Configuration class for instance). To configure that executor (with threads etc) check the Spring Boot Reference Guide.
You can also manually create a TaskExecutor and associate that with Spring MVC.
#Configuration
public class WebMvcConfig implements WebMvcConfigurer {
#Bean
public ThreadPoolTaskExecutor mvcTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(10);
taskExecutor.setMaxPoolSize(10);
return taskExecutor;
}
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor(mvcTaskExecutor());
}
}
Now this dedicated TaskExecutor will be used for the async handling in Spring MVC. However as mentioned this should already be pre-configured by Spring Boot if you haven't disabled auto-configuration (maybe even by accident!).
It is just a warning (that is why you still are able to download requested file) and Spring's suggestion to define your own TaskExecutor rather than using the SimpleAsyncTaskExecutor which, as the message states, is not suitable under load.
SimpleAsyncTaskExecutor fires up a new Thread for each task and does not reuse them. If you haven't configured limit on concurrent threads, it is by default unlimited.
#Configuration
class AsyncConfiguration implements AsyncConfigurer {
#Bean
protected WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor([your task executor]);
}
};
}
}
Use the above configuration to define your own TaskExecutor that suits your needs and get rid of the warning.
Spring boot in 2.1.0 provides auto configuration for task executors and uses for #EnableAsync and Spring MVC Async support.
There is no task executor bean / webMvcConfigurer configuration is needed from application. If you have one please remove it and you should be good.
If you like to control the values you can adjust using applicaion properties/yml file with spring.task.execution.*. Full listing can be found here
More details here and here
For me, the following did the trick:
#Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
#Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(1);
executor.setMaxPoolSize(10);
executor.setThreadNamePrefix("mvc-task-executor-");
executor.initialize();
configurer.setTaskExecutor(executor);
}
}
By this means a ThreadPoolTaskExecutor is specified for the MVC context.
Make sure your application picks up the #Configuration class! If your main class is annotated with #SpringBootApplication, this should happen automatically.
Also, make sure to configure your ThreadPoolTaskExecutor appropriately to your needs.

Server Sent Event with SQL Database connection using Spring Boot

I want to implement Server Sent Events in Spring Boot. The data is there in SQL database, It is resulting in blocking connection. Web Flux is an option but it is supported only for some NoSQL database.
Yes, you right WebFlux framework doesn't SQL databases in the non blocking mode because reactive drivers does not exist.
But WebFlux provides some instruments to avoid blocking our main threads while we are making blocking long queries to a database.
1) Create configuration with Scheduler where count of threads equals to pool size:
#Configuration
public class SchedulerConfiguration {
#Value("${spring.datasource.maximum-pool-size}
private final Integer connectionPoolSize;
#Bean
#Qualifier("jdbcScheduler")
public Scheduler jdbcScheduler() {
return Schedulers.fromExecutor(Executors.newFixedThreadPool(connectionPoolSize));
}
}
2) Inject your "jdbcScheduler" to the service class:
#Service
public class DataService {
#Autowired
private final DataRepository jdbcRepository;
#Autowired #Qualifier("jdbcScheduler")
private final Scheduler scheduler;
public Mono<String> findById(long id) {
return async(() -> repository.findById(id));
}
private <T> Mono<T> async(Callable<T> callable) {
return Mono.fromCallable(callable).publishOn(scheduler);
}
}
Wrap your blocking method by Mono.fromCallable and delegate from main thread to your "scheduler" via Mono.publishOn
More about schedulers you can read here: Threading and Schedulers
Yes you can achieve asynchronous processing in spring without flux by using their inbuilt #Async processing, here how you can achieve it.
Step1: Enable Aysnc and define a bean for Executor. You can define separate configuration or directly under Main application class.
#SpringBootApplication
#EnableAsync
public class Application {
public static void main(String[] args) {
// close the application context to shut down the custom ExecutorService
SpringApplication.run(Application.class, args).close();
}
#Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("GithubLookup-");
executor.initialize();
return executor;
}
STEP2:
Following is the simple way to configure a method with void return type to run asynchronously, You can also invoke method by retrieve the result of the asynchronous process using the Future object.
#Async
public void asyncMethodWithVoidReturnType() {
System.out.println("Execute method asynchronously. "
+ Thread.currentThread().getName());
}
For more information, You can visit Spring official guide Spring Async

Spring Cloud sleuth breaking DelegatingSecurityContextExecutor

I've a spring boot app version 1.3.3.RELEASE and I've added Spring Cloud Sleuth get those tracing goodies. After adding spring-cloud-sleuth I see some of my async API's are breaking as passed in org.springframework.security.concurrent.DelegatingSecurityContextExecutor. is null. Short story, I'm using org.springframework.security.concurrent.DelegatingSecurityContextExecutor from spring security to pass security context around different executors. For that I'm just wrapping those executors into org.springframework.security.concurrent.DelegatingSecurityContextExecutor instances during application start up. What I'm not sure is why Spring Sleuth is becoming a problem here. The way we're using async processing is, we have created a custom annotation and then created a point cut's around that to inject async behavior.
Example:
public class Async implements AsyncConfigurer {
public Executor getCustomAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//all configuration for thread pool
return new DelegatingSecurityContextAsyncTaskExecutor(executor);
}
public Executor getProcessingExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//all configuration for thread pool
return new DelegatingSecurityContextAsyncTaskExecutor(executor);
}
}
public class MyControllerClass {
#Autowired
private Executor myProcessingExecutor;
#MyCustomAsyncAnnotation
public ResponseObject getResponse() {
//As soon as below code get's executed I get NPE as
//`org.springframework.security.concurrent.DelegatingSecurityContextExecutor.executor` is null. What I'm not sure is why it's null??
// As you see above in my Async class I've registered executor in DelegatingSecurityContextAsyncTaskExecutor, then why it's null here?
//If I remove spring-cloud-sleuth code works fine once again.
CompletableFuture.supplyAsync(() -> ..., myProcessingExecutor);
}
}
class MyCustomAspect {
private Executor myCustomAsyncExecutor;
//create point cut here for those method which have
// #MyCustomAsyncAnnotionation and process it async via above executor.
}
I'm using spring boot 1.3.3.RELEASE, rest easy, spring-security 4.0.3.RELEASE, spring-cloud-sleuth 1.0.12.RELEASE

Resources