From 9719e1d2101779dd6196a0fe68ee76ea3bf3d0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Barto=C5=A1?= Date: Wed, 22 Mar 2023 12:39:40 +0100 Subject: [PATCH] Handle DB exceptions for JTA TX --- .../jpa/PersistenceExceptionConverter.java | 21 ++++++++++++++++--- .../jpa/PersistenceExceptionConverter.java | 21 ++++++++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/PersistenceExceptionConverter.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/PersistenceExceptionConverter.java index df89542273..2153af0a4d 100644 --- a/model/jpa/src/main/java/org/keycloak/connections/jpa/PersistenceExceptionConverter.java +++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/PersistenceExceptionConverter.java @@ -29,6 +29,8 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.sql.SQLIntegrityConstraintViolationException; +import java.util.function.Predicate; import java.util.regex.Pattern; /** @@ -75,10 +77,23 @@ public class PersistenceExceptionConverter implements InvocationHandler { } } + // For JTA, the database operations are executed during the commit phase of a transaction, and DB exceptions can be propagated differently public static ModelException convert(Throwable t) { - if (t.getCause() != null && t.getCause() instanceof ConstraintViolationException) { - throw new ModelDuplicateException(t); - } if (t instanceof EntityExistsException || t instanceof ConstraintViolationException) { + final Predicate checkDuplicationMessage = throwable -> { + final String message = throwable.getCause() != null ? throwable.getCause().getMessage() : throwable.getMessage(); + return message.toLowerCase().contains("duplicate"); + }; + + Predicate throwModelDuplicateEx = throwable -> + throwable instanceof EntityExistsException + || throwable instanceof ConstraintViolationException + || throwable instanceof SQLIntegrityConstraintViolationException; + + throwModelDuplicateEx = throwModelDuplicateEx.or(checkDuplicationMessage); + + if (t.getCause() != null && throwModelDuplicateEx.test(t.getCause())) { + throw new ModelDuplicateException(t.getCause()); + } else if (throwModelDuplicateEx.test(t)) { throw new ModelDuplicateException(t); } else { throw new ModelException(t); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/PersistenceExceptionConverter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/PersistenceExceptionConverter.java index 398408bf58..d68dc599be 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/PersistenceExceptionConverter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/PersistenceExceptionConverter.java @@ -27,6 +27,8 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.sql.SQLIntegrityConstraintViolationException; +import java.util.function.Predicate; /** * @author Stian Thorgersen @@ -52,10 +54,23 @@ public class PersistenceExceptionConverter implements InvocationHandler { } } + // For JTA, the database operations are executed during the commit phase of a transaction, and DB exceptions can be propagated differently public static ModelException convert(Throwable t) { - if (t.getCause() != null && t.getCause() instanceof ConstraintViolationException) { - throw new ModelDuplicateException(t); - } if (t instanceof EntityExistsException) { + final Predicate checkDuplicationMessage = throwable -> { + final String message = throwable.getCause() != null ? throwable.getCause().getMessage() : throwable.getMessage(); + return message.toLowerCase().contains("duplicate"); + }; + + Predicate throwModelDuplicateEx = throwable -> + throwable instanceof EntityExistsException + || throwable instanceof ConstraintViolationException + || throwable instanceof SQLIntegrityConstraintViolationException; + + throwModelDuplicateEx = throwModelDuplicateEx.or(checkDuplicationMessage); + + if (t.getCause() != null && throwModelDuplicateEx.test(t.getCause())) { + throw new ModelDuplicateException(t.getCause()); + } else if (throwModelDuplicateEx.test(t)) { throw new ModelDuplicateException(t); } else { throw new ModelException(t);