0

I have two Spring based async thread pools and methods in the same Spring bean. The doWork() uses the default Spring thread pool and holdAndReprocess() uses its own Spring thread pool.

I currently have my class setup like below where doWork processes some work and then if a failure occurs it parks the thread in the holdAndReprocess() "queue" thread pool and then waits and reprocesses the thread by calling the doWork(). With my current setup, the call to holdAndReprocess() and then the call back to doWork() is synchronous. Any ideas on how to wire this such that all communication between the doWork() and holdAndReprocess is asynchronous?

I'm using xml backed configuration and not pure annotation driven Spring beans.

public class AsyncSampleImpl implements AsyncSample {

  @Async
  public void doWork(){
      holdAndReprocess();
  }

  @Async("queue")
  @Transactional(propagation = Propagation.REQUIRED)
  public void holdAndReprocess(){
     //sleeps thread for static amount of time and then reprocesses
     doWork();
  }
}
Nolen Royalty
  • 18,415
  • 4
  • 40
  • 50
c12
  • 9,557
  • 48
  • 157
  • 253

1 Answers1

0

Read https://stackoverflow.com/a/4500353/516167

As you're calling your @Async method from another method in the same object, you're probably bypassing the async proxy code and just calling your plain method, ie within the same thread.

Split this bean into two beans and invoke holdAndReprocess() from separate bean.


This rules apply also to @Transactional annotations.

Read about this: https://stackoverflow.com/a/5109419/516167

From Spring Reference Documentation Section 11.5.6, “Using @Transactional”

In proxy mode (which is the default), only 'external' method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with @Transactional!


Draft

public class AsyncSampleImpl implements AsyncSample {

  public void doWork(){
      reprocessor.holdAndReprocess();
  }

  public void holdAndReprocess(){
     //sleeps thread for static amount of time and then reprocesses
     worker.doWork();
  }
}
Community
  • 1
  • 1
MariuszS
  • 30,646
  • 12
  • 114
  • 155
  • wouldn't that create a circular reference as the two beans would be dependent on each other... – c12 Jan 24 '14 at 22:08
  • Yes, but this circular dependency is already in your code, you need to fix this – MariuszS Jan 24 '14 at 22:12
  • If you are sure about this logic, then create bean for `holdAndReprocess` and for `doWork` with @Async and execute it from existing bean. Draft code added. – MariuszS Jan 24 '14 at 22:14