0

I'm using @Scheduled and @Async annotation of Spring.

My purpose

To schedule a sync method - which runs a for loop and this loop will run an async method, so the next value in the loop doesn't need to wait until the method is finished.

See my code below:

/**
 *  Explanation: Scheduling async task for getting new hired candidates from the Lumesse Queue and saving the received data.
 */
@LoggableDebug
@Scheduled(fixedRateString = "${scheduler.insertCandidateFromQueueInDB.fixedRate}")
public void insertNewHiredCandidateFromQueueInDbScheduler() {
    for(EnvironmentContext environmentContext: context) {
        if(environmentContext.isActive()) {
            environmentAsyncHandlerInsertNewHiredCandidateFromQueueInDb(environmentContext);
        }
    }
}

/**
 * @param environmentContext
 * Explanation: Async task for getting new hired candidates from the Lumesse Queue and saving the received data.
 */
@LoggableDebug
@Async
public void environmentAsyncHandlerInsertNewHiredCandidateFromQueueInDb(EnvironmentContext environmentContext) {
    CandidateLumesse candidateLumesse;
    candidateLumesse = lumesseConnectorService.getNewHiredCandidateDataFromQueue(environmentContext);   
}

Problem:

My async method does't run on different tasks. It only works when I put the @Async annotation also on my scheduled method. But then my scheduled method will runs asyncronuos to and that's not what I want. The scheduled method needs to run synchronous but the called method in the for loop needs to run asynchronous.

Tries

I tried a workaround like this one:

Spring @Async method call inside @Scheduled method

-> putting my async methods in another class. Like this:

@LoggableDebug
@Scheduled(fixedRateString = "${scheduler.insertCandidateFromQueueInDB.fixedRate}")
public void insertNewHiredCandidateFromQueueInDbScheduler() {
    for(EnvironmentContext environmentContext: context) {
        if(environmentContext.isActive()) {
            asyncServiceExecutor.environmentAsyncHandlerInsertNewHiredCandidateFromQueueInDb(environmentContext);
        }
    }
}

problem now is that my scheduled task get executed twice ...

Update

I did some more logging and my object only gets created once:

2018-02-06 13:17:19.053  WARN 13144 --- [           main] 
c.d.l.c.s.LumesseConnectorScheduler      : #### SCHEDULER CLASS CONSTRUCTOR

My fixedRate is 3000 -> 3 seconds Someone requested "increase it to 30 sec to see the flow", but still it is executing twice: So after 3 or 30 seconds or whatever the fixed rate has been set to, it will execute it twice instead of once..

2018-02-06 13:17:26.388  WARN 13144 --- [pool-7-thread-1] 
c.d.l.c.s.LumesseConnectorScheduler      : #### START SCHEDULING
2018-02-06 13:17:26.397  WARN 13144 --- [pool-7-thread-1] 
c.d.l.c.s.LumesseConnectorScheduler      : #### START SCHEDULING

-> Time between the two executions is just some very low miliseconds .. I just don't understand ..

Any thoughts ?

Tom
  • 85
  • 10
  • what is the frequency of scheduler.insertCandidateFromQueueInDB.fixedRate? – spandey Feb 06 '18 at 10:44
  • fixedRate: 3000 -> so 3 seconds – Tom Feb 06 '18 at 10:49
  • increase it to 30 sec to see the flow – spandey Feb 06 '18 at 10:51
  • My post is updated with results - it didn't resolve anything – Tom Feb 06 '18 at 10:56
  • @Tom Is has been executed twice, but why the period is not 3 or 30 seconds? From the log time stamp, the interval is very small. – xingbin Feb 06 '18 at 11:20
  • That is what I mean with executed twice. Every 3 or 30 seconds it will executed it twice instead of once – Tom Feb 06 '18 at 11:23
  • @Tom I think I find the reason. Post the annotation you put on the scheduler class.. Let me check it.. – xingbin Feb 06 '18 at 11:30
  • If it is executing twice you are running it twice. You probably have a component scan in your context for both the `ContextLoaderListener` and `DispatcherServlet`. Scanning and setting up the same components and thus loading your application twice, leading to the scheduling twice. – M. Deinum Feb 06 '18 at 11:33
  • @ConfigurationProperties(prefix="environment") @Component public class LumesseConnectorScheduler .. I tried Component, Service, Controller, .. – Tom Feb 06 '18 at 11:34
  • @M.Deinum I don't use a DispatcherServlet – Tom Feb 06 '18 at 11:35
  • Regardless, this is a symptom of things being loaded twice and thus executed twice. Which is actually a new question (your original question has been answered). – M. Deinum Feb 06 '18 at 11:36
  • But when I remove the async annotation - the scheduling task is correctly running once .. – Tom Feb 06 '18 at 11:37
  • @Tom Try remove `@ConfigurationProperties(prefix="environment")` or `@Component` – xingbin Feb 06 '18 at 11:38
  • If I remove @Component it run nothing .. I will try to remove the configurationProperties if it is possible – Tom Feb 06 '18 at 11:53
  • Ok I have done some more logging: My object only gets created once - so @M.Deinum it is not the way you where thinking .. but it is coming into my scheduler method twice ... :( – Tom Feb 06 '18 at 12:18
  • Trust me it is. If it is scheduled twice, things are being processed twice. This can be that you have multiple schedulers that are processing things or your bean has multiple instances. – M. Deinum Feb 06 '18 at 12:20
  • This is the only scheduler in my application and this the only running task when my application starts. I edited my post with the log result and it seems that the object only is created once.. hmm – Tom Feb 06 '18 at 12:23
  • @M.Deinum I believe you are wright but I don't see it where this happens – Tom Feb 06 '18 at 12:27
  • @Tom what's your spring version? – xingbin Feb 06 '18 at 12:55
  • springBootVersion = '1.5.3.RELEASE' – Tom Feb 06 '18 at 13:02
  • @user27149 I have removed ConfigurationProperties and replaced this with a new Autowired object. It is working now ! I will post my solution below .. Good job ! – Tom Feb 07 '18 at 09:37

1 Answers1

0

-> Async is working with my "Tries":

Tries

I tried a workaround like this one:

Spring @Async method call inside @Scheduled method

, but I had a new issue with scheduler executing twice :

Solution

@user27149 Try remove @ConfigurationProperties(prefix="environment") or @Component

So I changed

@Component
@ConfigurationProperties(prefix="environment")
public class LumesseConnectorScheduler {

    private List<EnvironmentContextImpl> context;

To:

@Component
public class LumesseConnectorScheduler {

    @Autowired
    EnvironmentContextList environmentContextList;

Thanks for the answers !

Tom
  • 85
  • 10