0

In my application I have 2 @Async methods: one for auditing purposes and another for updation of some maps in 2 entirely different beans, called from different beans but at same time. One from Audit listener and other from a controller.

My problem is that both of them run in a single thread, i.e first audit runs and then in the same thread those maps are created. So, if audit throws some exception, maps wont be created, or maps throw an error, audit wont get recorded.

Is there any way, I can have these 2 methods run in different Async threads.

Method1:

@Async(value="myExecutor")
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void regenerateZoneMapAsync(DemandSource ds) {
    System.out.println("\n\n********************Current Thread in Async Class*****************" + Thread
            .currentThread());
    regenerateZmFilesByDs(ds);
    System.out.println("\n\n*********Current Thread********" + Thread.currentThread());
}

Method2:

@Async(value="myExecutor")
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void callAudit(DemandSource ds) {
    System.out.println("\n\n************Current Thread in Audit Class*********" + Thread
            .currentThread());
    callAudit(ds);
    System.out.println("\n\n***********Current Thread********" + Thread.currentThread());
}

println has been added for my own clarity, to know which thread is been executed. I am new to both, multithreading and Spring.

My config class has

<task:annotation-driven executor="myExecutor"/> 
<task:executor id="myExecutor" pool-size="5"/> 

After adding above configuration with @Async(value="myExecutor") my code has stopped working altogether, By this I mean,bean in which regenerateZoneMapAsync() has been defined, is not called from my calling bean, some proxy issue arises.

Edit:

One thing that comes in my mind is can it be possible that Audit thread completes its processing and send the thread back to pool, and then map picks the same thread and starts its processing.

Basically I want that if audit throws any error, and roll backs map updation should still happen.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
dgupta3091
  • 1,067
  • 1
  • 7
  • 18
  • Add your configuration to your question. – M. Deinum Jun 09 '16 at 07:19
  • what part of configuration do you want exactly? – dgupta3091 Jun 09 '16 at 07:20
  • The configuration of the async and the thread pool configuration. – M. Deinum Jun 09 '16 at 07:21
  • After adding above configuration with @Async(value="myExecutor") my code has stopped working altogether – dgupta3091 Jun 09 '16 at 09:00
  • Please add the code as improvement to your question not as comments as that makes it completely unreadable not to mention the fact that people have to read everything to have a complete overview of the information. – M. Deinum Jun 09 '16 at 09:07
  • Also add the code that is calling the 2 async methods. I also wonder how did it stop working when adding `@Async(value="myExecutor")`. – M. Deinum Jun 09 '16 at 09:07
  • 1
    Not really `callAudit` is calling itself... Next to that you haven't explained what stopped working and how that manifests (you only say it stopped working). How is this code being called? – M. Deinum Jun 09 '16 at 10:35
  • Also for your usecase you don't really need multiple threads or async imho, just proper exception handling. – M. Deinum Jun 09 '16 at 10:37
  • I already told that both my methods are called from entirely different beans. Plus I have added what have stopped working. Is there any way to start two different threads for 2 different Async ?? – dgupta3091 Jun 09 '16 at 10:37
  • Still add that code and it is still unclear what isn't working. You are only telling/showing snippets without completing the full picture. So quite hard to help you then. I expect that you have multiple instances of your beans making the `@Async` useless as you will have a proxied and unproved one. Also `@Async(value="myExecutor")` doesn't add anything as `myExecutor` is already the default executor. – M. Deinum Jun 09 '16 at 10:41
  • Well my issue worked. The implicit thread executor creates 2 threads itself. It might be possible that I have earlier read wrong thread names, or my war wasn't updated. Any ways thanks. And I am closing the question. – dgupta3091 Jun 10 '16 at 06:28

1 Answers1

0

Well I got my answer.

@Transactional(propagation = Propagation.REQUIRES_NEW) always creates a new transaction if called from another bean.

If called from same bean, a new transaction is never made, and since it is @Async , it starts in the already running Async thread.

So, I had to make another bean for my method, and and the two methods started running in 2 different threads concurrently.

Got my reference from:

@Async has two limitations:

it must be applied to public methods only; self invocation – calling the async method from within the same class – won’t work;

The reasons are simple – the method needs to be public so that it can be proxied. And self-invocation doesn’t work because it bypasses the proxy and calls the underlying method directly.

http://www.baeldung.com/spring-async

dgupta3091
  • 1,067
  • 1
  • 7
  • 18