title: HBase secondary index with observer coprocessor, .put on the index table results in recursion
body: <p>In HBase database I want to create a secondary index by using additional "linking" table. I have followed the example given in this answer: <a href="https://stackoverflow.com/questions/14540167/create-secondary-index-using-coprocesor-hbase">Create secondary index using coprocesor HBase</a></p>
  
  <p>I am not very well familiar with the entire concept of HBase, and I had read some examples on the issue of creating secondary indexes. I am attaching the coprocessor to single table only, like this:</p>
  
  <pre><code>disable 'Entry2'
  alter 'Entry2', METHOD =&gt; 'table_att', 'COPROCESSOR' =&gt; '/home/user/hbase/rootdir/hcoprocessors.jar|com.acme.hobservers.EntryParentIndex||'
  enable 'Entry2'
  </code></pre>
  
  <p>The source code of it, is as follows:</p>
  
  <pre><code>public class EntryParentIndex extends BaseRegionObserver{
  
  private static final Log LOG = LogFactory.getLog(CoprocessorHost.class);
  
  private HTablePool pool = null;
  
  private final static String  INDEX_TABLE                       = "EntryParentIndex";
  private final static String  SOURCE_TABLE                      = "Entry2";
  
  @Override
    public void start(CoprocessorEnvironment env) throws IOException {
      pool = new HTablePool(env.getConfiguration(), 10);
   }
  
  @Override
    public void prePut(
        final ObserverContext&lt;RegionCoprocessorEnvironment&gt; observerContext,
        final Put put,
        final WALEdit edit,
        final boolean writeToWAL)
      throws IOException {
  
      try {
  
           final List&lt;KeyValue&gt; filteredList = put.get(Bytes.toBytes ("data"),Bytes.toBytes("parentId"));
           byte [] id = put.getRow(); //Get the Entry ID
  
           KeyValue kv=filteredList.get( 0 ); //get Entry PARENT_ID
           byte[] parentId=kv.getValue();
  
  
          HTableInterface htbl = pool.getTable(Bytes.toBytes(INDEX_TABLE));
  
          //create row key for the index table
          byte[] p1=concatTwoByteArrays(parentId, ":".getBytes()); //Insert a semicolon between two UUIDs
          byte[] rowkey=concatTwoByteArrays(p1, id);
  
          Put indexput  = new Put(rowkey);
  
          //The following call is setting up a strange? recursion, resulting
          //...in thesame prePut method invoken again and again. Interestingly
          //...the recursion limits itself up to 6 times. The actual row does not
          //...get inserted into the INDEX_TABLE
          htbl.put(indexput);
  
  
          htbl.close();
  
      }
      catch ( IllegalArgumentException ex) {  }
  
    }
  
  
    @Override
    public void stop(CoprocessorEnvironment env) throws IOException {
      pool.close();
    }
  
    public static final byte[] concatTwoByteArrays(byte[] first, byte[] second) {
          byte[] result = Arrays.copyOf(first, first.length + second.length);
          System.arraycopy(second, 0, result, first.length, second.length);
          return result;
      }
  
  }
  </code></pre>
  
  <p>This executes when I perform put on the SOURCE_TABLE.
  There is a comment in the code (please seek it): "The following call is setting up a strange".</p>
  
  <p>I set a debugging print in the log confirming that the prePut method is being executed only on the SOURCE_TABLE, and never on the INDEX_TABLE. Yet I don't understand why this strange recursion is happening despite in the coprocessor I only execute one put on the INDEX_TABLE.</p>
  
  <p>I have also confirmed that the put action on the source table is again only one.</p>