Return-Path: X-Original-To: apmail-hbase-issues-archive@www.apache.org Delivered-To: apmail-hbase-issues-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id F090C17D12 for ; Tue, 7 Apr 2015 19:07:22 +0000 (UTC) Received: (qmail 90279 invoked by uid 500); 7 Apr 2015 19:07:13 -0000 Delivered-To: apmail-hbase-issues-archive@hbase.apache.org Received: (qmail 90232 invoked by uid 500); 7 Apr 2015 19:07:13 -0000 Mailing-List: contact issues-help@hbase.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Delivered-To: mailing list issues@hbase.apache.org Received: (qmail 90219 invoked by uid 99); 7 Apr 2015 19:07:13 -0000 Received: from arcas.apache.org (HELO arcas.apache.org) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 Apr 2015 19:07:13 +0000 Date: Tue, 7 Apr 2015 19:07:13 +0000 (UTC) From: "Michael Muller (JIRA)" To: issues@hbase.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Updated] (HBASE-13419) Thrift gateway should propagate text from exception causes. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 [ 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 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)