Do Not Mix Scheduler With Service

In my app I have lots of scheduled service classes implemented like this:


public FiddleService {
   private TaskScheduler scheduler;

  
  private void setupScheduler() {
    Runnable task = new Runnable() {
       public void run() {
        letsFiddle();
      }
    };
    scheduler.scheduleAtFixedRate(task, 10 * 1000);
  }

  
  public void letsFiddle() {
    ...
  }
}

At first the structure looked relatively simple, the scheduler will call letsFiddle() every 10 seconds. AOP-transaction wise I thought this should be okay since I used AspectJ mode (instead of JDK proxy).

But I just discovered this is wrong! The annotation was not effective if it’s invoked inside an inner-class.

Yep I only figured this out when strange transaction related behaviour started occuring in my app.

Few trials and errors, and I figured out the best way to implement this is to always separate the task in its own class:


public class FiddleService {
  
  public void letsFiddle() {
    ...
  }
}

public class FiddleServiceScheduler {
   private TaskScheduler scheduler;
   private FiddleService fiddleService;

  
  private void setupScheduler() {
    Runnable task = new Runnable() {
       public void run() {
        fiddleService.letsFiddle();
      }
    };
    scheduler.scheduleAtFixedRate(task, 10 * 1000);
  }  
}

This will ensure all construction-related work is done on FiddleService (possibly AOP-tx related stuff) before we invoke its transactional method

Leave a Reply