In our Java EE application, we have a setup where Service A is an endpoint. In some valid business cases, this endpoint throws an exception and returns an error code to the client — this is expected behavior and cannot be changed.
However, Service A also calls Service B, which is part of another module (included as a Maven dependency). Service B performs an update (clearing activity data), which we want to persist, even when Service A throws the expected error.
The problem: this update is rolled back along with the outer transaction, so the update in Service B is lost.
Here’s a simplified version of the code:
// Service A (has maven dep on ServiceB)
@POST
@Path("/{id}/book")
public Response bookXXXX(..) {
try {
serviceB.doSmth(); // should persist even if error follows
...
} catch (SpecificServiceBException e) {
throw Response.error(Status.CONFLICT, someInfo); // expected and cannot be changed
}
}
// Service B
@ApplicationScoped
public class ServiceB {
@Inject
private IRepository repository;
public void deleteActivity(Long key) {
ActivityEntity activity = find...;
activity.updateLastDate(null);
repository.update(activity);
}
}
We tried using @Transactional(REQUIRES_NEW), but this leads to deadlocks in the database (Oracle). Because the database now has two concurrent transactions and waits for the first ("outer one") to commit and vice versa.
I also tried the recommended TransactionSynchronizationManager from this article to no success.
How can we make Service B’s update persist independently of Service A's transaction, even when Service A throws an exception (as part of normal flow)?
PS: We use Java EE but not Spring.