This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 813ed5eec726 CAMEL-26704: camel-sql - 
DefaultJdbcOptimisticLockingExceptionMapper should not fail on an SQLException 
without SQLState (#29401)
813ed5eec726 is described below

commit 813ed5eec7267343a5bd988c1072a0eca8c552b3
Author: allthingssecurity <[email protected]>
AuthorDate: Sun Nov 8 13:32:22 2026 +0530

    CAMEL-26704: camel-sql - DefaultJdbcOptimisticLockingExceptionMapper should 
not fail on an SQLException without SQLState (#29401)
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 ...efaultJdbcOptimisticLockingExceptionMapper.java |  4 +-
 ...ltJdbcOptimisticLockingExceptionMapperTest.java | 62 ++++++++++++++++++++++
 2 files changed, 65 insertions(+), 1 deletion(-)

diff --git 
a/components/camel-sql/src/main/java/org/apache/camel/processor/aggregate/jdbc/DefaultJdbcOptimisticLockingExceptionMapper.java
 
b/components/camel-sql/src/main/java/org/apache/camel/processor/aggregate/jdbc/DefaultJdbcOptimisticLockingExceptionMapper.java
index 598d49d72914..aeed7a26c202 100644
--- 
a/components/camel-sql/src/main/java/org/apache/camel/processor/aggregate/jdbc/DefaultJdbcOptimisticLockingExceptionMapper.java
+++ 
b/components/camel-sql/src/main/java/org/apache/camel/processor/aggregate/jdbc/DefaultJdbcOptimisticLockingExceptionMapper.java
@@ -74,7 +74,9 @@ public class DefaultJdbcOptimisticLockingExceptionMapper 
implements JdbcOptimist
     }
 
     public static boolean isConstraintViolation(SQLException e) {
-        return e.getSQLState().startsWith("23");
+        // the SQLState is optional, for example connection pools report a 
pool timeout without one
+        String state = e.getSQLState();
+        return state != null && state.startsWith("23");
     }
 
     private boolean hasClassName(String name) {
diff --git 
a/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/DefaultJdbcOptimisticLockingExceptionMapperTest.java
 
b/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/DefaultJdbcOptimisticLockingExceptionMapperTest.java
new file mode 100644
index 000000000000..323e78bb626b
--- /dev/null
+++ 
b/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/DefaultJdbcOptimisticLockingExceptionMapperTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.processor.aggregate.jdbc;
+
+import java.sql.SQLException;
+import java.sql.SQLTransientConnectionException;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.transaction.CannotCreateTransactionException;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class DefaultJdbcOptimisticLockingExceptionMapperTest {
+
+    private final DefaultJdbcOptimisticLockingExceptionMapper mapper = new 
DefaultJdbcOptimisticLockingExceptionMapper();
+
+    @Test
+    public void testSQLExceptionWithoutSQLState() {
+        // a connection pool timeout has no SQLState
+        SQLException cause = new SQLTransientConnectionException("Connection 
is not available, request timed out");
+
+        
assertFalse(DefaultJdbcOptimisticLockingExceptionMapper.isConstraintViolation(cause));
+        assertFalse(mapper.isOptimisticLocking(new 
CannotCreateTransactionException("Could not open connection", cause)));
+    }
+
+    @Test
+    public void testSQLExceptionWithoutSQLStateAndConfiguredClassName() {
+        mapper.addClassName(VendorLockException.class.getName());
+
+        Exception cause = new VendorLockException(new SQLException("Lock 
conflict"));
+
+        assertTrue(mapper.isOptimisticLocking(cause));
+    }
+
+    @Test
+    public void testSQLExceptionWithSQLState() {
+        assertTrue(mapper.isOptimisticLocking(new RuntimeException(new 
SQLException("Duplicate key", "23505"))));
+        assertFalse(mapper.isOptimisticLocking(new RuntimeException(new 
SQLException("Connection refused", "08001"))));
+    }
+
+    private static class VendorLockException extends Exception {
+
+        VendorLockException(Throwable cause) {
+            super(cause);
+        }
+    }
+}

Reply via email to