How to get details of Spring Boot @Async method's rejected task?

Viewed 1146

In my application I'm using an @Async method which is calling a rest service and based on the rest service result I'm updating the MyJob status in DB.

@Async("thatOneTaskExecutor")
public void myAsyncTask(MyJob job) {
    // get job details from the job and call rest service
    // update the job with the result from rest service and save updated MyJob to DB
}

I'm using Spring's ThreadPoolTaskExucutor, Below is a snap from my AsyncConfiguration class where I declared this task executor.

private ThreadPoolTaskExecutor createExecutor(String name, int core, int max, int queue) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(core);
        executor.setMaxPoolSize(max);
        executor.setQueueCapacity(queue);
        executor.setThreadNamePrefix(name);
        executor.setTaskDecorator(new MdcAwareTaskDecorator());
        executor.initialize();
        return executor;
    }

@Bean(name = "thatOneTaskExecutor")
public Executor taskExecutor() {

    String prefix = "thatOneTask-";
    String corePoolSize = 12;
    String maxPoolSize = 20;
    String queueSize = 1000;

    ThreadPoolTaskExecutor executor = createExecutor(prefix, corePoolSize, maxPoolSize, queueSize);
    executor.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
    return executor;
}

As you can see I had configured a RejectedExecutionHandler for my Executor. According to Spring documentation when queue is full this method will be called.

 * Method that may be invoked by a {@link ThreadPoolExecutor} when
 * {@link ThreadPoolExecutor#execute execute} cannot accept a
 * task.  This may occur when no more threads or queue slots are
 * available because their bounds would be exceeded, or upon
 * shutdown of the Executor.
public class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        log.error("Task Rejected because of max queue size");
        // How to get info about that particular job, for which Task executor rejected this task??
    } 
}

Rejected execution handler is working fine for me, now inside this rejectedExecutorion method, I want to access the MyJob(parameter of my async method) for which the async task is rejected. I want to update that particular rejected job with a status so that I can later run a corn and process those rejected jobs. Inside this rejectedExecution method I only have Runnable and ThreadPoolExucutor, how can I extract/get info about MyJob here?

My application's Spring boot version is 2.2.2.RELEASE

1 Answers

You could consider using the TaskExecutor directly instead of the @Async annotation by implementing the Runnable interface for MyJob Class and perform the required async operation inside the run() method.

The Runnable r could be cast back to MyJob Object in the rejectedExecution method of the handler and hence you could retrieve information of your job from there.

 public class Myjob implements Runnable{
   .......
   @Override
   public void run(){
         //get job details from the job and call rest service
         //update the job with the result from rest service and save updated MyJob to DB
      }
 }

@Autowired
TaskExecutor taskExecutor;
 
public void myAsyncTask(MyJob job) {
   taskExecutor.execute(job)
}

public class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        log.error("Task Rejected because of max queue size");
        if(r.getClass()==MyJob.class)
         {
            MyJob failedJob=(MyJob)r; //Job info
         }

    } 
 }

Related