[ 
https://issues.apache.org/jira/browse/HBASE-13419?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Michael Muller updated HBASE-13419:
-----------------------------------
    Status: Patch Available  (was: Open)

>From 475978873c0bf0bcad5a10e371f20d8191f3f582 Mon Sep 17 00:00:00 2001
From: Michael Muller <[email protected]>
Date: Tue, 7 Apr 2015 10:57:46 -0400
Subject: [PATCH] Expand the exception causes in the thrift gateway.

Expand the full chain of exception causes when passing an error back up to a
thrift client so useful information doesn't get lost when the exception is
flattened.
---
 .../hadoop/hbase/thrift/ThriftServerRunner.java    | 93 +++++++++++++---------
 .../hadoop/hbase/thrift/TestThriftServerUnit.java  | 39 +++++++++
 2 files changed, 95 insertions(+), 37 deletions(-)
 create mode 100644 
hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift/TestThriftServerUnit.java

diff --git 
a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java
 
b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java
index 617fab6..bf44008 100644
--- 
a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java
+++ 
b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java
@@ -755,7 +755,7 @@ public class ThriftServerRunner implements Runnable {
         getAdmin().enableTable(getTableName(tableName));
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -765,7 +765,7 @@ public class ThriftServerRunner implements Runnable {
         getAdmin().disableTable(getTableName(tableName));
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -775,7 +775,7 @@ public class ThriftServerRunner implements Runnable {
         return 
this.connectionCache.getAdmin().isTableEnabled(getTableName(tableName));
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -788,7 +788,7 @@ public class ThriftServerRunner implements Runnable {
         ((HBaseAdmin) getAdmin()).compact(getBytes(tableNameOrRegionName));
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -801,7 +801,7 @@ public class ThriftServerRunner implements Runnable {
         ((HBaseAdmin) 
getAdmin()).majorCompact(getBytes(tableNameOrRegionName));
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -816,7 +816,7 @@ public class ThriftServerRunner implements Runnable {
         return list;
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -849,7 +849,7 @@ public class ThriftServerRunner implements Runnable {
         return Collections.emptyList();
       } catch (IOException e){
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -894,7 +894,7 @@ public class ThriftServerRunner implements Runnable {
         return ThriftUtilities.cellFromHBase(result.rawCells());
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -937,7 +937,7 @@ public class ThriftServerRunner implements Runnable {
         return ThriftUtilities.cellFromHBase(result.rawCells());
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -981,7 +981,7 @@ public class ThriftServerRunner implements Runnable {
         return ThriftUtilities.cellFromHBase(result.rawCells());
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1038,7 +1038,7 @@ public class ThriftServerRunner implements Runnable {
         return ThriftUtilities.rowResultFromHBase(result);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1103,7 +1103,7 @@ public class ThriftServerRunner implements Runnable {
         return ThriftUtilities.rowResultFromHBase(result);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1135,7 +1135,7 @@ public class ThriftServerRunner implements Runnable {
 
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1157,7 +1157,7 @@ public class ThriftServerRunner implements Runnable {
         table.delete(delete);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1178,10 +1178,10 @@ public class ThriftServerRunner implements Runnable {
         getAdmin().createTable(desc);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       } catch (IllegalArgumentException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IllegalArgument(e.getMessage());
+        throw new IllegalArgument(expandCauses(e));
       }
     }
 
@@ -1202,7 +1202,7 @@ public class ThriftServerRunner implements Runnable {
         getAdmin().deleteTable(tableName);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1260,10 +1260,10 @@ public class ThriftServerRunner implements Runnable {
           table.put(put);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       } catch (IllegalArgumentException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IllegalArgument(e.getMessage());
+        throw new IllegalArgument(expandCauses(e));
       }
     }
 
@@ -1331,10 +1331,10 @@ public class ThriftServerRunner implements Runnable {
 
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       } catch (IllegalArgumentException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IllegalArgument(e.getMessage());
+        throw new IllegalArgument(expandCauses(e));
       }
     }
 
@@ -1360,7 +1360,7 @@ public class ThriftServerRunner implements Runnable {
             getBytes(row), family, qualifier, amount);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1396,7 +1396,7 @@ public class ThriftServerRunner implements Runnable {
         }
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
       return ThriftUtilities.rowResultFromHBase(results, 
resultScannerWrapper.isColumnSorted());
     }
@@ -1450,7 +1450,7 @@ public class ThriftServerRunner implements Runnable {
         return addScanner(table.getScanner(scan), tScan.sortColumns);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1475,7 +1475,7 @@ public class ThriftServerRunner implements Runnable {
         return addScanner(table.getScanner(scan), false);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1501,7 +1501,7 @@ public class ThriftServerRunner implements Runnable {
         return addScanner(table.getScanner(scan), false);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1531,7 +1531,7 @@ public class ThriftServerRunner implements Runnable {
         return addScanner(table.getScanner(scan), false);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1557,7 +1557,7 @@ public class ThriftServerRunner implements Runnable {
         return addScanner(table.getScanner(scan), false);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1585,7 +1585,7 @@ public class ThriftServerRunner implements Runnable {
         return addScanner(table.getScanner(scan), false);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1606,7 +1606,7 @@ public class ThriftServerRunner implements Runnable {
         return columns;
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1619,7 +1619,7 @@ public class ThriftServerRunner implements Runnable {
         return ThriftUtilities.cellFromHBase(result.rawCells());
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1658,7 +1658,7 @@ public class ThriftServerRunner implements Runnable {
         return region;
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1696,7 +1696,7 @@ public class ThriftServerRunner implements Runnable {
         table.increment(inc);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1724,7 +1724,7 @@ public class ThriftServerRunner implements Runnable {
         return ThriftUtilities.cellFromHBase(result.rawCells());
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       }
     }
 
@@ -1745,7 +1745,7 @@ public class ThriftServerRunner implements Runnable {
         put.setDurability(mput.writeToWAL ? Durability.SYNC_WAL : 
Durability.SKIP_WAL);
       } catch (IllegalArgumentException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IllegalArgument(e.getMessage());
+        throw new IllegalArgument(expandCauses(e));
       }
 
       Table table = null;
@@ -1756,15 +1756,34 @@ public class ThriftServerRunner implements Runnable {
           value != null ? getBytes(value) : HConstants.EMPTY_BYTE_ARRAY, put);
       } catch (IOException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IOError(e.getMessage());
+        throw new IOError(expandCauses(e));
       } catch (IllegalArgumentException e) {
         LOG.warn(e.getMessage(), e);
-        throw new IllegalArgument(e.getMessage());
+        throw new IllegalArgument(expandCauses(e));
       }
     }
   }
 
+  /**
+   * Join all of the messages of the "cause" throwables so we don't lose
+   * root cause information.
+   */
+  protected static String expandCauses(Throwable e) {
+    StringBuilder builder = new StringBuilder();
+    while (e != null) {
+      System.out.println("Considering " + e);
+      String message = e.getMessage();
+      if (message != null) {
+        if (builder.length() > 0) {
+          builder.append(": ");
+        }
+        builder.append(message);
+      }
+      e = e.getCause();
+    }
 
+    return builder.toString();
+  }
 
   /**
    * Adds all the attributes into the Operation object
diff --git 
a/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift/TestThriftServerUnit.java
 
b/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift/TestThriftServerUnit.java
new file mode 100644
index 0000000..29f02b2
--- /dev/null
+++ 
b/hbase-thrift/src/test/java/org/apache/hadoop/hbase/thrift/TestThriftServerUnit.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.hadoop.hbase.thrift;
+
+import org.apache.hadoop.hbase.testclassification.ClientTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import static org.junit.Assert.assertEquals;
+
+@Category({SmallTests.class})
+public class TestThriftServerUnit {
+  @Test
+  public void testErrorMessageExpansion() {
+    Throwable a = new Throwable("Inner");
+    Throwable b = new Throwable(a);
+    Throwable c = new Throwable("Outer", b);
+
+    assertEquals("Outer: java.lang.Throwable: Inner: Inner", 
ThriftServerRunner.expandCauses(c));
+  }
+}
+
-- 
2.2.0.rc0.207.ga3a616c


> Thrift gateway should propagate text from exception causes.
> -----------------------------------------------------------
>
>                 Key: HBASE-13419
>                 URL: https://issues.apache.org/jira/browse/HBASE-13419
>             Project: HBase
>          Issue Type: Improvement
>          Components: Thrift
>            Reporter: Michael Muller
>              Labels: newbie, patch
>             Fix For: 2.0.0, 1.0.1, 1.1.0
>
>
> Exceptions passed back from the thrift gateway only include the message text 
> of the toplevel exception.  Information from the cause chain is lost.
> In some cases, the top-level exception text is useless but there is some very 
> specific and useful information provided in some of the cause exceptions, so 
> it would be very helpful to flatten all of the messages into the exception 
> text returned to the user.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to