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?
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.
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.
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 .
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With