diff --git a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkbitEclipseLinkJpaDialect.java b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkbitEclipseLinkJpaDialect.java
index 397df02cf..79f52b69d 100644
--- a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkbitEclipseLinkJpaDialect.java
+++ b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkbitEclipseLinkJpaDialect.java
@@ -15,6 +15,8 @@ import java.sql.SQLException;
import jakarta.persistence.PersistenceException;
import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
+import org.springframework.jdbc.support.SQLErrorCodes;
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
import org.springframework.lang.NonNull;
import org.springframework.orm.jpa.JpaSystemException;
@@ -54,7 +56,20 @@ class HawkbitEclipseLinkJpaDialect extends EclipseLinkJpaDialect {
@Serial
private static final long serialVersionUID = 1L;
- private static final SQLStateSQLExceptionTranslator SQLSTATE_EXCEPTION_TRANSLATOR = new SQLStateSQLExceptionTranslator();
+ private static final SQLErrorCodeSQLExceptionTranslator SQL_EXCEPTION_TRANSLATOR;
+
+ // providing list/set of codes which are not handled from the sql translator properly
+ private static final String[] DATA_INTEGRITY_VIOLATION_CODES = new String[] {
+ "1366"
+ };
+
+ static {
+ SQL_EXCEPTION_TRANSLATOR = new SQLErrorCodeSQLExceptionTranslator();
+ SQLErrorCodes codes = new SQLErrorCodes();
+
+ codes.setDataIntegrityViolationCodes(DATA_INTEGRITY_VIOLATION_CODES);
+ SQL_EXCEPTION_TRANSLATOR.setSqlErrorCodes(codes);
+ }
@Override
public DataAccessException translateExceptionIfPossible(@NonNull final RuntimeException ex) {
@@ -84,7 +99,8 @@ class HawkbitEclipseLinkJpaDialect extends EclipseLinkJpaDialect {
if (sqlException == null) {
return null;
}
- return SQLSTATE_EXCEPTION_TRANSLATOR.translate("", null, sqlException);
+
+ return SQL_EXCEPTION_TRANSLATOR.translate("", null, sqlException);
}
private static SQLException findSqlException(final RuntimeException jpaSystemException) {
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java
index 72c91153d..7715fd34c 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java
@@ -24,7 +24,6 @@ import org.eclipse.hawkbit.repository.exception.ConcurrentModificationException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.springframework.core.Ordered;
-import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.security.access.AccessDeniedException;
@@ -49,12 +48,10 @@ public class ExceptionMappingAspectHandler implements Ordered {
static {
MAPPED_EXCEPTION_ORDER.add(DuplicateKeyException.class);
- MAPPED_EXCEPTION_ORDER.add(DataIntegrityViolationException.class);
MAPPED_EXCEPTION_ORDER.add(OptimisticLockingFailureException.class);
MAPPED_EXCEPTION_ORDER.add(AccessDeniedException.class);
EXCEPTION_MAPPING.put(DuplicateKeyException.class.getName(), EntityAlreadyExistsException.class.getName());
- EXCEPTION_MAPPING.put(DataIntegrityViolationException.class.getName(), EntityAlreadyExistsException.class.getName());
EXCEPTION_MAPPING.put(OptimisticLockingFailureException.class.getName(), ConcurrentModificationException.class.getName());
EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), InsufficientPermissionException.class.getName());
diff --git a/hawkbit-rest-core/pom.xml b/hawkbit-rest-core/pom.xml
index 40e3583e8..004123a3e 100644
--- a/hawkbit-rest-core/pom.xml
+++ b/hawkbit-rest-core/pom.xml
@@ -46,6 +46,10 @@
org.springframework.hateoas
spring-hateoas
+
+ org.springframework
+ spring-tx
+
org.springframework.data
spring-data-commons
diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java
index 127f02556..e86eecd10 100644
--- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java
+++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java
@@ -33,6 +33,7 @@ import org.eclipse.hawkbit.rest.util.FileStreamingFailedException;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
import org.springframework.http.HttpStatus;
@@ -272,6 +273,21 @@ public class RestConfiguration {
return new ResponseEntity<>(createExceptionInfo(new MultiPartFileUploadException(responseCause)), HttpStatus.BAD_REQUEST);
}
+ @ExceptionHandler({DataIntegrityViolationException.class})
+ public ResponseEntity handleDataAccessException(final HttpServletRequest request, final DataIntegrityViolationException ex) {
+ if (log.isDebugEnabled()) {
+ logRequest(request, ex);
+ } else {
+ log.error("Handling exception {} of request {}", ex.getClass().getName(), request.getRequestURL());
+ }
+
+ final ExceptionInfo response = new ExceptionInfo();
+ response.setMessage("The data provided violates integrity rules. Please ensure all required fields are valid.");
+ response.setExceptionClass(ex.getClass().getName());
+
+ return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
+ }
+
private static HttpStatus getStatusOrDefault(final SpServerError error) {
return ERROR_TO_HTTP_STATUS.getOrDefault(error, DEFAULT_RESPONSE_STATUS);
}