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