Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to catch transaction exceptions in @Async?

When writing transactional methods with @Async, it's not possible to catch the @Transactional exceptions. Like ObjectOptimisticLockingFailureException, because they are thrown outside of the method itself during eg transaction commit.

Example:

public class UpdateService {
    @Autowired
    private CrudRepository<MyEntity> dao;

    //throws eg ObjectOptimisticLockingFailureException.class, cannot be caught
    @Async
    @Transactional
    public void updateEntity {
        MyEntity entity = dao.findOne(..);
        entity.setField(..);
    }
}

I know I can catch @Async exceptions in general as follows:

@Component
public class MyHandler extends AsyncConfigurerSupport {
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> {
            //handle
        };
    }
}

But I'd prefer to handle the given exception in a different way ONLY if it occurs within the UpdateService.

Question: how can I catch it inside the UpdateService?

Is the only chance: creating an additional @Service that wraps the UpdateService and has a try-catch block? Or could I do better?

like image 441
membersound Avatar asked Sep 05 '16 09:09

membersound


People also ask

Does transactional work on async?

In order to make Spring manage the transaction of the @Async method either the @Component or the method itself should declare the @Transactional annotation, this way Spring will manage the transaction even if a method is being executed asynchronous.

How do you catch exceptions without trying?

throws: The throws keyword is used for exception handling without try & catch block. It specifies the exceptions that a method can throw to the caller and does not handle itself.

What is an Catch exception?

Each catch block is an exception handler that handles the type of exception indicated by its argument. The argument type, ExceptionType , declares the type of exception that the handler can handle and must be the name of a class that inherits from the Throwable class. The handler can refer to the exception with name .


1 Answers

You could try self-injecting your bean which should work with Spring 4.3. While self-injecting is generally not a good idea, this may be one of the use-cases which are legitimate.

@Autowired
private UpdateService self;

@Transactional
public void updateEntity() {
    MyEntity entity = dao.findOne(..);
    entity.setField(..);
}

@Async
public void updateEntityAsync(){
    try {
       self.updateEntity();
    } catch (Exception e) {
        // handle exception
    }
}
like image 182
user140547 Avatar answered Oct 06 '22 18:10

user140547