Unique Constraint violation in Rest API Response

Hi,
I am doing simple curl request to create an Entity. But, I am unable to get the Unique Constraint Violation for creating an entity as mentioned in the documentation (Create Entities :: Jmix Documentation) in my REST API response.

Actually i am getting the following REST API response:

{"error":"Server error","details":""}

Please guide me how to get the Unique Constraint Violation in REST API Response.

This is my curl request:

curl http://localhost:8080/rest/entities/cdp_Hierarchy --header "Content-Type: application/json" --header "Authorization: Bearer <access-token>" --data '{"hierarchyId": "EC00515", "description": "EC00515 Desc", "type": "FOLDER", "status": "READY"}' --request POST

This is my server log:

rror Code: -104
Call: INSERT INTO CDP_P6_HIERARCHY (ID, CREATED_BY, CREATED_DATE, DESCRIPTION, HIERARCHY_ID, LAST_MODIFIED_BY, LAST_MODIFIED_DATE, PROJECT_ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
	bind => [44f14428-dff2-9825-a219-194b14741b5e, zhfkegazct, 2024-06-05T18:19:14.037+08:00, EC00515 Desc, EC00515, null, 2024-06-05T18:19:14.037+08:00, null]
Query: InsertObjectQuery(com.ipectechnologies.cdpcloud.entity.P6Hierarchy-44f14428-dff2-9825-a219-194b14741b5e [detached])
	at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:334) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:948) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:1010) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:657) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:569) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2058) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:311) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:280) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:266) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:436) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:193) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:209) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:514) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:86) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:97) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:326) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:61) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:913) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:812) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:109) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:86) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:3063) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1851) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1833) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1783) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:248) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:147) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4345) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1511) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithPreBuiltChangeSet(UnitOfWorkImpl.java:1657) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:472) ~[org.eclipse.persistence.core-4.0.2-3-jmix.jar:na]
	at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:966) ~[org.eclipse.persistence.jpa-4.0.2-3-jmix.jar:na]
	... 114 common frames omitted

Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: unique constraint or index violation ; IDX_CDP_P6_HIERARCHY_UNQ table: CDP_P6_HIERARCHY
	at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) ~[hsqldb-2.7.2.jar:2.7.2]
Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: unique constraint or index violation ; IDX_CDP_P6_HIERARCHY_UNQ table: CDP_P6_HIERARCHY

Thanks.

Hi,

You can create a custom exception handler in your project. You need to create a @ControllerAdvice that will handle UniqueConstraintViolationException:

import io.jmix.data.exception.UniqueConstraintViolationException;
import io.jmix.rest.impl.controller.ErrorInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice("io.jmix.rest.impl.controller")
@Order(0)
public class MyRestControllerExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(MyRestControllerExceptionHandler.class);

    @ExceptionHandler(UniqueConstraintViolationException.class)
    @ResponseBody
    public ResponseEntity<ErrorInfo> handleUniqueConstraintViolationException(UniqueConstraintViolationException e) {
        log.info("UniqueConstraintViolationException: {}", e.getConstraintName(), e);
        ErrorInfo errorInfo = new ErrorInfo("Unique constraint violation", e.getConstraintName());
        return new ResponseEntity<>(errorInfo, HttpStatus.CONFLICT);
    }
}
  • @ControllerAdvice("io.jmix.rest.impl.controller") - handles errors thrown by Jmix REST add-on classes
  • @Order(0) - to be processed before @ControllerAdvice from the REST add-on
  • @ExceptionHandler(UniqueConstraintViolationException.class) - exception class to be handled

Here is a sample project that demonstrates this: rest-unique.zip (104.9 KB)

1 Like