001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.rest; 019 020import static org.junit.Assert.assertEquals; 021 022import com.fasterxml.jackson.databind.ObjectMapper; 023import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; 024import java.io.IOException; 025import java.util.Collection; 026import javax.ws.rs.core.MediaType; 027import javax.xml.bind.JAXBContext; 028import javax.xml.bind.JAXBException; 029import javax.xml.bind.Marshaller; 030import javax.xml.bind.Unmarshaller; 031import org.apache.hadoop.conf.Configuration; 032import org.apache.hadoop.hbase.HBaseClassTestRule; 033import org.apache.hadoop.hbase.HBaseCommonTestingUtility; 034import org.apache.hadoop.hbase.HBaseTestingUtility; 035import org.apache.hadoop.hbase.HColumnDescriptor; 036import org.apache.hadoop.hbase.HTableDescriptor; 037import org.apache.hadoop.hbase.TableName; 038import org.apache.hadoop.hbase.client.Admin; 039import org.apache.hadoop.hbase.rest.client.Client; 040import org.apache.hadoop.hbase.rest.client.Cluster; 041import org.apache.hadoop.hbase.rest.client.Response; 042import org.apache.hadoop.hbase.rest.model.CellModel; 043import org.apache.hadoop.hbase.rest.model.CellSetModel; 044import org.apache.hadoop.hbase.rest.model.RowModel; 045import org.apache.hadoop.hbase.testclassification.MediumTests; 046import org.apache.hadoop.hbase.testclassification.RestTests; 047import org.apache.hadoop.hbase.util.Bytes; 048import org.apache.http.Header; 049import org.apache.http.message.BasicHeader; 050import org.junit.AfterClass; 051import org.junit.BeforeClass; 052import org.junit.ClassRule; 053import org.junit.Test; 054import org.junit.experimental.categories.Category; 055import org.junit.runner.RunWith; 056import org.junit.runners.Parameterized; 057 058@Category({RestTests.class, MediumTests.class}) 059@RunWith(Parameterized.class) 060public class TestMultiRowResource { 061 062 @ClassRule 063 public static final HBaseClassTestRule CLASS_RULE = 064 HBaseClassTestRule.forClass(TestMultiRowResource.class); 065 066 private static final TableName TABLE = TableName.valueOf("TestRowResource"); 067 private static final String CFA = "a"; 068 private static final String CFB = "b"; 069 private static final String COLUMN_1 = CFA + ":1"; 070 private static final String COLUMN_2 = CFB + ":2"; 071 private static final String ROW_1 = "testrow5"; 072 private static final String VALUE_1 = "testvalue5"; 073 private static final String ROW_2 = "testrow6"; 074 private static final String VALUE_2 = "testvalue6"; 075 076 077 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 078 private static final HBaseRESTTestingUtility REST_TEST_UTIL = new HBaseRESTTestingUtility(); 079 080 private static Client client; 081 private static JAXBContext context; 082 private static Marshaller marshaller; 083 private static Unmarshaller unmarshaller; 084 private static Configuration conf; 085 086 private static Header extraHdr = null; 087 private static boolean csrfEnabled = true; 088 089 @Parameterized.Parameters 090 public static Collection<Object[]> data() { 091 return HBaseCommonTestingUtility.BOOLEAN_PARAMETERIZED; 092 } 093 094 public TestMultiRowResource(Boolean csrf) { 095 csrfEnabled = csrf; 096 } 097 098 099 @BeforeClass 100 public static void setUpBeforeClass() throws Exception { 101 conf = TEST_UTIL.getConfiguration(); 102 conf.setBoolean(RESTServer.REST_CSRF_ENABLED_KEY, csrfEnabled); 103 extraHdr = new BasicHeader(RESTServer.REST_CSRF_CUSTOM_HEADER_DEFAULT, ""); 104 TEST_UTIL.startMiniCluster(); 105 REST_TEST_UTIL.startServletContainer(conf); 106 context = JAXBContext.newInstance( 107 CellModel.class, 108 CellSetModel.class, 109 RowModel.class); 110 marshaller = context.createMarshaller(); 111 unmarshaller = context.createUnmarshaller(); 112 client = new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort())); 113 Admin admin = TEST_UTIL.getAdmin(); 114 if (admin.tableExists(TABLE)) { 115 return; 116 } 117 HTableDescriptor htd = new HTableDescriptor(TABLE); 118 htd.addFamily(new HColumnDescriptor(CFA)); 119 htd.addFamily(new HColumnDescriptor(CFB)); 120 admin.createTable(htd); 121 } 122 123 @AfterClass 124 public static void tearDownAfterClass() throws Exception { 125 REST_TEST_UTIL.shutdownServletContainer(); 126 TEST_UTIL.shutdownMiniCluster(); 127 } 128 129 130 @Test 131 public void testMultiCellGetJSON() throws IOException, JAXBException { 132 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 133 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 134 135 136 StringBuilder path = new StringBuilder(); 137 path.append("/"); 138 path.append(TABLE); 139 path.append("/multiget/?row="); 140 path.append(ROW_1); 141 path.append("&row="); 142 path.append(ROW_2); 143 144 if (csrfEnabled) { 145 Response response = client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1)); 146 assertEquals(400, response.getCode()); 147 } 148 149 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 150 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 151 152 153 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 154 assertEquals(200, response.getCode()); 155 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); 156 157 client.delete(row_5_url, extraHdr); 158 client.delete(row_6_url, extraHdr); 159 160 } 161 162 @Test 163 public void testMultiCellGetXML() throws IOException, JAXBException { 164 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 165 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 166 167 168 StringBuilder path = new StringBuilder(); 169 path.append("/"); 170 path.append(TABLE); 171 path.append("/multiget/?row="); 172 path.append(ROW_1); 173 path.append("&row="); 174 path.append(ROW_2); 175 176 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 177 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 178 179 180 Response response = client.get(path.toString(), Constants.MIMETYPE_XML); 181 assertEquals(200, response.getCode()); 182 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type")); 183 184 client.delete(row_5_url, extraHdr); 185 client.delete(row_6_url, extraHdr); 186 187 } 188 189 @Test 190 public void testMultiCellGetWithColsJSON() throws IOException, JAXBException { 191 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 192 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 193 194 StringBuilder path = new StringBuilder(); 195 path.append("/"); 196 path.append(TABLE); 197 path.append("/multiget"); 198 path.append("/" + COLUMN_1 + "," + CFB); 199 path.append("?row="); 200 path.append(ROW_1); 201 path.append("&row="); 202 path.append(ROW_2); 203 204 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 205 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 206 207 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 208 assertEquals(200, response.getCode()); 209 ObjectMapper mapper = 210 new JacksonJaxbJsonProvider().locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE); 211 CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class); 212 assertEquals(2, cellSet.getRows().size()); 213 assertEquals(ROW_1, Bytes.toString(cellSet.getRows().get(0).getKey())); 214 assertEquals(VALUE_1, Bytes.toString(cellSet.getRows().get(0).getCells().get(0).getValue())); 215 assertEquals(ROW_2, Bytes.toString(cellSet.getRows().get(1).getKey())); 216 assertEquals(VALUE_2, Bytes.toString(cellSet.getRows().get(1).getCells().get(0).getValue())); 217 218 client.delete(row_5_url, extraHdr); 219 client.delete(row_6_url, extraHdr); 220 221 } 222 223 @Test 224 public void testMultiCellGetJSONNotFound() throws IOException, JAXBException { 225 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 226 227 StringBuilder path = new StringBuilder(); 228 path.append("/"); 229 path.append(TABLE); 230 path.append("/multiget/?row="); 231 path.append(ROW_1); 232 path.append("&row="); 233 path.append(ROW_2); 234 235 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 236 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 237 assertEquals(200, response.getCode()); 238 ObjectMapper mapper = new JacksonJaxbJsonProvider().locateMapper(CellSetModel.class, 239 MediaType.APPLICATION_JSON_TYPE); 240 CellSetModel cellSet = (CellSetModel) mapper.readValue(response.getBody(), CellSetModel.class); 241 assertEquals(1, cellSet.getRows().size()); 242 assertEquals(ROW_1, Bytes.toString(cellSet.getRows().get(0).getKey())); 243 assertEquals(VALUE_1, Bytes.toString(cellSet.getRows().get(0).getCells().get(0).getValue())); 244 client.delete(row_5_url, extraHdr); 245 } 246 247} 248