hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ndimi...@apache.org
Subject svn commit: r1552369 - in /hbase/branches/0.98/hbase-server/src: main/java/org/apache/hadoop/hbase/rest/ test/java/org/apache/hadoop/hbase/rest/ test/java/org/apache/hadoop/hbase/rest/client/
Date Thu, 19 Dec 2013 17:31:02 GMT
Author: ndimiduk
Date: Thu Dec 19 17:31:02 2013
New Revision: 1552369

URL: http://svn.apache.org/r1552369
Log:
HBASE-9524 Multi row get does not return any results even if any one of the rows specified in the query is missing and improve exception handling (Vandana Ayyalasomayajula)

Added:
    hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/RowResourceBase.java
    hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestDeleteRow.java
    hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestGetAndPutResource.java
Removed:
    hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestRowResource.java
Modified:
    hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/MultiRowResource.java
    hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/ResourceBase.java
    hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RootResource.java
    hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java
    hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/SchemaResource.java
    hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestMultiRowResource.java
    hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java

Modified: hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/MultiRowResource.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/MultiRowResource.java?rev=1552369&r1=1552368&r2=1552369&view=diff
==============================================================================
--- hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/MultiRowResource.java (original)
+++ hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/MultiRowResource.java Thu Dec 19 17:31:02 2013
@@ -27,6 +27,8 @@ import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.CellUtil;
@@ -36,6 +38,7 @@ import org.apache.hadoop.hbase.rest.mode
 
 @InterfaceAudience.Private
 public class MultiRowResource extends ResourceBase {
+  private static final Log LOG = LogFactory.getLog(MultiRowResource.class);
   public static final String ROW_KEYS_PARAM_NAME = "row";
 
   TableResource tableResource;
@@ -59,8 +62,7 @@ public class MultiRowResource extends Re
   }
 
   @GET
-  @Produces({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
-    MIMETYPE_PROTOBUF_IETF})
+  @Produces({ MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF, MIMETYPE_PROTOBUF_IETF })
   public Response get(final @Context UriInfo uriInfo) {
     MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
 
@@ -75,32 +77,33 @@ public class MultiRowResource extends Re
         }
 
         ResultGenerator generator =
-          ResultGenerator.fromRowSpec(this.tableResource.getName(), rowSpec, null);
-        if (!generator.hasNext()) {
-          return Response.status(Response.Status.NOT_FOUND)
-            .type(MIMETYPE_TEXT).entity("Not found" + CRLF)
-            .build();
-        }
-
+            ResultGenerator.fromRowSpec(this.tableResource.getName(), rowSpec, null);
         Cell value = null;
         RowModel rowModel = new RowModel(rk);
-
-        while ((value = generator.next()) != null) {
-          rowModel.addCell(new CellModel(CellUtil.cloneFamily(value),
-              CellUtil.cloneQualifier(value),
-            value.getTimestamp(), CellUtil.cloneValue(value)));
+        if (generator.hasNext()) {
+          while ((value = generator.next()) != null) {
+            rowModel.addCell(new CellModel(CellUtil.cloneFamily(value), CellUtil
+                .cloneQualifier(value), value.getTimestamp(), CellUtil.cloneValue(value)));
+          }
+          model.addRow(rowModel);
+        } else {
+          LOG.trace("The row : " + rk + " not found in the table.");
         }
+      }
 
-        model.addRow(rowModel);
+      if (model.getRows().size() == 0) {
+      //If no rows found.
+        servlet.getMetrics().incrementFailedGetRequests(1);
+        return Response.status(Response.Status.NOT_FOUND)
+            .type(MIMETYPE_TEXT).entity("No rows found." + CRLF)
+            .build();
+      } else {
+        servlet.getMetrics().incrementSucessfulGetRequests(1);
+        return Response.ok(model).build();
       }
-      servlet.getMetrics().incrementSucessfulGetRequests(1);
-      return Response.ok(model).build();
-    } catch (IOException e) {
+    } catch (Exception e) {
       servlet.getMetrics().incrementFailedGetRequests(1);
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+      return processException(e);
     }
-
   }
 }

Modified: hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/ResourceBase.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/ResourceBase.java?rev=1552369&r1=1552368&r2=1552369&view=diff
==============================================================================
--- hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/ResourceBase.java (original)
+++ hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/ResourceBase.java Thu Dec 19 17:31:02 2013
@@ -21,14 +21,73 @@ package org.apache.hadoop.hbase.rest;
 
 import java.io.IOException;
 
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
 import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.TableNotFoundException;
+import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;
+import org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException;
+import org.apache.hadoop.util.StringUtils;
 
 @InterfaceAudience.Private
 public class ResourceBase implements Constants {
 
   RESTServlet servlet;
+  Class<?>  accessDeniedClazz;
 
   public ResourceBase() throws IOException {
     servlet = RESTServlet.getInstance();
+    try {
+      accessDeniedClazz = Class.forName("org.apache.hadoop.hbase.security.AccessDeniedException");
+    } catch (ClassNotFoundException e) {
+    }
+  }
+  
+  protected Response processException(Throwable exp) {
+    Throwable curr = exp;
+    if(accessDeniedClazz != null) {
+      //some access denied exceptions are buried
+      while (curr != null) {
+        if(accessDeniedClazz.isAssignableFrom(curr.getClass())) {
+          throw new SecurityException("Unauthorized" + CRLF +
+              StringUtils.stringifyException(exp) + CRLF);
+        }
+        curr = curr.getCause();
+      }
+    }
+    //TableNotFound may also be buried one level deep
+    if (exp instanceof TableNotFoundException ||
+        exp.getCause() instanceof TableNotFoundException) {
+      throw new WebApplicationException(
+        Response.status(Response.Status.NOT_FOUND)
+          .type(MIMETYPE_TEXT).entity("Not found" + CRLF +
+             StringUtils.stringifyException(exp) + CRLF)
+          .build());
+    }
+    if (exp instanceof NoSuchColumnFamilyException){
+      throw new WebApplicationException(
+        Response.status(Response.Status.NOT_FOUND)
+          .type(MIMETYPE_TEXT).entity("Not found" + CRLF +
+             StringUtils.stringifyException(exp) + CRLF)
+          .build());
+    }
+    if (exp instanceof RuntimeException) {
+      throw new WebApplicationException(
+          Response.status(Response.Status.BAD_REQUEST)
+            .type(MIMETYPE_TEXT).entity("Bad request" + CRLF +
+              StringUtils.stringifyException(exp) + CRLF)
+            .build());
+    }
+    if (exp instanceof RetriesExhaustedWithDetailsException) {
+      RetriesExhaustedWithDetailsException retryException =
+          (RetriesExhaustedWithDetailsException) exp;
+      processException(retryException.getCause(0));
+    }
+    throw new WebApplicationException(
+      Response.status(Response.Status.SERVICE_UNAVAILABLE)
+        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF +
+          StringUtils.stringifyException(exp) + CRLF)
+        .build());
   }
 }

Modified: hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RootResource.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RootResource.java?rev=1552369&r1=1552368&r2=1552369&view=diff
==============================================================================
--- hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RootResource.java (original)
+++ hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RootResource.java Thu Dec 19 17:31:02 2013
@@ -81,11 +81,9 @@ public class RootResource extends Resour
       response.cacheControl(cacheControl);
       servlet.getMetrics().incrementSucessfulGetRequests(1);
       return response.build();
-    } catch (IOException e) {
+    } catch (Exception e) {
       servlet.getMetrics().incrementFailedGetRequests(1);
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+      return processException(e);
     }
   }
 

Modified: hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java?rev=1552369&r1=1552368&r2=1552369&view=diff
==============================================================================
--- hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java (original)
+++ hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java Thu Dec 19 17:31:02 2013
@@ -35,6 +35,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.UriInfo;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.classification.InterfaceAudience;
@@ -42,7 +43,6 @@ import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.CellUtil;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.KeyValue;
-import org.apache.hadoop.hbase.TableNotFoundException;
 import org.apache.hadoop.hbase.client.Delete;
 import org.apache.hadoop.hbase.client.HTableInterface;
 import org.apache.hadoop.hbase.client.Put;
@@ -118,21 +118,9 @@ public class RowResource extends Resourc
       model.addRow(rowModel);
       servlet.getMetrics().incrementSucessfulGetRequests(1);
       return Response.ok(model).build();
-    } catch (RuntimeException e) {
-      servlet.getMetrics().incrementFailedGetRequests(1);
-      if (e.getCause() instanceof TableNotFoundException) {
-        return Response.status(Response.Status.NOT_FOUND)
-          .type(MIMETYPE_TEXT).entity("Not found" + CRLF)
-          .build();
-      }
-      return Response.status(Response.Status.BAD_REQUEST)
-        .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
-        .build();
     } catch (Exception e) {
-      servlet.getMetrics().incrementFailedGetRequests(1);
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+      servlet.getMetrics().incrementFailedPutRequests(1);
+      return processException(e);
     }
   }
 
@@ -146,9 +134,9 @@ public class RowResource extends Resourc
     // doesn't make sense to use a non specific coordinate as this can only
     // return a single cell
     if (!rowspec.hasColumns() || rowspec.getColumns().length > 1) {
-      return Response.status(Response.Status.BAD_REQUEST)
-        .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
-        .build();
+      servlet.getMetrics().incrementFailedGetRequests(1);
+      return Response.status(Response.Status.BAD_REQUEST).type(MIMETYPE_TEXT)
+          .entity("Bad request: Either 0 or more than 1 columns specified." + CRLF).build();
     }
     try {
       ResultGenerator generator =
@@ -164,17 +152,16 @@ public class RowResource extends Resourc
       response.header("X-Timestamp", value.getTimestamp());
       servlet.getMetrics().incrementSucessfulGetRequests(1);
       return response.build();
-    } catch (IOException e) {
+    } catch (Exception e) {
       servlet.getMetrics().incrementFailedGetRequests(1);
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+      return processException(e);
     }
   }
 
   Response update(final CellSetModel model, final boolean replace) {
     servlet.getMetrics().incrementRequests(1);
     if (servlet.isReadOnly()) {
+      servlet.getMetrics().incrementFailedPutRequests(1);
       return Response.status(Response.Status.FORBIDDEN)
         .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
         .build();
@@ -200,8 +187,9 @@ public class RowResource extends Resourc
           key = rowspec.getRow();
         }
         if (key == null) {
+          servlet.getMetrics().incrementFailedPutRequests(1);
           return Response.status(Response.Status.BAD_REQUEST)
-            .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
+            .type(MIMETYPE_TEXT).entity("Bad request: Row key not specified." + CRLF)
             .build();
         }
         Put put = new Put(key);
@@ -214,8 +202,9 @@ public class RowResource extends Resourc
             col = null;
           }
           if (col == null) {
+            servlet.getMetrics().incrementFailedPutRequests(1);
             return Response.status(Response.Status.BAD_REQUEST)
-              .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
+              .type(MIMETYPE_TEXT).entity("Bad request: Column found to be null." + CRLF)
               .build();
           }
           byte [][] parts = KeyValue.parseColumn(col);
@@ -237,11 +226,9 @@ public class RowResource extends Resourc
       ResponseBuilder response = Response.ok();
       servlet.getMetrics().incrementSucessfulPutRequests(1);
       return response.build();
-    } catch (IOException e) {
+    } catch (Exception e) {
       servlet.getMetrics().incrementFailedPutRequests(1);
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+      return processException(e);
     } finally {
       if (table != null) try {
         table.close();
@@ -256,6 +243,7 @@ public class RowResource extends Resourc
       final boolean replace) {
     servlet.getMetrics().incrementRequests(1);
     if (servlet.isReadOnly()) {
+      servlet.getMetrics().incrementFailedPutRequests(1);
       return Response.status(Response.Status.FORBIDDEN)
         .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
         .build();
@@ -282,9 +270,10 @@ public class RowResource extends Resourc
         timestamp = Long.valueOf(vals.get(0));
       }
       if (column == null) {
+        servlet.getMetrics().incrementFailedPutRequests(1);
         return Response.status(Response.Status.BAD_REQUEST)
-          .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
-          .build();
+            .type(MIMETYPE_TEXT).entity("Bad request: Column found to be null." + CRLF)
+            .build();
       }
       Put put = new Put(row);
       byte parts[][] = KeyValue.parseColumn(column);
@@ -301,15 +290,15 @@ public class RowResource extends Resourc
       }
       servlet.getMetrics().incrementSucessfulPutRequests(1);
       return Response.ok().build();
-    } catch (IOException e) {
+    } catch (Exception e) {
       servlet.getMetrics().incrementFailedPutRequests(1);
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+      return processException(e);
     } finally {
       if (table != null) try {
         table.close();
-      } catch (IOException ioe) { }
+      } catch (IOException ioe) {
+        LOG.debug(ioe);
+      }
     }
   }
 
@@ -364,6 +353,7 @@ public class RowResource extends Resourc
     }
     servlet.getMetrics().incrementRequests(1);
     if (servlet.isReadOnly()) {
+      servlet.getMetrics().incrementFailedDeleteRequests(1);
       return Response.status(Response.Status.FORBIDDEN)
         .type(MIMETYPE_TEXT).entity("Forbidden" + CRLF)
         .build();
@@ -406,15 +396,15 @@ public class RowResource extends Resourc
       if (LOG.isDebugEnabled()) {
         LOG.debug("DELETE " + delete.toString());
       }
-    } catch (IOException e) {
+    } catch (Exception e) {
       servlet.getMetrics().incrementFailedDeleteRequests(1);
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+      return processException(e);
     } finally {
       if (table != null) try {
         table.close();
-      } catch (IOException ioe) { }
+      } catch (IOException ioe) {
+        LOG.debug(ioe);
+      }
     }
     return Response.ok().build();
   }
@@ -429,10 +419,11 @@ public class RowResource extends Resourc
   Response checkAndPut(final CellSetModel model) {
     HTableInterface table = null;
     try {
+      table = servlet.getTable(tableResource.getName());
       if (model.getRows().size() != 1) {
-        return Response.status(Response.Status.BAD_REQUEST)
-          .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
-          .build();
+        servlet.getMetrics().incrementFailedPutRequests(1);
+        return Response.status(Response.Status.BAD_REQUEST).type(MIMETYPE_TEXT)
+            .entity("Bad request: Number of rows specified is not 1." + CRLF).build();
       }
 
       RowModel rowModel = model.getRows().get(0);
@@ -444,56 +435,68 @@ public class RowResource extends Resourc
       List<CellModel> cellModels = rowModel.getCells();
       int cellModelCount = cellModels.size();
       if (key == null || cellModelCount <= 1) {
-        return Response.status(Response.Status.BAD_REQUEST)
-          .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
-          .build();
+        servlet.getMetrics().incrementFailedPutRequests(1);
+        return Response
+            .status(Response.Status.BAD_REQUEST)
+            .type(MIMETYPE_TEXT)
+            .entity(
+              "Bad request: Either row key is null or no data found for columns specified." + CRLF)
+            .build();
       }
 
       Put put = new Put(key);
+      boolean retValue;
       CellModel valueToCheckCell = cellModels.get(cellModelCount - 1);
       byte[] valueToCheckColumn = valueToCheckCell.getColumn();
       byte[][] valueToPutParts = KeyValue.parseColumn(valueToCheckColumn);
-      if (valueToPutParts.length != 2) {
-        return Response.status(Response.Status.BAD_REQUEST)
-          .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
-          .build();
-      }
-      CellModel valueToPutCell = null;
-      for (int i = 0, n = cellModelCount - 1; i < n ; i++) {
-        if(Bytes.equals(cellModels.get(i).getColumn(),
-            valueToCheckCell.getColumn())) {
-          valueToPutCell = cellModels.get(i);
-          break;
+      if (valueToPutParts.length == 2 && valueToPutParts[1].length > 0) {
+        CellModel valueToPutCell = null;
+        for (int i = 0, n = cellModelCount - 1; i < n ; i++) {
+          if(Bytes.equals(cellModels.get(i).getColumn(),
+              valueToCheckCell.getColumn())) {
+            valueToPutCell = cellModels.get(i);
+            break;
+          }
         }
-      }
-      if (null == valueToPutCell) {
+        if (valueToPutCell == null) {
+          servlet.getMetrics().incrementFailedPutRequests(1);
+          return Response.status(Response.Status.BAD_REQUEST).type(MIMETYPE_TEXT)
+              .entity("Bad request: The column to put and check do not match." + CRLF).build();
+        } else {
+          put.addImmutable(valueToPutParts[0], valueToPutParts[1], valueToPutCell.getTimestamp(),
+            valueToPutCell.getValue());
+          retValue = table.checkAndPut(key, valueToPutParts[0], valueToPutParts[1],
+            valueToCheckCell.getValue(), put);
+        }
+      } else {
+        servlet.getMetrics().incrementFailedPutRequests(1);
         return Response.status(Response.Status.BAD_REQUEST)
-          .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
+          .type(MIMETYPE_TEXT).entity("Bad request: Column incorrectly specified." + CRLF)
           .build();
       }
-      put.addImmutable(valueToPutParts[0], valueToPutParts[1], valueToPutCell
-        .getTimestamp(), valueToPutCell.getValue());
 
-      table = servlet.getTable(this.tableResource.getName());
-      boolean retValue = table.checkAndPut(key, valueToPutParts[0],
-        valueToPutParts[1], valueToCheckCell.getValue(), put);
       if (LOG.isDebugEnabled()) {
         LOG.debug("CHECK-AND-PUT " + put.toString() + ", returns " + retValue);
       }
-      table.flushCommits();
-      ResponseBuilder response = Response.ok();
       if (!retValue) {
-        response = Response.status(304);
+        servlet.getMetrics().incrementFailedPutRequests(1);
+        return Response.status(Response.Status.NOT_MODIFIED)
+          .type(MIMETYPE_TEXT).entity("Value not Modified" + CRLF)
+          .build();
       }
+      table.flushCommits();
+      ResponseBuilder response = Response.ok();
+      servlet.getMetrics().incrementSucessfulPutRequests(1);
       return response.build();
-    } catch (IOException e) {
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+    } catch (Exception e) {
+      servlet.getMetrics().incrementFailedPutRequests(1);
+      return processException(e);
     } finally {
       if (table != null) try {
         table.close();
-      } catch (IOException ioe) { }
+      } catch (IOException ioe) { 
+        LOG.debug("Exception received while closing the table", ioe);
+      }
     }
   }
 
@@ -508,7 +511,9 @@ public class RowResource extends Resourc
     HTableInterface table = null;
     Delete delete = null;
     try {
+      table = servlet.getTable(tableResource.getName());
       if (model.getRows().size() != 1) {
+        servlet.getMetrics().incrementFailedDeleteRequests(1);
         return Response.status(Response.Status.BAD_REQUEST)
           .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
           .build();
@@ -519,48 +524,64 @@ public class RowResource extends Resourc
         key = rowspec.getRow();
       }
       if (key == null) {
+        servlet.getMetrics().incrementFailedDeleteRequests(1);
         return Response.status(Response.Status.BAD_REQUEST)
-          .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
+          .type(MIMETYPE_TEXT).entity("Bad request: Row key found to be null." + CRLF)
           .build();
       }
 
       delete = new Delete(key);
+      boolean retValue;
       CellModel valueToDeleteCell = rowModel.getCells().get(0);
       byte[] valueToDeleteColumn = valueToDeleteCell.getColumn();
       if (valueToDeleteColumn == null) {
         try {
           valueToDeleteColumn = rowspec.getColumns()[0];
         } catch (final ArrayIndexOutOfBoundsException e) {
+          servlet.getMetrics().incrementFailedDeleteRequests(1);
           return Response.status(Response.Status.BAD_REQUEST)
-            .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
+            .type(MIMETYPE_TEXT).entity("Bad request: Column not specified for check." + CRLF)
             .build();
         }
       }
       byte[][] parts = KeyValue.parseColumn(valueToDeleteColumn);
-      if (parts.length != 2) {
+      if (parts.length == 2) {
+        if (parts[1].length != 0) {
+          delete.deleteColumns(parts[0], parts[1]);
+          retValue = table.checkAndDelete(key, parts[0], parts[1],
+            valueToDeleteCell.getValue(), delete);
+        } else {
+          // The case of empty qualifier.
+          delete.deleteColumns(parts[0], Bytes.toBytes(StringUtils.EMPTY));
+          retValue = table.checkAndDelete(key, parts[0], Bytes.toBytes(StringUtils.EMPTY),
+            valueToDeleteCell.getValue(), delete);
+        }
+      } else {
+        servlet.getMetrics().incrementFailedDeleteRequests(1);
         return Response.status(Response.Status.BAD_REQUEST)
-          .type(MIMETYPE_TEXT).entity("Bad request" + CRLF)
+          .type(MIMETYPE_TEXT).entity("Bad request: Column incorrectly specified." + CRLF)
           .build();
       }
       delete.deleteColumns(parts[0], parts[1]);
 
-      table = servlet.getTable(tableResource.getName());
-      boolean retValue = table.checkAndDelete(key, parts[0], parts[1],
-        valueToDeleteCell.getValue(), delete);
       if (LOG.isDebugEnabled()) {
         LOG.debug("CHECK-AND-DELETE " + delete.toString() + ", returns "
           + retValue);
       }
-      table.flushCommits();
-      ResponseBuilder response = Response.ok();
+
       if (!retValue) {
-        response = Response.status(304);
+        servlet.getMetrics().incrementFailedDeleteRequests(1);
+        return Response.status(Response.Status.NOT_MODIFIED)
+            .type(MIMETYPE_TEXT).entity(" Delete check failed." + CRLF)
+            .build();
       }
+      table.flushCommits();
+      ResponseBuilder response = Response.ok();
+      servlet.getMetrics().incrementSucessfulDeleteRequests(1);
       return response.build();
-    } catch (IOException e) {
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+    } catch (Exception e) {
+      servlet.getMetrics().incrementFailedDeleteRequests(1);
+      return processException(e);
     } finally {
       if (table != null) try {
         table.close();

Modified: hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/SchemaResource.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/SchemaResource.java?rev=1552369&r1=1552368&r2=1552369&view=diff
==============================================================================
--- hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/SchemaResource.java (original)
+++ hbase/branches/0.98/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/SchemaResource.java Thu Dec 19 17:31:02 2013
@@ -96,17 +96,10 @@ public class SchemaResource extends Reso
       response.cacheControl(cacheControl);
       servlet.getMetrics().incrementSucessfulGetRequests(1);
       return response.build();
-    } catch (TableNotFoundException e) {
+    } catch (Exception e) {
       servlet.getMetrics().incrementFailedGetRequests(1);
-      return Response.status(Response.Status.NOT_FOUND)
-        .type(MIMETYPE_TEXT).entity("Not found" + CRLF)
-        .build();
-    } catch (IOException e) {
-      servlet.getMetrics().incrementFailedGetRequests(1);
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
-    }
+      return processException(e);
+    } 
   }
 
   private Response replace(final byte[] name, final TableSchemaModel model,
@@ -143,10 +136,9 @@ public class SchemaResource extends Reso
           .build();
       }
       return Response.created(uriInfo.getAbsolutePath()).build();
-    } catch (IOException e) {
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+    } catch (Exception e) {
+      servlet.getMetrics().incrementFailedPutRequests(1);
+      return processException(e);
     }
   }
 
@@ -181,10 +173,9 @@ public class SchemaResource extends Reso
       }
       servlet.getMetrics().incrementSucessfulPutRequests(1);
       return Response.ok().build();
-    } catch (IOException e) {
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+    } catch (Exception e) {
+      servlet.getMetrics().incrementFailedPutRequests(1);
+      return processException(e);
     }
   }
 
@@ -198,11 +189,9 @@ public class SchemaResource extends Reso
       } else {
         return update(name, model, uriInfo, admin);
       }
-    } catch (IOException e) {
+    } catch (Exception e) {
       servlet.getMetrics().incrementFailedPutRequests(1);
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+      return processException(e);
     }
   }
 
@@ -255,16 +244,9 @@ public class SchemaResource extends Reso
       admin.deleteTable(tableResource.getName());
       servlet.getMetrics().incrementSucessfulDeleteRequests(1);
       return Response.ok().build();
-    } catch (TableNotFoundException e) {
+    } catch (Exception e) {
       servlet.getMetrics().incrementFailedDeleteRequests(1);
-      return Response.status(Response.Status.NOT_FOUND)
-        .type(MIMETYPE_TEXT).entity("Not found" + CRLF)
-        .build();
-    } catch (IOException e) {
-      servlet.getMetrics().incrementFailedDeleteRequests(1);
-      return Response.status(Response.Status.SERVICE_UNAVAILABLE)
-        .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF)
-        .build();
+      return processException(e);
     }
   }
 }

Added: hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/RowResourceBase.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/RowResourceBase.java?rev=1552369&view=auto
==============================================================================
--- hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/RowResourceBase.java (added)
+++ hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/RowResourceBase.java Thu Dec 19 17:31:02 2013
@@ -0,0 +1,481 @@
+/**
+ * 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.rest;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.ws.rs.core.MediaType;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.rest.client.Client;
+import org.apache.hadoop.hbase.rest.client.Cluster;
+import org.apache.hadoop.hbase.rest.client.Response;
+import org.apache.hadoop.hbase.rest.model.CellModel;
+import org.apache.hadoop.hbase.rest.model.CellSetModel;
+import org.apache.hadoop.hbase.rest.model.RowModel;
+import org.apache.hadoop.hbase.rest.provider.JacksonProvider;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+public class RowResourceBase {
+
+  protected static final String TABLE = "TestRowResource";
+  protected static final String CFA = "a";
+  protected static final String CFB = "b";
+  protected static final String COLUMN_1 = CFA + ":1";
+  protected static final String COLUMN_2 = CFB + ":2";
+  protected static final String COLUMN_3 = CFA + ":";
+  protected static final String ROW_1 = "testrow1";
+  protected static final String VALUE_1 = "testvalue1";
+  protected static final String ROW_2 = "testrow2";
+  protected static final String VALUE_2 = "testvalue2";
+  protected static final String ROW_3 = "testrow3";
+  protected static final String VALUE_3 = "testvalue3";
+  protected static final String ROW_4 = "testrow4";
+  protected static final String VALUE_4 = "testvalue4";
+
+  protected static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
+  protected static final HBaseRESTTestingUtility REST_TEST_UTIL =
+    new HBaseRESTTestingUtility();
+  protected static Client client;
+  protected static JAXBContext context;
+  protected static Marshaller xmlMarshaller;
+  protected static Unmarshaller xmlUnmarshaller;
+  protected static Configuration conf;
+  protected static ObjectMapper jsonMapper;
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+    conf = TEST_UTIL.getConfiguration();
+    TEST_UTIL.startMiniCluster(3);
+    REST_TEST_UTIL.startServletContainer(conf);
+    context = JAXBContext.newInstance(
+        CellModel.class,
+        CellSetModel.class,
+        RowModel.class);
+    xmlMarshaller = context.createMarshaller();
+    xmlUnmarshaller = context.createUnmarshaller();
+    jsonMapper = new JacksonProvider()
+    .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
+    client = new Client(new Cluster().add("localhost",
+      REST_TEST_UTIL.getServletPort()));
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    REST_TEST_UTIL.shutdownServletContainer();
+    TEST_UTIL.shutdownMiniCluster();
+  }
+
+  @Before
+  public void beforeMethod() throws Exception {
+    HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
+    if (admin.tableExists(TABLE)) {
+      TEST_UTIL.deleteTable(Bytes.toBytes(TABLE));
+    }
+    HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(TABLE));
+    htd.addFamily(new HColumnDescriptor(CFA));
+    htd.addFamily(new HColumnDescriptor(CFB));
+    admin.createTable(htd);
+  }
+
+  @After
+  public void afterMethod() throws Exception {
+    HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
+    if (admin.tableExists(TABLE)) {
+      TEST_UTIL.deleteTable(Bytes.toBytes(TABLE));
+    }
+  }
+
+  static Response putValuePB(String table, String row, String column,
+      String value) throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    return putValuePB(path.toString(), table, row, column, value);
+  }
+
+  static Response putValuePB(String url, String table, String row,
+      String column, String value) throws IOException {
+    RowModel rowModel = new RowModel(row);
+    rowModel.addCell(new CellModel(Bytes.toBytes(column),
+      Bytes.toBytes(value)));
+    CellSetModel cellSetModel = new CellSetModel();
+    cellSetModel.addRow(rowModel);
+    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
+      cellSetModel.createProtobufOutput());
+    Thread.yield();
+    return response;
+  }
+
+  protected static void checkValueXML(String url, String table, String row,
+      String column, String value) throws IOException, JAXBException {
+    Response response = getValueXML(url);
+    assertEquals(response.getCode(), 200);
+    assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
+    CellSetModel cellSet = (CellSetModel)
+      xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
+    RowModel rowModel = cellSet.getRows().get(0);
+    CellModel cell = rowModel.getCells().get(0);
+    assertEquals(Bytes.toString(cell.getColumn()), column);
+    assertEquals(Bytes.toString(cell.getValue()), value);
+  }
+
+  protected static void checkValueXML(String table, String row, String column,
+      String value) throws IOException, JAXBException {
+    Response response = getValueXML(table, row, column);
+    assertEquals(response.getCode(), 200);
+    assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
+    CellSetModel cellSet = (CellSetModel)
+      xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
+    RowModel rowModel = cellSet.getRows().get(0);
+    CellModel cell = rowModel.getCells().get(0);
+    assertEquals(Bytes.toString(cell.getColumn()), column);
+    assertEquals(Bytes.toString(cell.getValue()), value);
+  }
+
+  protected static Response getValuePB(String url) throws IOException {
+    Response response = client.get(url, Constants.MIMETYPE_PROTOBUF); 
+    return response;
+  }
+
+  protected static Response putValueXML(String table, String row, String column,
+      String value) throws IOException, JAXBException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    return putValueXML(path.toString(), table, row, column, value);
+  }
+
+  protected static Response putValueXML(String url, String table, String row,
+      String column, String value) throws IOException, JAXBException {
+    RowModel rowModel = new RowModel(row);
+    rowModel.addCell(new CellModel(Bytes.toBytes(column),
+      Bytes.toBytes(value)));
+    CellSetModel cellSetModel = new CellSetModel();
+    cellSetModel.addRow(rowModel);
+    StringWriter writer = new StringWriter();
+    xmlMarshaller.marshal(cellSetModel, writer);
+    Response response = client.put(url, Constants.MIMETYPE_XML,
+      Bytes.toBytes(writer.toString()));
+    Thread.yield();
+    return response;
+  }
+
+  protected static Response getValuePB(String table, String row, String column)
+      throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    return getValuePB(path.toString());
+  }
+
+  protected static void checkValuePB(String table, String row, String column,
+      String value) throws IOException {
+    Response response = getValuePB(table, row, column);
+    assertEquals(response.getCode(), 200);
+    assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
+    CellSetModel cellSet = new CellSetModel();
+    cellSet.getObjectFromMessage(response.getBody());
+    RowModel rowModel = cellSet.getRows().get(0);
+    CellModel cell = rowModel.getCells().get(0);
+    assertEquals(Bytes.toString(cell.getColumn()), column);
+    assertEquals(Bytes.toString(cell.getValue()), value);
+  }
+
+  protected static Response checkAndPutValuePB(String url, String table,
+      String row, String column, String valueToCheck, String valueToPut)
+        throws IOException {
+    RowModel rowModel = new RowModel(row);
+    rowModel.addCell(new CellModel(Bytes.toBytes(column),
+      Bytes.toBytes(valueToPut)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(column),
+      Bytes.toBytes(valueToCheck)));
+    CellSetModel cellSetModel = new CellSetModel();
+    cellSetModel.addRow(rowModel);
+    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
+      cellSetModel.createProtobufOutput());
+    Thread.yield();
+    return response;
+  }
+
+  protected static Response checkAndPutValuePB(String table, String row,
+      String column, String valueToCheck, String valueToPut) throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append("?check=put");
+    return checkAndPutValuePB(path.toString(), table, row, column,
+      valueToCheck, valueToPut);
+  }
+
+  protected static Response checkAndPutValueXML(String url, String table,
+      String row, String column, String valueToCheck, String valueToPut)
+        throws IOException, JAXBException {
+    RowModel rowModel = new RowModel(row);
+    rowModel.addCell(new CellModel(Bytes.toBytes(column),
+      Bytes.toBytes(valueToPut)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(column),
+      Bytes.toBytes(valueToCheck)));
+    CellSetModel cellSetModel = new CellSetModel();
+    cellSetModel.addRow(rowModel);
+    StringWriter writer = new StringWriter();
+    xmlMarshaller.marshal(cellSetModel, writer);
+    Response response = client.put(url, Constants.MIMETYPE_XML,
+      Bytes.toBytes(writer.toString()));
+    Thread.yield();
+    return response;
+  }
+
+  protected static Response checkAndPutValueXML(String table, String row,
+      String column, String valueToCheck, String valueToPut)
+        throws IOException, JAXBException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append("?check=put");
+    return checkAndPutValueXML(path.toString(), table, row, column,
+      valueToCheck, valueToPut);
+  }
+
+  protected static Response checkAndDeleteXML(String url, String table,
+      String row, String column, String valueToCheck)
+        throws IOException, JAXBException {
+    RowModel rowModel = new RowModel(row);
+    rowModel.addCell(new CellModel(Bytes.toBytes(column),
+      Bytes.toBytes(valueToCheck)));
+    CellSetModel cellSetModel = new CellSetModel();
+    cellSetModel.addRow(rowModel);
+    StringWriter writer = new StringWriter();
+    xmlMarshaller.marshal(cellSetModel, writer);
+    Response response = client.put(url, Constants.MIMETYPE_XML,
+      Bytes.toBytes(writer.toString()));
+    Thread.yield();
+    return response;
+  }
+
+  protected static Response checkAndDeleteXML(String table, String row,
+      String column, String valueToCheck) throws IOException, JAXBException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append("?check=delete");
+    return checkAndDeleteXML(path.toString(), table, row, column, valueToCheck);
+  }
+
+  protected static Response checkAndDeleteJson(String table, String row,
+      String column, String valueToCheck) throws IOException, JAXBException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append("?check=delete");
+    return checkAndDeleteJson(path.toString(), table, row, column, valueToCheck);
+  }
+
+  protected static Response checkAndDeleteJson(String url, String table,
+      String row, String column, String valueToCheck)
+        throws IOException, JAXBException {
+    RowModel rowModel = new RowModel(row);
+    rowModel.addCell(new CellModel(Bytes.toBytes(column),
+      Bytes.toBytes(valueToCheck)));
+    CellSetModel cellSetModel = new CellSetModel();
+    cellSetModel.addRow(rowModel);
+    String jsonString = jsonMapper.writeValueAsString(cellSetModel);
+    Response response = client.put(url, Constants.MIMETYPE_JSON,
+      Bytes.toBytes(jsonString));
+    Thread.yield();
+    return response;
+  }
+
+  protected static Response checkAndDeletePB(String table, String row,
+      String column, String value) throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append("?check=delete");
+    return checkAndDeleteValuePB(path.toString(), table, row, column, value);
+  }
+
+  protected static Response checkAndDeleteValuePB(String url, String table,
+      String row, String column, String valueToCheck)
+      throws IOException {
+    RowModel rowModel = new RowModel(row);
+    rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes
+        .toBytes(valueToCheck)));
+    CellSetModel cellSetModel = new CellSetModel();
+    cellSetModel.addRow(rowModel);
+    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
+        cellSetModel.createProtobufOutput());
+    Thread.yield();
+    return response;
+  }
+
+  protected static Response getValueXML(String table, String startRow,
+      String endRow, String column) throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(startRow);
+    path.append(",");
+    path.append(endRow);
+    path.append('/');
+    path.append(column);
+    return getValueXML(path.toString());
+  }
+
+  protected static Response getValueXML(String url) throws IOException {
+    Response response = client.get(url, Constants.MIMETYPE_XML);
+    return response;
+  }
+
+  protected static Response getValueJson(String url) throws IOException {
+    Response response = client.get(url, Constants.MIMETYPE_JSON);
+    return response;
+  }
+
+  protected static Response deleteValue(String table, String row, String column)
+      throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    Response response = client.delete(path.toString());
+    Thread.yield();
+    return response;
+  }
+
+  protected static Response getValueXML(String table, String row, String column)
+      throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    return getValueXML(path.toString());
+  }
+
+  protected static Response deleteRow(String table, String row)
+      throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    Response response = client.delete(path.toString());
+    Thread.yield();
+    return response;
+  }
+
+  protected static Response getValueJson(String table, String row,
+      String column) throws IOException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    return getValueJson(path.toString());
+  }
+
+  protected static void checkValueJSON(String table, String row, String column,
+      String value) throws IOException, JAXBException {
+    Response response = getValueJson(table, row, column);
+    assertEquals(response.getCode(), 200);
+    assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
+    ObjectMapper mapper = new JacksonProvider()
+    .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
+    CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class);
+    RowModel rowModel = cellSet.getRows().get(0);
+    CellModel cell = rowModel.getCells().get(0);
+    assertEquals(Bytes.toString(cell.getColumn()), column);
+    assertEquals(Bytes.toString(cell.getValue()), value);
+  }
+
+  protected static Response putValueJson(String table, String row, String column,
+      String value) throws IOException, JAXBException {
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(table);
+    path.append('/');
+    path.append(row);
+    path.append('/');
+    path.append(column);
+    return putValueJson(path.toString(), table, row, column, value);
+  }
+
+  protected static Response putValueJson(String url, String table, String row, String column,
+      String value) throws IOException, JAXBException {
+    RowModel rowModel = new RowModel(row);
+    rowModel.addCell(new CellModel(Bytes.toBytes(column),
+      Bytes.toBytes(value)));
+    CellSetModel cellSetModel = new CellSetModel();
+    cellSetModel.addRow(rowModel);
+    String jsonString = jsonMapper.writeValueAsString(cellSetModel);
+    Response response = client.put(url, Constants.MIMETYPE_JSON,
+      Bytes.toBytes(jsonString));
+    Thread.yield();
+    return response;
+  }
+
+}

Added: hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestDeleteRow.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestDeleteRow.java?rev=1552369&view=auto
==============================================================================
--- hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestDeleteRow.java (added)
+++ hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestDeleteRow.java Thu Dec 19 17:31:02 2013
@@ -0,0 +1,99 @@
+/*
+ * 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.rest;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.hadoop.hbase.MediumTests;
+import org.apache.hadoop.hbase.rest.client.Response;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+
+@Category(MediumTests.class)
+public class TestDeleteRow extends RowResourceBase {
+
+  @Test
+  public void testDeleteNonExistentColumn() throws Exception {
+    Response response = putValueJson(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+
+    response = checkAndDeleteJson(TABLE, ROW_1, COLUMN_1, VALUE_2);
+    assertEquals(304, response.getCode());
+    assertEquals(200, getValueJson(TABLE, ROW_1, COLUMN_1).getCode());
+
+    response = checkAndDeleteJson(TABLE, ROW_2, COLUMN_1, VALUE_2);
+    assertEquals(304, response.getCode());
+    assertEquals(200, getValueJson(TABLE, ROW_1, COLUMN_1).getCode());
+
+    response = checkAndDeleteJson(TABLE, ROW_1, "dummy", VALUE_1);
+    assertEquals(400, response.getCode());
+    assertEquals(200, getValueJson(TABLE, ROW_1, COLUMN_1).getCode());
+
+    response = checkAndDeleteJson(TABLE, ROW_1, "dummy:test", VALUE_1);
+    assertEquals(404, response.getCode());
+    assertEquals(200, getValueJson(TABLE, ROW_1, COLUMN_1).getCode());
+
+    response = checkAndDeleteJson(TABLE, ROW_1, "a:test", VALUE_1);
+    assertEquals(304, response.getCode());
+    assertEquals(200, getValueJson(TABLE, ROW_1, COLUMN_1).getCode());
+  }
+
+  @Test
+  public void testDeleteXML() throws IOException, JAXBException {
+    Response response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    response = putValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
+    assertEquals(response.getCode(), 200);
+    checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
+
+    response = deleteValue(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 200);
+    response = getValueXML(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 404);
+    checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
+
+    response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    response = checkAndDeletePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    response = getValueXML(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 404);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);
+    response = getValueXML(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 404);
+    response = getValueXML(TABLE, ROW_1, COLUMN_2);
+    assertEquals(response.getCode(), 404);
+
+    //Delete a row in non existent table
+    response = deleteValue("dummy", ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 404);
+
+    //Delete non existent column
+    response = deleteValue(TABLE, ROW_1, "dummy");
+    assertEquals(response.getCode(), 404);
+  }
+
+}

Added: hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestGetAndPutResource.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestGetAndPutResource.java?rev=1552369&view=auto
==============================================================================
--- hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestGetAndPutResource.java (added)
+++ hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestGetAndPutResource.java Thu Dec 19 17:31:02 2013
@@ -0,0 +1,486 @@
+/**
+ * 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.rest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URLEncoder;
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.hadoop.hbase.CompatibilityFactory;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.MediumTests;
+import org.apache.hadoop.hbase.rest.client.Response;
+import org.apache.hadoop.hbase.rest.model.CellModel;
+import org.apache.hadoop.hbase.rest.model.CellSetModel;
+import org.apache.hadoop.hbase.rest.model.RowModel;
+import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.test.MetricsAssertHelper;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category(MediumTests.class)
+public class TestGetAndPutResource extends RowResourceBase {
+
+  private static final MetricsAssertHelper METRICS_ASSERT =
+      CompatibilityFactory.getInstance(MetricsAssertHelper.class);
+
+  @Test
+  public void testForbidden() throws IOException, JAXBException {
+    conf.set("hbase.rest.readonly", "true");
+
+    Response response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 403);
+    response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 403);
+    response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_2);
+    assertEquals(response.getCode(), 403);
+    response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_2);
+    assertEquals(response.getCode(), 403);
+    response = deleteValue(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 403);
+    response = checkAndDeletePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 403);
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 403);
+
+    conf.set("hbase.rest.readonly", "false");
+
+    response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_2);
+    assertEquals(response.getCode(), 200);
+    response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2, VALUE_3);
+    assertEquals(response.getCode(), 200);
+    response = deleteValue(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 200);
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);
+  }
+
+  @Test
+  public void testSingleCellGetPutXML() throws IOException, JAXBException {
+    Response response = getValueXML(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 404);
+
+    response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
+    assertEquals(response.getCode(), 200);
+    checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
+    response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2, VALUE_3);
+    assertEquals(response.getCode(), 200);
+    checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3);
+    response = checkAndDeleteXML(TABLE, ROW_1, COLUMN_1, VALUE_3);
+    assertEquals(response.getCode(), 200);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);
+  }
+
+  @Test
+  public void testSingleCellGetPutPB() throws IOException, JAXBException {
+    Response response = getValuePB(TABLE, ROW_1, COLUMN_1);
+    assertEquals(response.getCode(), 404);
+    
+    response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    assertEquals(response.getCode(), 200);
+    checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
+    assertEquals(response.getCode(), 200);
+    checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2);
+
+    response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2, VALUE_3);
+    assertEquals(response.getCode(), 200);
+    checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_3);
+    response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3, VALUE_4);
+    assertEquals(response.getCode(), 200);
+    checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_4);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);
+  }
+
+  @Test
+  public void testSingleCellGetPutBinary() throws IOException {
+    final String path = "/" + TABLE + "/" + ROW_3 + "/" + COLUMN_1;
+    final byte[] body = Bytes.toBytes(VALUE_3);
+    Response response = client.put(path, Constants.MIMETYPE_BINARY, body);
+    assertEquals(response.getCode(), 200);
+    Thread.yield();
+
+    response = client.get(path, Constants.MIMETYPE_BINARY);
+    assertEquals(response.getCode(), 200);
+    assertEquals(Constants.MIMETYPE_BINARY, response.getHeader("content-type"));
+    assertTrue(Bytes.equals(response.getBody(), body));
+    boolean foundTimestampHeader = false;
+    for (Header header: response.getHeaders()) {
+      if (header.getName().equals("X-Timestamp")) {
+        foundTimestampHeader = true;
+        break;
+      }
+    }
+    assertTrue(foundTimestampHeader);
+
+    response = deleteRow(TABLE, ROW_3);
+    assertEquals(response.getCode(), 200);
+  }
+
+  @Test
+  public void testSingleCellGetJSON() throws IOException, JAXBException {
+    final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1;
+    Response response = client.put(path, Constants.MIMETYPE_BINARY,
+      Bytes.toBytes(VALUE_4));
+    assertEquals(response.getCode(), 200);
+    Thread.yield();
+    response = client.get(path, Constants.MIMETYPE_JSON);
+    assertEquals(response.getCode(), 200);
+    assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
+    response = deleteRow(TABLE, ROW_4);
+    assertEquals(response.getCode(), 200);
+  }
+
+  @Test
+  public void testLatestCellGetJSON() throws IOException, JAXBException {
+    final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1;
+    CellSetModel cellSetModel = new CellSetModel();
+    RowModel rowModel = new RowModel(ROW_4);
+    CellModel cellOne = new CellModel(Bytes.toBytes(COLUMN_1), 1L,
+      Bytes.toBytes(VALUE_1));
+    CellModel cellTwo = new CellModel(Bytes.toBytes(COLUMN_1), 2L,
+      Bytes.toBytes(VALUE_2));
+    rowModel.addCell(cellOne);
+    rowModel.addCell(cellTwo);
+    cellSetModel.addRow(rowModel);
+    String jsonString = jsonMapper.writeValueAsString(cellSetModel);
+    Response response = client.put(path, Constants.MIMETYPE_JSON,
+      Bytes.toBytes(jsonString));
+    assertEquals(response.getCode(), 200);
+    Thread.yield();
+    response = client.get(path, Constants.MIMETYPE_JSON);
+    assertEquals(response.getCode(), 200);
+    assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
+    CellSetModel cellSet = jsonMapper.readValue(response.getBody(), CellSetModel.class);
+    assertTrue(cellSet.getRows().size() == 1);
+    assertTrue(cellSet.getRows().get(0).getCells().size() == 1);
+    CellModel cell = cellSet.getRows().get(0).getCells().get(0);
+    assertEquals(VALUE_2 , Bytes.toString(cell.getValue()));
+    assertEquals(2L , cell.getTimestamp());
+    response = deleteRow(TABLE, ROW_4);
+    assertEquals(response.getCode(), 200);
+  }
+
+  @Test
+  public void testURLEncodedKey() throws IOException, JAXBException {
+    String urlKey = "http://example.com/foo";
+    StringBuilder path = new StringBuilder();
+    path.append('/');
+    path.append(TABLE);
+    path.append('/');
+    path.append(URLEncoder.encode(urlKey, HConstants.UTF8_ENCODING));
+    path.append('/');
+    path.append(COLUMN_1);
+    Response response;
+    response = putValueXML(path.toString(), TABLE, urlKey, COLUMN_1,
+      VALUE_1);
+    assertEquals(response.getCode(), 200);
+    checkValueXML(path.toString(), TABLE, urlKey, COLUMN_1, VALUE_1);
+  }
+
+  @Test
+  public void testNoSuchCF() throws IOException, JAXBException {
+    final String goodPath = "/" + TABLE + "/" + ROW_1 + "/" + CFA+":";
+    final String badPath = "/" + TABLE + "/" + ROW_1 + "/" + "BAD";
+    Response response = client.post(goodPath, Constants.MIMETYPE_BINARY,
+      Bytes.toBytes(VALUE_1));
+    assertEquals(response.getCode(), 200);
+    assertEquals(client.get(goodPath, Constants.MIMETYPE_BINARY).getCode(),
+      200);
+    assertEquals(client.get(badPath, Constants.MIMETYPE_BINARY).getCode(),
+      404);
+    assertEquals(client.get(goodPath, Constants.MIMETYPE_BINARY).getCode(),
+      200);
+  }
+
+  @Test
+  public void testMultiCellGetPutXML() throws IOException, JAXBException {
+    String path = "/" + TABLE + "/fakerow";  // deliberate nonexistent row
+
+    CellSetModel cellSetModel = new CellSetModel();
+    RowModel rowModel = new RowModel(ROW_1);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
+      Bytes.toBytes(VALUE_1)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
+      Bytes.toBytes(VALUE_2)));
+    cellSetModel.addRow(rowModel);
+    rowModel = new RowModel(ROW_2);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
+      Bytes.toBytes(VALUE_3)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
+      Bytes.toBytes(VALUE_4)));
+    cellSetModel.addRow(rowModel);
+    StringWriter writer = new StringWriter();
+    xmlMarshaller.marshal(cellSetModel, writer);
+    Response response = client.put(path, Constants.MIMETYPE_XML,
+      Bytes.toBytes(writer.toString()));
+    Thread.yield();
+
+    // make sure the fake row was not actually created
+    response = client.get(path, Constants.MIMETYPE_XML);
+    assertEquals(response.getCode(), 404);
+
+    // check that all of the values were created
+    checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
+    checkValueXML(TABLE, ROW_2, COLUMN_1, VALUE_3);
+    checkValueXML(TABLE, ROW_2, COLUMN_2, VALUE_4);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);
+    response = deleteRow(TABLE, ROW_2);
+    assertEquals(response.getCode(), 200);
+  }
+
+  @Test
+  public void testMultiCellGetPutPB() throws IOException {
+    String path = "/" + TABLE + "/fakerow";  // deliberate nonexistent row
+
+    CellSetModel cellSetModel = new CellSetModel();
+    RowModel rowModel = new RowModel(ROW_1);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
+      Bytes.toBytes(VALUE_1)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
+      Bytes.toBytes(VALUE_2)));
+    cellSetModel.addRow(rowModel);
+    rowModel = new RowModel(ROW_2);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
+      Bytes.toBytes(VALUE_3)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
+      Bytes.toBytes(VALUE_4)));
+    cellSetModel.addRow(rowModel);
+    Response response = client.put(path, Constants.MIMETYPE_PROTOBUF,
+      cellSetModel.createProtobufOutput());
+    Thread.yield();
+
+    // make sure the fake row was not actually created
+    response = client.get(path, Constants.MIMETYPE_PROTOBUF);
+    assertEquals(response.getCode(), 404);
+
+    // check that all of the values were created
+    checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
+    checkValuePB(TABLE, ROW_2, COLUMN_1, VALUE_3);
+    checkValuePB(TABLE, ROW_2, COLUMN_2, VALUE_4);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);
+    response = deleteRow(TABLE, ROW_2);
+    assertEquals(response.getCode(), 200);
+  }
+
+  @Test
+  public void testStartEndRowGetPutXML() throws IOException, JAXBException {
+    String[] rows = { ROW_1, ROW_2, ROW_3 };
+    String[] values = { VALUE_1, VALUE_2, VALUE_3 };
+    Response response = null;
+    for (int i = 0; i < rows.length; i++) {
+      response = putValueXML(TABLE, rows[i], COLUMN_1, values[i]);
+      assertEquals(200, response.getCode());
+      checkValueXML(TABLE, rows[i], COLUMN_1, values[i]);
+    }
+    response = getValueXML(TABLE, rows[0], rows[2], COLUMN_1);
+    assertEquals(200, response.getCode());
+    CellSetModel cellSet = (CellSetModel)
+      xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
+    assertEquals(2, cellSet.getRows().size());
+    for (int i = 0; i < cellSet.getRows().size()-1; i++) {
+      RowModel rowModel = cellSet.getRows().get(i);
+      for (CellModel cell: rowModel.getCells()) {
+        assertEquals(COLUMN_1, Bytes.toString(cell.getColumn()));
+        assertEquals(values[i], Bytes.toString(cell.getValue()));
+      }
+    }
+    for (String row : rows) {
+      response = deleteRow(TABLE, row);
+      assertEquals(200, response.getCode());
+    }
+  }
+
+  @Test
+  public void testInvalidCheckParam() throws IOException, JAXBException {
+    CellSetModel cellSetModel = new CellSetModel();
+    RowModel rowModel = new RowModel(ROW_1);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
+      Bytes.toBytes(VALUE_1)));
+    cellSetModel.addRow(rowModel);
+    StringWriter writer = new StringWriter();
+    xmlMarshaller.marshal(cellSetModel, writer);
+
+    final String path = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1 + "?check=blah";
+
+    Response response = client.put(path, Constants.MIMETYPE_XML,
+      Bytes.toBytes(writer.toString()));
+    assertEquals(response.getCode(), 400);
+  }
+
+  @Test
+  public void testInvalidColumnPut() throws IOException, JAXBException {
+    String dummyColumn = "doesnot:exist";
+    CellSetModel cellSetModel = new CellSetModel();
+    RowModel rowModel = new RowModel(ROW_1);
+    rowModel.addCell(new CellModel(Bytes.toBytes(dummyColumn),
+      Bytes.toBytes(VALUE_1)));
+    cellSetModel.addRow(rowModel);
+    StringWriter writer = new StringWriter();
+    xmlMarshaller.marshal(cellSetModel, writer);
+
+    final String path = "/" + TABLE + "/" + ROW_1 + "/" + dummyColumn;
+
+    Response response = client.put(path, Constants.MIMETYPE_XML,
+      Bytes.toBytes(writer.toString()));
+    assertEquals(response.getCode(), 404);
+  }
+
+  @Test
+  public void testMultiCellGetJson() throws IOException, JAXBException {
+    String path = "/" + TABLE + "/fakerow";  // deliberate nonexistent row
+
+    CellSetModel cellSetModel = new CellSetModel();
+    RowModel rowModel = new RowModel(ROW_1);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
+      Bytes.toBytes(VALUE_1)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
+      Bytes.toBytes(VALUE_2)));
+    cellSetModel.addRow(rowModel);
+    rowModel = new RowModel(ROW_2);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
+      Bytes.toBytes(VALUE_3)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
+      Bytes.toBytes(VALUE_4)));
+    cellSetModel.addRow(rowModel);
+    String jsonString = jsonMapper.writeValueAsString(cellSetModel);
+
+    Response response = client.put(path, Constants.MIMETYPE_JSON,
+      Bytes.toBytes(jsonString));
+    Thread.yield();
+
+    // make sure the fake row was not actually created
+    response = client.get(path, Constants.MIMETYPE_JSON);
+    assertEquals(response.getCode(), 404);
+
+    // check that all of the values were created
+    checkValueJSON(TABLE, ROW_1, COLUMN_1, VALUE_1);
+    checkValueJSON(TABLE, ROW_1, COLUMN_2, VALUE_2);
+    checkValueJSON(TABLE, ROW_2, COLUMN_1, VALUE_3);
+    checkValueJSON(TABLE, ROW_2, COLUMN_2, VALUE_4);
+
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);
+    response = deleteRow(TABLE, ROW_2);
+    assertEquals(response.getCode(), 200);
+  }
+  
+  @Test
+  public void testMetrics() throws IOException, JAXBException {
+    final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1;
+    Response response = client.put(path, Constants.MIMETYPE_BINARY,
+        Bytes.toBytes(VALUE_4));
+    assertEquals(response.getCode(), 200);
+    Thread.yield();
+    response = client.get(path, Constants.MIMETYPE_JSON);
+    assertEquals(response.getCode(), 200);
+    assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
+    response = deleteRow(TABLE, ROW_4);
+    assertEquals(response.getCode(), 200);
+
+    UserGroupInformation ugi = User.getCurrent().getUGI();
+    METRICS_ASSERT.assertCounterGt("requests", 2l,
+      RESTServlet.getInstance(conf, ugi).getMetrics().getSource());
+
+    METRICS_ASSERT.assertCounterGt("successfulGet", 0l,
+      RESTServlet.getInstance(conf, ugi).getMetrics().getSource());
+
+    METRICS_ASSERT.assertCounterGt("successfulPut", 0l,
+      RESTServlet.getInstance(conf, ugi).getMetrics().getSource());
+
+    METRICS_ASSERT.assertCounterGt("successfulDelete", 0l,
+      RESTServlet.getInstance(conf, ugi).getMetrics().getSource());
+  }
+  
+  @Test
+  public void testMultiColumnGetXML() throws Exception {
+    String path = "/" + TABLE + "/fakerow";
+    CellSetModel cellSetModel = new CellSetModel();
+    RowModel rowModel = new RowModel(ROW_1);
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2)));
+    rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_3), Bytes.toBytes(VALUE_2)));
+    cellSetModel.addRow(rowModel);
+    StringWriter writer = new StringWriter();
+    xmlMarshaller.marshal(cellSetModel, writer);
+
+    Response response = client.put(path, Constants.MIMETYPE_XML, Bytes.toBytes(writer.toString()));
+    Thread.yield();
+
+    // make sure the fake row was not actually created
+    response = client.get(path, Constants.MIMETYPE_XML);
+    assertEquals(response.getCode(), 404);
+
+    // Try getting all the column values at once.
+    path = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1 + "," + COLUMN_2 + "," + COLUMN_3;
+    response = client.get(path, Constants.MIMETYPE_XML);
+    assertEquals(200, response.getCode());
+    CellSetModel cellSet = (CellSetModel) xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response
+        .getBody()));
+    assertTrue(cellSet.getRows().size() == 1);
+    assertTrue(cellSet.getRows().get(0).getCells().size() == 3);
+    List<CellModel> cells = cellSet.getRows().get(0).getCells();
+
+    assertTrue(containsCellModel(cells, COLUMN_1, VALUE_1));
+    assertTrue(containsCellModel(cells, COLUMN_2, VALUE_2));
+    assertTrue(containsCellModel(cells, COLUMN_3, VALUE_2));
+    response = deleteRow(TABLE, ROW_1);
+    assertEquals(response.getCode(), 200);
+  }
+
+  private boolean containsCellModel(List<CellModel> cells, String column, String value) {
+    boolean contains = false;
+    for (CellModel cell : cells) {
+      if (Bytes.toString(cell.getColumn()).equals(column)
+          && Bytes.toString(cell.getValue()).equals(value)) {
+        contains = true;
+        return contains;
+      }
+    }
+    return contains;
+  }
+}
+

Modified: hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestMultiRowResource.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestMultiRowResource.java?rev=1552369&r1=1552368&r2=1552369&view=diff
==============================================================================
--- hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestMultiRowResource.java (original)
+++ hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestMultiRowResource.java Thu Dec 19 17:31:02 2013
@@ -28,12 +28,15 @@ import org.apache.hadoop.hbase.rest.clie
 import org.apache.hadoop.hbase.rest.model.CellModel;
 import org.apache.hadoop.hbase.rest.model.CellSetModel;
 import org.apache.hadoop.hbase.rest.model.RowModel;
+import org.apache.hadoop.hbase.rest.provider.JacksonProvider;
 import org.apache.hadoop.hbase.util.Bytes;
+import org.codehaus.jackson.map.ObjectMapper;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
+import javax.ws.rs.core.MediaType;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
@@ -151,7 +154,7 @@ public class TestMultiRowResource {
   }
 
   @Test
-  public void testMultiCellGetJSONNotFound() throws IOException {
+  public void testMultiCellGetJSONNotFound() throws IOException, JAXBException {
     String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1;
 
     StringBuilder path = new StringBuilder();
@@ -163,11 +166,15 @@ public class TestMultiRowResource {
     path.append(ROW_2);
 
     client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1));
-
     Response response = client.get(path.toString(), Constants.MIMETYPE_JSON);
-
-    assertEquals(response.getCode(), 404);
-
+    assertEquals(response.getCode(), 200);
+    ObjectMapper mapper = new JacksonProvider().locateMapper(CellSetModel.class,
+      MediaType.APPLICATION_JSON_TYPE);
+    CellSetModel cellSet = (CellSetModel) mapper.readValue(response.getBody(), CellSetModel.class);
+    assertEquals(1, cellSet.getRows().size());
+    assertEquals(ROW_1, Bytes.toString(cellSet.getRows().get(0).getKey()));
+    assertEquals(VALUE_1, Bytes.toString(cellSet.getRows().get(0).getCells().get(0).getValue()));
+    client.delete(row_5_url);
   }
 
 }

Modified: hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java?rev=1552369&r1=1552368&r2=1552369&view=diff
==============================================================================
--- hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java (original)
+++ hbase/branches/0.98/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java Thu Dec 19 17:31:02 2013
@@ -281,7 +281,7 @@ public class TestRemoteTable {
     gets.add(new Get(ROW_2));
     results = remoteTable.get(gets);
     assertNotNull(results);
-    assertEquals(0, results.length);
+    assertEquals(2, results.length);
   }
 
   @Test



Mime
View raw message