You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by nr...@apache.org on 2018/03/13 20:07:50 UTC
[geode] branch develop updated: GEODE-4266: Make
JdbcConnectionException safely serializable to clients (#1601)
This is an automated email from the ASF dual-hosted git repository.
nreich pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new a07b67a GEODE-4266: Make JdbcConnectionException safely serializable to clients (#1601)
a07b67a is described below
commit a07b67a7dc7828528864520352daf7401249dac7
Author: Nick Reich <nr...@pivotal.io>
AuthorDate: Tue Mar 13 13:07:46 2018 -0700
GEODE-4266: Make JdbcConnectionException safely serializable to clients (#1601)
* SQLExceptions that come from underlying sql drivers may not be availale
on clients or locators and will not be deserializable. When these
exceptions are contained in a JdbcConnectorException, the stack trace
is instead converted to a string to ensure safe serialization
---
.../connectors/jdbc/JdbcConnectorException.java | 53 +++++++++++++++++++++-
.../apache/geode/connectors/jdbc/JdbcLoader.java | 2 +-
.../apache/geode/connectors/jdbc/JdbcWriter.java | 2 +-
.../jdbc/internal/TableKeyColumnManager.java | 2 +-
.../jdbc/JdbcConnectorExceptionTest.java | 47 +++++++++++++++++++
5 files changed, 101 insertions(+), 5 deletions(-)
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcConnectorException.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcConnectorException.java
index 24674ea..d152873 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcConnectorException.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcConnectorException.java
@@ -14,18 +14,67 @@
*/
package org.apache.geode.connectors.jdbc;
+import java.sql.SQLException;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+
import org.apache.geode.cache.CacheRuntimeException;
/**
* An exception thrown when communication with an external JDBC data source fails and can be used
- * to diagnose the cause of database communication failures.
+ * to diagnose the cause of database communication failures. In cases where the cause of this
+ * exception is not safe to serialize to clients, the stack trace is included in the message of the
+ * exception and the cause is left empty.
*
* @since Geode 1.5
*/
public class JdbcConnectorException extends CacheRuntimeException {
private static final long serialVersionUID = 1L;
- public JdbcConnectorException(Exception e) {
+ /**
+ * Create a new JdbcConnectorException by first checking to see if the causing exception is or
+ * contains an exception that potentially could not be deserialized by remote systems receiving
+ * the serialized exception.
+ *
+ * @param e cause of this Exception
+ * @return a new JdbcConnectorException containing either the causing exception, if it can be
+ * serialized/deserialized by Geode, or containing the causing exception stack trace in
+ * its message if not
+ */
+ public static JdbcConnectorException createException(Exception e) {
+ String message;
+ if (containsNonSerializableException(e)) {
+ message = e.getMessage() + System.lineSeparator() + ExceptionUtils.getFullStackTrace(e);
+ return new JdbcConnectorException(message);
+ } else {
+ return new JdbcConnectorException(e);
+ }
+ }
+
+ /*
+ * SQLExceptions likely are instances of or contain exceptions from the underlying SQL driver
+ * and potentially cannot be deserialzed by other systems (e.g. client or locators) that do not
+ * possess the driver on their classpaths.
+ */
+ private static boolean containsNonSerializableException(Exception e) {
+ if (e == null) {
+ return false;
+ }
+
+ if (e instanceof SQLException) {
+ return true;
+ }
+
+ Throwable cause;
+ while ((cause = e.getCause()) != null) {
+ if (cause instanceof SQLException) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private JdbcConnectorException(Exception e) {
super(e);
}
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcLoader.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcLoader.java
index 5196bce..d76baf9 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcLoader.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcLoader.java
@@ -54,7 +54,7 @@ public class JdbcLoader<K, V> extends AbstractJdbcCallback implements CacheLoade
try {
return (V) getSqlHandler().read(helper.getRegion(), helper.getKey());
} catch (SQLException e) {
- throw new JdbcConnectorException(e);
+ throw JdbcConnectorException.createException(e);
}
}
}
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcWriter.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcWriter.java
index 777a5f3..193066f 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcWriter.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/JdbcWriter.java
@@ -78,7 +78,7 @@ public class JdbcWriter<K, V> extends AbstractJdbcCallback implements CacheWrite
getSqlHandler().write(event.getRegion(), event.getOperation(), event.getKey(),
getPdxNewValue(event));
} catch (SQLException e) {
- throw new JdbcConnectorException(e);
+ throw JdbcConnectorException.createException(e);
}
}
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableKeyColumnManager.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableKeyColumnManager.java
index 03c9e69..5fccb66 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableKeyColumnManager.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableKeyColumnManager.java
@@ -47,7 +47,7 @@ class TableKeyColumnManager {
key = getPrimaryKeyColumnNameFromMetaData(realTableName, metaData);
}
} catch (SQLException e) {
- throw new JdbcConnectorException(e);
+ throw JdbcConnectorException.createException(e);
}
return key;
}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcConnectorExceptionTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcConnectorExceptionTest.java
new file mode 100644
index 0000000..fe138db
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcConnectorExceptionTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.geode.connectors.jdbc;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.sql.SQLException;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TestName;
+
+import org.apache.geode.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class JdbcConnectorExceptionTest {
+ @Rule
+ public TestName testName = new TestName();
+
+ @Test
+ public void returnsExceptionWithCauseForNonSqlException() {
+ Exception e = JdbcConnectorException.createException(new IllegalStateException());
+ assertThat(e.getCause()).isNotNull().isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ public void returnsExceptionWithNoCauseForSqlException() {
+ Exception sqlException = new SQLException();
+ Exception e = JdbcConnectorException.createException(sqlException);
+ assertThat(e.getCause()).isNull();
+ assertThat(e.getMessage())
+ .contains(this.getClass().getCanonicalName() + "." + testName.getMethodName());
+ }
+}
--
To stop receiving notification emails like this one, please contact
nreich@apache.org.