View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.rest.client;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertNotNull;
23  import static org.junit.Assert.assertNull;
24  import static org.junit.Assert.assertTrue;
25  
26  import java.io.IOException;
27  import java.util.ArrayList;
28  import java.util.Collections;
29  import java.util.Iterator;
30  import java.util.List;
31  
32  import org.apache.commons.httpclient.Header;
33  import org.apache.hadoop.hbase.Cell;
34  import org.apache.hadoop.hbase.CellUtil;
35  import org.apache.hadoop.hbase.HBaseTestingUtility;
36  import org.apache.hadoop.hbase.HColumnDescriptor;
37  import org.apache.hadoop.hbase.HTableDescriptor;
38  import org.apache.hadoop.hbase.client.HTable;
39  import org.apache.hadoop.hbase.testclassification.MediumTests;
40  import org.apache.hadoop.hbase.TableName;
41  import org.apache.hadoop.hbase.client.Admin;
42  import org.apache.hadoop.hbase.client.Delete;
43  import org.apache.hadoop.hbase.client.Get;
44  import org.apache.hadoop.hbase.client.Put;
45  import org.apache.hadoop.hbase.client.Result;
46  import org.apache.hadoop.hbase.client.ResultScanner;
47  import org.apache.hadoop.hbase.client.Scan;
48  import org.apache.hadoop.hbase.client.Table;
49  import org.apache.hadoop.hbase.rest.HBaseRESTTestingUtility;
50  import org.apache.hadoop.hbase.rest.RESTServlet;
51  import org.apache.hadoop.hbase.util.Bytes;
52  import org.junit.After;
53  import org.junit.AfterClass;
54  import org.junit.Before;
55  import org.junit.BeforeClass;
56  import org.junit.Test;
57  import org.junit.experimental.categories.Category;
58  
59  @Category(MediumTests.class)
60  public class TestRemoteTable {
61    // Verify that invalid URL characters and arbitrary bytes are escaped when
62    // constructing REST URLs per HBASE-7621. RemoteHTable should support row keys
63    // and qualifiers containing any byte for all table operations.
64    private static final String INVALID_URL_CHARS_1 =
65        "|\"\\^{}\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000B\u000C";
66  
67    // HColumnDescriptor prevents certain characters in column names.  The following
68    // are examples of characters are allowed in column names but are not valid in
69    // URLs.
70    private static final String INVALID_URL_CHARS_2 = "|^{}\u0242";
71  
72    // Besides alphanumeric these characters can also be present in table names.
73    private static final String VALID_TABLE_NAME_CHARS = "_-.";
74  
75    private static final TableName TABLE =
76        TableName.valueOf("TestRemoteTable" + VALID_TABLE_NAME_CHARS);
77  
78    private static final byte[] ROW_1 = Bytes.toBytes("testrow1" + INVALID_URL_CHARS_1);
79    private static final byte[] ROW_2 = Bytes.toBytes("testrow2" + INVALID_URL_CHARS_1);
80    private static final byte[] ROW_3 = Bytes.toBytes("testrow3" + INVALID_URL_CHARS_1);
81    private static final byte[] ROW_4 = Bytes.toBytes("testrow4"+ INVALID_URL_CHARS_1);
82  
83    private static final byte[] COLUMN_1 = Bytes.toBytes("a" + INVALID_URL_CHARS_2);
84    private static final byte[] COLUMN_2 = Bytes.toBytes("b" + INVALID_URL_CHARS_2);
85    private static final byte[] COLUMN_3 = Bytes.toBytes("c" + INVALID_URL_CHARS_2);
86  
87    private static final byte[] QUALIFIER_1 = Bytes.toBytes("1" + INVALID_URL_CHARS_1);
88    private static final byte[] QUALIFIER_2 = Bytes.toBytes("2" + INVALID_URL_CHARS_1);
89    private static final byte[] VALUE_1 = Bytes.toBytes("testvalue1");
90    private static final byte[] VALUE_2 = Bytes.toBytes("testvalue2");
91  
92    private static final long ONE_HOUR = 60 * 60 * 1000;
93    private static final long TS_2 = System.currentTimeMillis();
94    private static final long TS_1 = TS_2 - ONE_HOUR;
95  
96    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
97    private static final HBaseRESTTestingUtility REST_TEST_UTIL =
98      new HBaseRESTTestingUtility();
99    private RemoteHTable remoteTable;
100 
101   @BeforeClass
102   public static void setUpBeforeClass() throws Exception {
103     TEST_UTIL.startMiniCluster();
104     REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration());
105   }
106 
107   @Before
108   public void before() throws Exception  {
109     Admin admin = TEST_UTIL.getHBaseAdmin();
110     if (admin.tableExists(TABLE)) {
111       if (admin.isTableEnabled(TABLE)) {
112         admin.disableTable(TABLE);
113       }
114 
115       admin.deleteTable(TABLE);
116     }
117     HTableDescriptor htd = new HTableDescriptor(TABLE);
118     htd.addFamily(new HColumnDescriptor(COLUMN_1).setMaxVersions(3));
119     htd.addFamily(new HColumnDescriptor(COLUMN_2).setMaxVersions(3));
120     htd.addFamily(new HColumnDescriptor(COLUMN_3).setMaxVersions(3));
121     admin.createTable(htd);
122     try (Table table = TEST_UTIL.getConnection().getTable(TABLE)) {
123       Put put = new Put(ROW_1);
124       put.add(COLUMN_1, QUALIFIER_1, TS_2, VALUE_1);
125       table.put(put);
126       put = new Put(ROW_2);
127       put.add(COLUMN_1, QUALIFIER_1, TS_1, VALUE_1);
128       put.add(COLUMN_1, QUALIFIER_1, TS_2, VALUE_2);
129       put.add(COLUMN_2, QUALIFIER_2, TS_2, VALUE_2);
130       table.put(put);
131     }
132     remoteTable = new RemoteHTable(
133       new Client(new Cluster().add("localhost",
134           REST_TEST_UTIL.getServletPort())),
135         TEST_UTIL.getConfiguration(), TABLE.toBytes());
136   }
137 
138   @After
139   public void after() throws Exception {
140     remoteTable.close();
141   }
142 
143   @AfterClass
144   public static void tearDownAfterClass() throws Exception {
145     REST_TEST_UTIL.shutdownServletContainer();
146     TEST_UTIL.shutdownMiniCluster();
147   }
148 
149   @Test
150   public void testGetTableDescriptor() throws IOException {
151     Table table = null;
152     try {
153       table = new HTable(TEST_UTIL.getConfiguration(), TABLE);
154       HTableDescriptor local = table.getTableDescriptor();
155       assertEquals(remoteTable.getTableDescriptor(), local);
156     } finally {
157       if (null != table) table.close();
158     }
159   }
160 
161   @Test
162   public void testGet() throws IOException {
163     Get get = new Get(ROW_1);
164     Result result = remoteTable.get(get);
165     byte[] value1 = result.getValue(COLUMN_1, QUALIFIER_1);
166     byte[] value2 = result.getValue(COLUMN_2, QUALIFIER_2);
167     assertNotNull(value1);
168     assertTrue(Bytes.equals(VALUE_1, value1));
169     assertNull(value2);
170 
171     get = new Get(ROW_1);
172     get.addFamily(COLUMN_3);
173     result = remoteTable.get(get);
174     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
175     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
176     assertNull(value1);
177     assertNull(value2);
178 
179     get = new Get(ROW_1);
180     get.addColumn(COLUMN_1, QUALIFIER_1);
181     get.addColumn(COLUMN_2, QUALIFIER_2);
182     result = remoteTable.get(get);
183     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
184     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
185     assertNotNull(value1);
186     assertTrue(Bytes.equals(VALUE_1, value1));
187     assertNull(value2);
188 
189     get = new Get(ROW_2);
190     result = remoteTable.get(get);
191     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
192     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
193     assertNotNull(value1);
194     assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
195     assertNotNull(value2);
196     assertTrue(Bytes.equals(VALUE_2, value2));
197 
198     get = new Get(ROW_2);
199     get.addFamily(COLUMN_1);
200     result = remoteTable.get(get);
201     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
202     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
203     assertNotNull(value1);
204     assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
205     assertNull(value2);
206 
207     get = new Get(ROW_2);
208     get.addColumn(COLUMN_1, QUALIFIER_1);
209     get.addColumn(COLUMN_2, QUALIFIER_2);
210     result = remoteTable.get(get);
211     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
212     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
213     assertNotNull(value1);
214     assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
215     assertNotNull(value2);
216     assertTrue(Bytes.equals(VALUE_2, value2));
217 
218     // test timestamp
219     get = new Get(ROW_2);
220     get.addFamily(COLUMN_1);
221     get.addFamily(COLUMN_2);
222     get.setTimeStamp(TS_1);
223     result = remoteTable.get(get);
224     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
225     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
226     assertNotNull(value1);
227     assertTrue(Bytes.equals(VALUE_1, value1)); // @TS_1
228     assertNull(value2);
229 
230     // test timerange
231     get = new Get(ROW_2);
232     get.addFamily(COLUMN_1);
233     get.addFamily(COLUMN_2);
234     get.setTimeRange(0, TS_1 + 1);
235     result = remoteTable.get(get);
236     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
237     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
238     assertNotNull(value1);
239     assertTrue(Bytes.equals(VALUE_1, value1)); // @TS_1
240     assertNull(value2);
241 
242     // test maxVersions
243     get = new Get(ROW_2);
244     get.addFamily(COLUMN_1);
245     get.setMaxVersions(2);
246     result = remoteTable.get(get);
247     int count = 0;
248     for (Cell kv: result.listCells()) {
249       if (CellUtil.matchingFamily(kv, COLUMN_1) && TS_1 == kv.getTimestamp()) {
250         assertTrue(CellUtil.matchingValue(kv, VALUE_1)); // @TS_1
251         count++;
252       }
253       if (CellUtil.matchingFamily(kv, COLUMN_1) && TS_2 == kv.getTimestamp()) {
254         assertTrue(CellUtil.matchingValue(kv, VALUE_2)); // @TS_2
255         count++;
256       }
257     }
258     assertEquals(2, count);
259   }
260 
261   @Test
262   public void testMultiGet() throws Exception {
263     ArrayList<Get> gets = new ArrayList<>();
264     gets.add(new Get(ROW_1));
265     gets.add(new Get(ROW_2));
266     Result[] results = remoteTable.get(gets);
267     assertNotNull(results);
268     assertEquals(2, results.length);
269     assertEquals(1, results[0].size());
270     assertEquals(2, results[1].size());
271 
272     //Test Versions
273     gets = new ArrayList<>();
274     Get g = new Get(ROW_1);
275     g.setMaxVersions(3);
276     gets.add(g);
277     gets.add(new Get(ROW_2));
278     results = remoteTable.get(gets);
279     assertNotNull(results);
280     assertEquals(2, results.length);
281     assertEquals(1, results[0].size());
282     assertEquals(3, results[1].size());
283 
284     //404
285     gets = new ArrayList<>();
286     gets.add(new Get(Bytes.toBytes("RESALLYREALLYNOTTHERE")));
287     results = remoteTable.get(gets);
288     assertNotNull(results);
289     assertEquals(0, results.length);
290 
291     gets = new ArrayList<>();
292     gets.add(new Get(Bytes.toBytes("RESALLYREALLYNOTTHERE")));
293     gets.add(new Get(ROW_1));
294     gets.add(new Get(ROW_2));
295     results = remoteTable.get(gets);
296     assertNotNull(results);
297     assertEquals(2, results.length);
298   }
299 
300   @Test
301   public void testPut() throws IOException {
302     Put put = new Put(ROW_3);
303     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
304     remoteTable.put(put);
305 
306     Get get = new Get(ROW_3);
307     get.addFamily(COLUMN_1);
308     Result result = remoteTable.get(get);
309     byte[] value = result.getValue(COLUMN_1, QUALIFIER_1);
310     assertNotNull(value);
311     assertTrue(Bytes.equals(VALUE_1, value));
312 
313     // multiput
314     List<Put> puts = new ArrayList<>();
315     put = new Put(ROW_3);
316     put.add(COLUMN_2, QUALIFIER_2, VALUE_2);
317     puts.add(put);
318     put = new Put(ROW_4);
319     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
320     puts.add(put);
321     put = new Put(ROW_4);
322     put.add(COLUMN_2, QUALIFIER_2, VALUE_2);
323     puts.add(put);
324     remoteTable.put(puts);
325 
326     get = new Get(ROW_3);
327     get.addFamily(COLUMN_2);
328     result = remoteTable.get(get);
329     value = result.getValue(COLUMN_2, QUALIFIER_2);
330     assertNotNull(value);
331     assertTrue(Bytes.equals(VALUE_2, value));
332     get = new Get(ROW_4);
333     result = remoteTable.get(get);
334     value = result.getValue(COLUMN_1, QUALIFIER_1);
335     assertNotNull(value);
336     assertTrue(Bytes.equals(VALUE_1, value));
337     value = result.getValue(COLUMN_2, QUALIFIER_2);
338     assertNotNull(value);
339     assertTrue(Bytes.equals(VALUE_2, value));
340 
341     assertTrue(Bytes.equals(Bytes.toBytes("TestRemoteTable" + VALID_TABLE_NAME_CHARS),
342         remoteTable.getTableName()));
343   }
344 
345   @Test
346   public void testDelete() throws IOException {
347     Put put = new Put(ROW_3);
348     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
349     put.add(COLUMN_2, QUALIFIER_2, VALUE_2);
350     put.add(COLUMN_3, QUALIFIER_1, VALUE_1);
351     put.add(COLUMN_3, QUALIFIER_2, VALUE_2);
352     remoteTable.put(put);
353 
354     Get get = new Get(ROW_3);
355     get.addFamily(COLUMN_1);
356     get.addFamily(COLUMN_2);
357     get.addFamily(COLUMN_3);
358     Result result = remoteTable.get(get);
359     byte[] value1 = result.getValue(COLUMN_1, QUALIFIER_1);
360     byte[] value2 = result.getValue(COLUMN_2, QUALIFIER_2);
361     byte[] value3 = result.getValue(COLUMN_3, QUALIFIER_1);
362     byte[] value4 = result.getValue(COLUMN_3, QUALIFIER_2);
363     assertNotNull(value1);
364     assertTrue(Bytes.equals(VALUE_1, value1));
365     assertNotNull(value2);
366     assertTrue(Bytes.equals(VALUE_2, value2));
367     assertNotNull(value3);
368     assertTrue(Bytes.equals(VALUE_1, value3));
369     assertNotNull(value4);
370     assertTrue(Bytes.equals(VALUE_2, value4));
371 
372     Delete delete = new Delete(ROW_3);
373     delete.addColumn(COLUMN_2, QUALIFIER_2);
374     remoteTable.delete(delete);
375 
376     get = new Get(ROW_3);
377     get.addFamily(COLUMN_1);
378     get.addFamily(COLUMN_2);
379     result = remoteTable.get(get);
380     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
381     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
382     assertNotNull(value1);
383     assertTrue(Bytes.equals(VALUE_1, value1));
384     assertNull(value2);
385 
386     delete = new Delete(ROW_3);
387     delete.setTimestamp(1L);
388     remoteTable.delete(delete);
389 
390     get = new Get(ROW_3);
391     get.addFamily(COLUMN_1);
392     get.addFamily(COLUMN_2);
393     result = remoteTable.get(get);
394     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
395     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
396     assertNotNull(value1);
397     assertTrue(Bytes.equals(VALUE_1, value1));
398     assertNull(value2);
399 
400     // Delete column family from row
401     delete = new Delete(ROW_3);
402     delete.addFamily(COLUMN_3);
403     remoteTable.delete(delete);
404 
405     get = new Get(ROW_3);
406     get.addFamily(COLUMN_3);
407     result = remoteTable.get(get);
408     value3 = result.getValue(COLUMN_3, QUALIFIER_1);
409     value4 = result.getValue(COLUMN_3, QUALIFIER_2);
410     assertNull(value3);
411     assertNull(value4);
412 
413     delete = new Delete(ROW_3);
414     remoteTable.delete(delete);
415 
416     get = new Get(ROW_3);
417     get.addFamily(COLUMN_1);
418     get.addFamily(COLUMN_2);
419     result = remoteTable.get(get);
420     value1 = result.getValue(COLUMN_1, QUALIFIER_1);
421     value2 = result.getValue(COLUMN_2, QUALIFIER_2);
422     assertNull(value1);
423     assertNull(value2);
424   }
425 
426   /**
427    * Test RemoteHTable.Scanner
428    */
429   @Test
430   public void testScanner() throws IOException {
431     List<Put> puts = new ArrayList<>();
432     Put put = new Put(ROW_1);
433     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
434     puts.add(put);
435     put = new Put(ROW_2);
436     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
437     puts.add(put);
438     put = new Put(ROW_3);
439     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
440     puts.add(put);
441     put = new Put(ROW_4);
442     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
443     puts.add(put);
444     remoteTable.put(puts);
445 
446     ResultScanner scanner = remoteTable.getScanner(new Scan());
447 
448     Result[] results = scanner.next(1);
449     assertNotNull(results);
450     assertEquals(1, results.length);
451     assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
452 
453     Result result = scanner.next();
454     assertNotNull(result);
455     assertTrue(Bytes.equals(ROW_2, result.getRow()));
456 
457     results = scanner.next(2);
458     assertNotNull(results);
459     assertEquals(2, results.length);
460     assertTrue(Bytes.equals(ROW_3, results[0].getRow()));
461     assertTrue(Bytes.equals(ROW_4, results[1].getRow()));
462 
463     results = scanner.next(1);
464     assertNull(results);
465     scanner.close();
466 
467     scanner = remoteTable.getScanner(COLUMN_1);
468     results = scanner.next(4);
469     assertNotNull(results);
470     assertEquals(4, results.length);
471     assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
472     assertTrue(Bytes.equals(ROW_2, results[1].getRow()));
473     assertTrue(Bytes.equals(ROW_3, results[2].getRow()));
474     assertTrue(Bytes.equals(ROW_4, results[3].getRow()));
475 
476     scanner.close();
477 
478     scanner = remoteTable.getScanner(COLUMN_1,QUALIFIER_1);
479     results = scanner.next(4);
480     assertNotNull(results);
481     assertEquals(4, results.length);
482     assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
483     assertTrue(Bytes.equals(ROW_2, results[1].getRow()));
484     assertTrue(Bytes.equals(ROW_3, results[2].getRow()));
485     assertTrue(Bytes.equals(ROW_4, results[3].getRow()));
486     scanner.close();
487     assertTrue(remoteTable.isAutoFlush());
488   }
489 
490   @Test
491   public void testCheckAndDelete() throws IOException {
492     Get get = new Get(ROW_1);
493     Result result = remoteTable.get(get);
494     byte[] value1 = result.getValue(COLUMN_1, QUALIFIER_1);
495     byte[] value2 = result.getValue(COLUMN_2, QUALIFIER_2);
496     assertNotNull(value1);
497     assertTrue(Bytes.equals(VALUE_1, value1));
498     assertNull(value2);
499     assertTrue(remoteTable.exists(get));
500     assertEquals(1, remoteTable.existsAll(Collections.singletonList(get)).length);
501     Delete delete = new Delete(ROW_1);
502 
503     remoteTable.checkAndDelete(ROW_1, COLUMN_1, QUALIFIER_1, VALUE_1, delete);
504     assertFalse(remoteTable.exists(get));
505 
506     Put put = new Put(ROW_1);
507     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
508     remoteTable.put(put);
509 
510     assertTrue(remoteTable.checkAndPut(ROW_1, COLUMN_1, QUALIFIER_1, VALUE_1, put));
511     assertFalse(remoteTable.checkAndPut(ROW_1, COLUMN_1, QUALIFIER_1, VALUE_2, put));
512   }
513 
514   /**
515    * Test RemoteHable.Scanner.iterator method
516    */
517   @Test
518   public void testIteratorScaner() throws IOException {
519     List<Put> puts = new ArrayList<>();
520     Put put = new Put(ROW_1);
521     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
522     puts.add(put);
523     put = new Put(ROW_2);
524     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
525     puts.add(put);
526     put = new Put(ROW_3);
527     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
528     puts.add(put);
529     put = new Put(ROW_4);
530     put.add(COLUMN_1, QUALIFIER_1, VALUE_1);
531     puts.add(put);
532     remoteTable.put(puts);
533 
534     ResultScanner scanner = remoteTable.getScanner(new Scan());
535     Iterator<Result> iterator = scanner.iterator();
536     assertTrue(iterator.hasNext());
537     int counter = 0;
538     while (iterator.hasNext()) {
539       iterator.next();
540       counter++;
541     }
542     assertEquals(4, counter);
543   }
544 
545   /**
546    * Test a some methods of class Response.
547    */
548   @Test
549   public void testResponse(){
550     Response response = new Response(200);
551     assertEquals(200, response.getCode());
552     Header[] headers = new Header[2];
553     headers[0] = new Header("header1", "value1");
554     headers[1] = new Header("header2", "value2");
555     response = new Response(200, headers);
556     assertEquals("value1", response.getHeader("header1"));
557     assertFalse(response.hasBody());
558     response.setCode(404);
559     assertEquals(404, response.getCode());
560     headers = new Header[2];
561     headers[0] = new Header("header1", "value1.1");
562     headers[1] = new Header("header2", "value2");
563     response.setHeaders(headers);
564     assertEquals("value1.1", response.getHeader("header1"));
565     response.setBody(Bytes.toBytes("body"));
566     assertTrue(response.hasBody());
567   }
568 
569   /**
570    * Tests keeping a HBase scanner alive for long periods of time. Each call to next() should reset
571    * the ConnectionCache timeout for the scanner's connection.
572    *
573    * @throws Exception if starting the servlet container or disabling or truncating the table fails
574    */
575   @Test
576   public void testLongLivedScan() throws Exception {
577     int numTrials = 6;
578     int trialPause = 1000;
579     int cleanUpInterval = 100;
580 
581     // Shutdown the Rest Servlet container
582     REST_TEST_UTIL.shutdownServletContainer();
583 
584     // Set the ConnectionCache timeout to trigger halfway through the trials
585     TEST_UTIL.getConfiguration().setLong(RESTServlet.MAX_IDLETIME, (numTrials / 2) * trialPause);
586     TEST_UTIL.getConfiguration().setLong(RESTServlet.CLEANUP_INTERVAL, cleanUpInterval);
587 
588     // Start the Rest Servlet container
589     REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration());
590 
591     // Truncate the test table for inserting test scenarios rows keys
592     TEST_UTIL.getHBaseAdmin().disableTable(TABLE);
593     TEST_UTIL.getHBaseAdmin().truncateTable(TABLE, false);
594 
595     remoteTable = new RemoteHTable(
596         new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort())),
597         TEST_UTIL.getConfiguration(), TABLE.toBytes());
598 
599     String row = "testrow";
600 
601     try (Table table = TEST_UTIL.getConnection().getTable(TABLE)) {
602       List<Put> puts = new ArrayList<Put>();
603       Put put = null;
604       for (int i = 1; i <= numTrials; i++) {
605         put = new Put(Bytes.toBytes(row + i));
606         put.addColumn(COLUMN_1, QUALIFIER_1, TS_2, Bytes.toBytes("testvalue" + i));
607         puts.add(put);
608       }
609       table.put(puts);
610     }
611 
612     Scan scan = new Scan();
613     scan.setCaching(1);
614     scan.setBatch(1);
615 
616     ResultScanner scanner = remoteTable.getScanner(scan);
617     Result result = null;
618     // get scanner and rows
619     for (int i = 1; i <= numTrials; i++) {
620       // Make sure that the Scanner doesn't throw an exception after the ConnectionCache timeout
621       result = scanner.next();
622       assertEquals(row + i, Bytes.toString(result.getRow()));
623       Thread.sleep(trialPause);
624     }
625   }
626 }