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