Spring Task Async and Delayed

11,540

Solution 1

You could use the ScheduledExecutorService to schedule the Task

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
...
scheduler.schedule(() -> {yourtaskhere}, 15, TimeUnit.MINUTES);

But this is not what you want. What if the server dies between the scheduling of the task and its execution? you will lose your task. It would be better if you persist the message in a queue, and retrieve it later, or use any scheduler that uses persistence (a la Quartz)

Solution 2

you can add @EnableScheduling annotation to your configuration:

@Configuration
@EnableAsync
@EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("TIMCLL-");
        executor.initialize();
        return executor;

    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        // TODO Auto-generated method stub
        return null;
    }

}

if you want to do schedule once and delayed you can call the taskScheduler :

@Autowired 
private TaskScheduler taskScheduler;

and execute the task:

taskScheduler.schedule(
    () -> {//your task}, 
    //Your Delay task
);

Solution 3

i think we can use @Scheduled in latest spring. it will run every 15 minutes like method is annotated as below

@Scheduled(cron = "0 0/15 * * * *")
public void verifyStatusTimPayment() throws InterruptedException {
    logger.info( "Executed after 5s " +  new SimpleDateFormat("dd/MM/yyyy hh:mm:ss").format(new Date())); 

}

i know i am late but might help someone who is going through thread

Solution 4

You can use Redis backed delayed scheduler, which would guarantee you wouldn't lose your tasks. This can be done using Rqueue very easily.

In Rqueue you can enqueue a task which would run after 15 minutes as

public class Verification {
    private String id;
}

@Component
class VerificationListener {
  @RqueueListener(
  value = "verification-queue")
  public void onMessage(Verification verification) {
    // do verification 
  }
}


@Service
class DelayedTaskService {
    @Autowired private RqueueMessageSender rqueueMessageSender
    public void enqeueVerification(Verification verification) {
         rqueueMessageSender.enqueuIn("verification-queue", verification, Duration.ofMinutes(15);
    }
}

P.S. I'm a developer of the Rqueue library.

Share:
11,540
danilongc
Author by

danilongc

Updated on June 04, 2022

Comments

  • danilongc
    danilongc almost 2 years

    I need to do onething that I don't know wich is the best practice to this.

    After I send one request to an especific service, this one returns OK and queue my request. I have a callback service that is used to notify when it ends.

    The problem is that the whole process can take a long time and over without notify anything and after that I need to consider a timeout.

    The application is SpringBoot APP and I was considering to use the annotations @EnableAsync and @Async on a service method with a Sleep time.

    @Configuration
    @EnableAsync
    public class AsyncConfiguration implements AsyncConfigurer {
    
        @Override
        public Executor getAsyncExecutor() {
    
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(2);
            executor.setMaxPoolSize(10);
            executor.setQueueCapacity(500);
            executor.setThreadNamePrefix("TIMCLL-");
            executor.initialize();
            return executor;
    
        }
    
        @Override
        public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
            // TODO Auto-generated method stub
            return null;
        }
    
    }
    

    . . .

    @Async
    public void verifyStatusTimPayment() throws InterruptedException {
    
        Thread.sleep(5000);
        logger.info( "Executed after 5s " +  new SimpleDateFormat("dd/MM/yyyy hh:mm:ss").format(new Date())); 
    
    }
    

    The verification needs to be done 15 minutes after the request and have to occur just one time per request.

    How can I do this without make a Thread.sleep ?????

  • Kamil Nękanowicz
    Kamil Nękanowicz over 5 years
    but i want execute it only once, your example run every 15 minutes
  • Musab Qamri
    Musab Qamri over 5 years
    Then you can use java timer