membersound
membersound

Reputation: 86747

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?

Upvotes: 7

Views: 1667

Answers (1)

user140547
user140547

Reputation: 8200

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
    }
}

Upvotes: 2

Related Questions