From 2a71f61cc28376636e8463e15126352a30d9454d Mon Sep 17 00:00:00 2001 From: Stanislav Trailov Date: Tue, 29 Apr 2025 17:20:17 +0300 Subject: [PATCH] Extend current SQL translator in EclipseLink (#2383) * Extend current SQL translator in EclipseLink * Initialize translator in static block Signed-off-by: strailov * translation methods to static Signed-off-by: strailov * handle DataIntegrityViolation in rest core Signed-off-by: strailov --------- Signed-off-by: strailov --- .../jpa/HawkbitEclipseLinkJpaDialect.java | 20 +++++++++++++++++-- .../ExceptionMappingAspectHandler.java | 3 --- hawkbit-rest-core/pom.xml | 4 ++++ .../hawkbit/rest/RestConfiguration.java | 16 +++++++++++++++ 4 files changed, 38 insertions(+), 5 deletions(-) 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); }