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 java.io.IOException; 024import java.util.Collection; 025import javax.xml.bind.JAXBContext; 026import javax.xml.bind.Marshaller; 027import javax.xml.bind.Unmarshaller; 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.hbase.HBaseClassTestRule; 030import org.apache.hadoop.hbase.HBaseCommonTestingUtility; 031import org.apache.hadoop.hbase.HBaseTestingUtility; 032import org.apache.hadoop.hbase.HColumnDescriptor; 033import org.apache.hadoop.hbase.HTableDescriptor; 034import org.apache.hadoop.hbase.TableName; 035import org.apache.hadoop.hbase.client.Admin; 036import org.apache.hadoop.hbase.rest.client.Client; 037import org.apache.hadoop.hbase.rest.client.Cluster; 038import org.apache.hadoop.hbase.rest.client.Response; 039import org.apache.hadoop.hbase.rest.model.CellModel; 040import org.apache.hadoop.hbase.rest.model.CellSetModel; 041import org.apache.hadoop.hbase.rest.model.RowModel; 042import org.apache.hadoop.hbase.testclassification.MediumTests; 043import org.apache.hadoop.hbase.testclassification.RestTests; 044import org.apache.hadoop.hbase.util.Bytes; 045import org.apache.http.Header; 046import org.apache.http.message.BasicHeader; 047import org.junit.AfterClass; 048import org.junit.BeforeClass; 049import org.junit.ClassRule; 050import org.junit.Test; 051import org.junit.experimental.categories.Category; 052import org.junit.runner.RunWith; 053import org.junit.runners.Parameterized; 054 055import org.apache.hbase.thirdparty.com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; 056import org.apache.hbase.thirdparty.javax.ws.rs.core.MediaType; 057 058@Category({ RestTests.class, MediumTests.class }) 059@RunWith(Parameterized.class) 060public class TestMultiRowResource { 061 @ClassRule 062 public static final HBaseClassTestRule CLASS_RULE = 063 HBaseClassTestRule.forClass(TestMultiRowResource.class); 064 065 private static final TableName TABLE = TableName.valueOf("TestRowResource"); 066 private static final String CFA = "a"; 067 private static final String CFB = "b"; 068 private static final String COLUMN_1 = CFA + ":1"; 069 private static final String COLUMN_2 = CFB + ":2"; 070 private static final String ROW_1 = "testrow5"; 071 private static final String VALUE_1 = "testvalue5"; 072 private static final String ROW_2 = "testrow6"; 073 private static final String VALUE_2 = "testvalue6"; 074 075 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 076 private static final HBaseRESTTestingUtility REST_TEST_UTIL = new HBaseRESTTestingUtility(); 077 078 private static Client client; 079 private static JAXBContext context; 080 private static Marshaller marshaller; 081 private static Unmarshaller unmarshaller; 082 private static Configuration conf; 083 084 private static Header extraHdr = null; 085 private static boolean csrfEnabled = true; 086 087 @Parameterized.Parameters 088 public static Collection<Object[]> data() { 089 return HBaseCommonTestingUtility.BOOLEAN_PARAMETERIZED; 090 } 091 092 public TestMultiRowResource(Boolean csrf) { 093 csrfEnabled = csrf; 094 } 095 096 @BeforeClass 097 public static void setUpBeforeClass() throws Exception { 098 conf = TEST_UTIL.getConfiguration(); 099 conf.setBoolean(RESTServer.REST_CSRF_ENABLED_KEY, csrfEnabled); 100 if (csrfEnabled) { 101 conf.set(RESTServer.REST_CSRF_BROWSER_USERAGENTS_REGEX_KEY, ".*"); 102 } 103 extraHdr = new BasicHeader(RESTServer.REST_CSRF_CUSTOM_HEADER_DEFAULT, ""); 104 TEST_UTIL.startMiniCluster(); 105 REST_TEST_UTIL.startServletContainer(conf); 106 context = JAXBContext.newInstance(CellModel.class, CellSetModel.class, RowModel.class); 107 marshaller = context.createMarshaller(); 108 unmarshaller = context.createUnmarshaller(); 109 client = new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort())); 110 Admin admin = TEST_UTIL.getAdmin(); 111 if (admin.tableExists(TABLE)) { 112 return; 113 } 114 HTableDescriptor htd = new HTableDescriptor(TABLE); 115 htd.addFamily(new HColumnDescriptor(CFA)); 116 htd.addFamily(new HColumnDescriptor(CFB)); 117 admin.createTable(htd); 118 } 119 120 @AfterClass 121 public static void tearDownAfterClass() throws Exception { 122 REST_TEST_UTIL.shutdownServletContainer(); 123 TEST_UTIL.shutdownMiniCluster(); 124 } 125 126 @Test 127 public void testMultiCellGetJSON() throws IOException { 128 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 129 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 130 131 StringBuilder path = new StringBuilder(); 132 path.append("/"); 133 path.append(TABLE); 134 path.append("/multiget/?row="); 135 path.append(ROW_1); 136 path.append("&row="); 137 path.append(ROW_2); 138 139 if (csrfEnabled) { 140 Response response = client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1)); 141 assertEquals(400, response.getCode()); 142 } 143 144 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 145 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 146 147 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 148 assertEquals(200, response.getCode()); 149 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); 150 151 client.delete(row_5_url, extraHdr); 152 client.delete(row_6_url, extraHdr); 153 } 154 155 @Test 156 public void testMultiCellGetXML() throws IOException { 157 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 158 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 159 160 StringBuilder path = new StringBuilder(); 161 path.append("/"); 162 path.append(TABLE); 163 path.append("/multiget/?row="); 164 path.append(ROW_1); 165 path.append("&row="); 166 path.append(ROW_2); 167 168 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 169 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 170 171 Response response = client.get(path.toString(), Constants.MIMETYPE_XML); 172 assertEquals(200, response.getCode()); 173 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type")); 174 175 client.delete(row_5_url, extraHdr); 176 client.delete(row_6_url, extraHdr); 177 } 178 179 @Test 180 public void testMultiCellGetWithColsJSON() throws IOException { 181 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 182 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 183 184 StringBuilder path = new StringBuilder(); 185 path.append("/"); 186 path.append(TABLE); 187 path.append("/multiget"); 188 path.append("/" + COLUMN_1 + "," + CFB); 189 path.append("?row="); 190 path.append(ROW_1); 191 path.append("&row="); 192 path.append(ROW_2); 193 194 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 195 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 196 197 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 198 assertEquals(200, response.getCode()); 199 ObjectMapper mapper = new JacksonJaxbJsonProvider().locateMapper(CellSetModel.class, 200 MediaType.APPLICATION_JSON_TYPE); 201 CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class); 202 assertEquals(2, cellSet.getRows().size()); 203 assertEquals(ROW_1, Bytes.toString(cellSet.getRows().get(0).getKey())); 204 assertEquals(VALUE_1, Bytes.toString(cellSet.getRows().get(0).getCells().get(0).getValue())); 205 assertEquals(ROW_2, Bytes.toString(cellSet.getRows().get(1).getKey())); 206 assertEquals(VALUE_2, Bytes.toString(cellSet.getRows().get(1).getCells().get(0).getValue())); 207 208 client.delete(row_5_url, extraHdr); 209 client.delete(row_6_url, extraHdr); 210 } 211 212 @Test 213 public void testMultiCellGetJSONNotFound() throws IOException { 214 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 215 216 StringBuilder path = new StringBuilder(); 217 path.append("/"); 218 path.append(TABLE); 219 path.append("/multiget/?row="); 220 path.append(ROW_1); 221 path.append("&row="); 222 path.append(ROW_2); 223 224 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 225 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 226 assertEquals(200, response.getCode()); 227 ObjectMapper mapper = new JacksonJaxbJsonProvider().locateMapper(CellSetModel.class, 228 MediaType.APPLICATION_JSON_TYPE); 229 CellSetModel cellSet = (CellSetModel) mapper.readValue(response.getBody(), CellSetModel.class); 230 assertEquals(1, cellSet.getRows().size()); 231 assertEquals(ROW_1, Bytes.toString(cellSet.getRows().get(0).getKey())); 232 assertEquals(VALUE_1, Bytes.toString(cellSet.getRows().get(0).getCells().get(0).getValue())); 233 client.delete(row_5_url, extraHdr); 234 } 235 236 @Test 237 public void testMultiCellGetWithColsInQueryPathJSON() throws IOException { 238 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 239 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 240 241 StringBuilder path = new StringBuilder(); 242 path.append("/"); 243 path.append(TABLE); 244 path.append("/multiget/?row="); 245 path.append(ROW_1); 246 path.append("/"); 247 path.append(COLUMN_1); 248 path.append("&row="); 249 path.append(ROW_2); 250 path.append("/"); 251 path.append(COLUMN_1); 252 253 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 254 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 255 256 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 257 assertEquals(200, response.getCode()); 258 ObjectMapper mapper = new JacksonJaxbJsonProvider().locateMapper(CellSetModel.class, 259 MediaType.APPLICATION_JSON_TYPE); 260 CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class); 261 assertEquals(1, cellSet.getRows().size()); 262 assertEquals(ROW_1, Bytes.toString(cellSet.getRows().get(0).getKey())); 263 assertEquals(VALUE_1, Bytes.toString(cellSet.getRows().get(0).getCells().get(0).getValue())); 264 265 client.delete(row_5_url, extraHdr); 266 client.delete(row_6_url, extraHdr); 267 } 268}