I am using Quarkus 3.19 with JTA, and I am trying to catch PSQLException using a @ServerExceptionMapper.
Here’s my exception handler:
@ServerExceptionMapper
public RestResponse<ErrorMessage> handleRollbackException(QuarkusTransactionException exception) {
Throwable cause = exception;
while (cause.getCause() != null && cause.getCause() != cause) {
cause = cause.getCause();
}
log.info(cause.getClass()
.getName() + "\n" + cause.toString());
var message = ErrorMessage.builder()
.type("/service/transaction-exception")
.title("Could not persist data")
.status(Response.Status.CONFLICT)
.detail(cause.getMessage())
.instance(String.format("%s:%s", applicationName, cause.getMessage()))
.build();
return RestResponse.status(message.getStatus(), message);
}
However, the issue is that my application throws a QuarkusTransactionException, which wraps a RollbackException.
The log displayed by the mapper is
INFO requestId= processId= [co.nx.po.op.ws.er.QuarkusExceptionMappers] (vert.x-eventloop-thread-1) jakarta.transaction.RollbackException
jakarta.transaction.RollbackException: ARJUNA016053: Could not commit transaction.
Unfortunately, RollbackException does not provide any useful details about the original PSQLException. I get the following message in the log file
WARN requestId= processId= [co.ar.at.jta] (vert.x-eventloop-thread-1) ARJUNA016039: onePhaseCommit on < formatId=131077, gtrid_length=35, bqual_length=36, tx_uid=0:ffff7f000101:9b09:67e27ea9:32, node_name=quarkus, branch_uid=0:ffff7f000101:9b09:67e27ea9:35, subordinatenodename=null, eis_name=0 > (io.agroal.narayana.LocalXAResource@490a4005) failed with exception XAException.XA_RBROLLBACK: javax.transaction.xa.XAException: Error trying to transactionCommit local transaction: ERROR: update or delete on table "postmaster_fact_definition" violates foreign key constraint "postmaster_condition_fact_fk" on table "postmaster_condition"
Detail: Key (id)=(crm_main_contract_number) is still referenced from table "postmaster_condition".
at io.agroal.narayana.XAExceptionUtils.xaException(XAExceptionUtils.java:20)
at io.agroal.narayana.XAExceptionUtils.xaException(XAExceptionUtils.java:8)
at io.agroal.narayana.LocalXAResourcemit(LocalXAResource.java:73)
at com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord.topLevelOnePhaseCommit(XAResourceRecord.java:631)
at com.arjuna.ats.arjuna.coordinator.BasicAction.onePhaseCommit(BasicAction.java:2477)
at com.arjuna.ats.arjuna.coordinator.BasicAction.End(BasicAction.java:1542)
at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:71)
Caused by: .postgresql.util.PSQLException: ERROR: update or delete on table "postmaster_fact_definition" violates foreign key constraint "postmaster_condition_fact_fk" on table "postmaster_condition"
Detail: Key (id)=(crm_main_contract_number) is still referenced from table "postmaster_condition".
at .postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2733)
at .postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2420)
at .postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:372)
at .postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:330)
at .postgresql.jdbc.PgConnection.executeTransactionCommand(PgConnection.java:981)
at .postgresql.jdbc.PgConnectionmit(PgConnection.java:1003)
at io.agroal.pool.ConnectionHandler.transactionCommit(ConnectionHandler.java:348)
at io.agroal.narayana.LocalXAResourcemit(LocalXAResource.java:70)
... 49 more
How can I retrieve the original PSQLException that caused the rollback?
Any insights or best practices would be greatly appreciated!
I am using Quarkus 3.19 with JTA, and I am trying to catch PSQLException using a @ServerExceptionMapper.
Here’s my exception handler:
@ServerExceptionMapper
public RestResponse<ErrorMessage> handleRollbackException(QuarkusTransactionException exception) {
Throwable cause = exception;
while (cause.getCause() != null && cause.getCause() != cause) {
cause = cause.getCause();
}
log.info(cause.getClass()
.getName() + "\n" + cause.toString());
var message = ErrorMessage.builder()
.type("/service/transaction-exception")
.title("Could not persist data")
.status(Response.Status.CONFLICT)
.detail(cause.getMessage())
.instance(String.format("%s:%s", applicationName, cause.getMessage()))
.build();
return RestResponse.status(message.getStatus(), message);
}
However, the issue is that my application throws a QuarkusTransactionException, which wraps a RollbackException.
The log displayed by the mapper is
INFO requestId= processId= [co.nx.po.op.ws.er.QuarkusExceptionMappers] (vert.x-eventloop-thread-1) jakarta.transaction.RollbackException
jakarta.transaction.RollbackException: ARJUNA016053: Could not commit transaction.
Unfortunately, RollbackException does not provide any useful details about the original PSQLException. I get the following message in the log file
WARN requestId= processId= [co.ar.at.jta] (vert.x-eventloop-thread-1) ARJUNA016039: onePhaseCommit on < formatId=131077, gtrid_length=35, bqual_length=36, tx_uid=0:ffff7f000101:9b09:67e27ea9:32, node_name=quarkus, branch_uid=0:ffff7f000101:9b09:67e27ea9:35, subordinatenodename=null, eis_name=0 > (io.agroal.narayana.LocalXAResource@490a4005) failed with exception XAException.XA_RBROLLBACK: javax.transaction.xa.XAException: Error trying to transactionCommit local transaction: ERROR: update or delete on table "postmaster_fact_definition" violates foreign key constraint "postmaster_condition_fact_fk" on table "postmaster_condition"
Detail: Key (id)=(crm_main_contract_number) is still referenced from table "postmaster_condition".
at io.agroal.narayana.XAExceptionUtils.xaException(XAExceptionUtils.java:20)
at io.agroal.narayana.XAExceptionUtils.xaException(XAExceptionUtils.java:8)
at io.agroal.narayana.LocalXAResourcemit(LocalXAResource.java:73)
at com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord.topLevelOnePhaseCommit(XAResourceRecord.java:631)
at com.arjuna.ats.arjuna.coordinator.BasicAction.onePhaseCommit(BasicAction.java:2477)
at com.arjuna.ats.arjuna.coordinator.BasicAction.End(BasicAction.java:1542)
at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:71)
Caused by: .postgresql.util.PSQLException: ERROR: update or delete on table "postmaster_fact_definition" violates foreign key constraint "postmaster_condition_fact_fk" on table "postmaster_condition"
Detail: Key (id)=(crm_main_contract_number) is still referenced from table "postmaster_condition".
at .postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2733)
at .postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2420)
at .postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:372)
at .postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:330)
at .postgresql.jdbc.PgConnection.executeTransactionCommand(PgConnection.java:981)
at .postgresql.jdbc.PgConnectionmit(PgConnection.java:1003)
at io.agroal.pool.ConnectionHandler.transactionCommit(ConnectionHandler.java:348)
at io.agroal.narayana.LocalXAResourcemit(LocalXAResource.java:70)
... 49 more
How can I retrieve the original PSQLException that caused the rollback?
Any insights or best practices would be greatly appreciated!
Share Improve this question edited Mar 25 at 10:13 Joao Violante asked Mar 19 at 8:18 Joao ViolanteJoao Violante 112 bronze badges 4 |1 Answer
Reset to default 0You need to iterate over the causes of the exception and print that out.
Something like this:
private String getMessage(Exception e) {
var result = e.getMessage();
var cause = e.getCause();
var maxDepth = 3;
while (cause != null && maxDepth-- > 0) {
result = cause.getMessage();
cause = cause.getCause();
}
return result;
}
Replace the 3 with your own logic.
See my exceptionmapper here:
https://github/quarkiverse/quarkus-fluentjdbc/blob/main/examples/src/main/java/com/acme/fluentjdbc/config/ExceptionMapper.java
RollbackException
you're probably seeing in logs, and thePSQLExcetpion
(which you can probably send to the console using debug mode ande.printStackTrace()
). Also: do you use XA transactions? – yrodiere Commented Mar 19 at 12:39