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.hbase.archetypes.exemplars.client;
019
020import java.io.IOException;
021import java.util.Map.Entry;
022import java.util.NavigableMap;
023import org.apache.hadoop.hbase.NamespaceDescriptor;
024import org.apache.hadoop.hbase.NamespaceNotFoundException;
025import org.apache.hadoop.hbase.TableName;
026import org.apache.hadoop.hbase.client.Admin;
027import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
028import org.apache.hadoop.hbase.client.Connection;
029import org.apache.hadoop.hbase.client.ConnectionFactory;
030import org.apache.hadoop.hbase.client.Delete;
031import org.apache.hadoop.hbase.client.Get;
032import org.apache.hadoop.hbase.client.Put;
033import org.apache.hadoop.hbase.client.Result;
034import org.apache.hadoop.hbase.client.Table;
035import org.apache.hadoop.hbase.client.TableDescriptor;
036import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
037import org.apache.hadoop.hbase.util.Bytes;
038
039/**
040 * Successful running of this application requires access to an active instance of HBase. For
041 * install instructions for a standalone instance of HBase, please refer to
042 * https://hbase.apache.org/book.html#quickstart
043 */
044public final class HelloHBase {
045
046  protected static final String MY_NAMESPACE_NAME = "myTestNamespace";
047  static final TableName MY_TABLE_NAME = TableName.valueOf("myTestTable");
048  static final byte[] MY_COLUMN_FAMILY_NAME = Bytes.toBytes("cf");
049  static final byte[] MY_FIRST_COLUMN_QUALIFIER = Bytes.toBytes("myFirstColumn");
050  static final byte[] MY_SECOND_COLUMN_QUALIFIER = Bytes.toBytes("mySecondColumn");
051  static final byte[] MY_ROW_ID = Bytes.toBytes("rowId01");
052
053  // Private constructor included here to avoid checkstyle warnings
054  private HelloHBase() {
055  }
056
057  public static void main(final String[] args) throws IOException {
058    final boolean deleteAllAtEOJ = true;
059
060    /**
061     * ConnectionFactory#createConnection() automatically looks for hbase-site.xml (HBase
062     * configuration parameters) on the system's CLASSPATH, to enable creation of Connection to
063     * HBase via ZooKeeper.
064     */
065    try (Connection connection = ConnectionFactory.createConnection();
066      Admin admin = connection.getAdmin()) {
067      admin.getClusterMetrics(); // assure connection successfully established
068      System.out
069        .println("\n*** Hello HBase! -- Connection has been " + "established via ZooKeeper!!\n");
070
071      createNamespaceAndTable(admin);
072
073      System.out.println("Getting a Table object for [" + MY_TABLE_NAME
074        + "] with which to perform CRUD operations in HBase.");
075      try (Table table = connection.getTable(MY_TABLE_NAME)) {
076
077        putRowToTable(table);
078        getAndPrintRowContents(table);
079
080        if (deleteAllAtEOJ) {
081          deleteRow(table);
082        }
083      }
084
085      if (deleteAllAtEOJ) {
086        deleteNamespaceAndTable(admin);
087      }
088    }
089  }
090
091  /**
092   * Invokes Admin#createNamespace and Admin#createTable to create a namespace with a table that has
093   * one column-family.
094   * @param admin Standard Admin object
095   * @throws IOException If IO problem encountered
096   */
097  static void createNamespaceAndTable(final Admin admin) throws IOException {
098
099    if (!namespaceExists(admin, MY_NAMESPACE_NAME)) {
100      System.out.println("Creating Namespace [" + MY_NAMESPACE_NAME + "].");
101
102      admin.createNamespace(NamespaceDescriptor.create(MY_NAMESPACE_NAME).build());
103    }
104    if (!admin.tableExists(MY_TABLE_NAME)) {
105      System.out.println("Creating Table [" + MY_TABLE_NAME.getNameAsString()
106        + "], with one Column Family [" + Bytes.toString(MY_COLUMN_FAMILY_NAME) + "].");
107      TableDescriptor desc = TableDescriptorBuilder.newBuilder(MY_TABLE_NAME)
108        .setColumnFamily(ColumnFamilyDescriptorBuilder.of(MY_COLUMN_FAMILY_NAME)).build();
109      admin.createTable(desc);
110    }
111  }
112
113  /**
114   * Invokes Table#put to store a row (with two new columns created 'on the fly') into the table.
115   * @param table Standard Table object (used for CRUD operations).
116   * @throws IOException If IO problem encountered
117   */
118  static void putRowToTable(final Table table) throws IOException {
119
120    table.put(new Put(MY_ROW_ID)
121      .addColumn(MY_COLUMN_FAMILY_NAME, MY_FIRST_COLUMN_QUALIFIER, Bytes.toBytes("Hello"))
122      .addColumn(MY_COLUMN_FAMILY_NAME, MY_SECOND_COLUMN_QUALIFIER, Bytes.toBytes("World!")));
123
124    System.out.println("Row [" + Bytes.toString(MY_ROW_ID) + "] was put into Table ["
125      + table.getName().getNameAsString() + "] in HBase;\n"
126      + "  the row's two columns (created 'on the fly') are: ["
127      + Bytes.toString(MY_COLUMN_FAMILY_NAME) + ":" + Bytes.toString(MY_FIRST_COLUMN_QUALIFIER)
128      + "] and [" + Bytes.toString(MY_COLUMN_FAMILY_NAME) + ":"
129      + Bytes.toString(MY_SECOND_COLUMN_QUALIFIER) + "]");
130  }
131
132  /**
133   * Invokes Table#get and prints out the contents of the retrieved row.
134   * @param table Standard Table object
135   * @throws IOException If IO problem encountered
136   */
137  static void getAndPrintRowContents(final Table table) throws IOException {
138
139    Result row = table.get(new Get(MY_ROW_ID));
140
141    System.out.println("Row [" + Bytes.toString(row.getRow()) + "] was retrieved from Table ["
142      + table.getName().getNameAsString() + "] in HBase, with the following content:");
143
144    for (Entry<byte[], NavigableMap<byte[], byte[]>> colFamilyEntry : row.getNoVersionMap()
145      .entrySet()) {
146      String columnFamilyName = Bytes.toString(colFamilyEntry.getKey());
147
148      System.out.println("  Columns in Column Family [" + columnFamilyName + "]:");
149
150      for (Entry<byte[], byte[]> columnNameAndValueMap : colFamilyEntry.getValue().entrySet()) {
151
152        System.out.println("    Value of Column [" + columnFamilyName + ":"
153          + Bytes.toString(columnNameAndValueMap.getKey()) + "] == "
154          + Bytes.toString(columnNameAndValueMap.getValue()));
155      }
156    }
157  }
158
159  /**
160   * Checks to see whether a namespace exists.
161   * @param admin         Standard Admin object
162   * @param namespaceName Name of namespace
163   * @return true If namespace exists
164   * @throws IOException If IO problem encountered
165   */
166  static boolean namespaceExists(final Admin admin, final String namespaceName) throws IOException {
167    try {
168      admin.getNamespaceDescriptor(namespaceName);
169    } catch (NamespaceNotFoundException e) {
170      return false;
171    }
172    return true;
173  }
174
175  /**
176   * Invokes Table#delete to delete test data (i.e. the row)
177   * @param table Standard Table object
178   * @throws IOException If IO problem is encountered
179   */
180  static void deleteRow(final Table table) throws IOException {
181    System.out.println("Deleting row [" + Bytes.toString(MY_ROW_ID) + "] from Table ["
182      + table.getName().getNameAsString() + "].");
183    table.delete(new Delete(MY_ROW_ID));
184  }
185
186  /**
187   * Invokes Admin#disableTable, Admin#deleteTable, and Admin#deleteNamespace to disable/delete
188   * Table and delete Namespace.
189   * @param admin Standard Admin object
190   * @throws IOException If IO problem is encountered
191   */
192  static void deleteNamespaceAndTable(final Admin admin) throws IOException {
193    if (admin.tableExists(MY_TABLE_NAME)) {
194      System.out.println("Disabling/deleting Table [" + MY_TABLE_NAME.getNameAsString() + "].");
195      admin.disableTable(MY_TABLE_NAME); // Disable a table before deleting it.
196      admin.deleteTable(MY_TABLE_NAME);
197    }
198    if (namespaceExists(admin, MY_NAMESPACE_NAME)) {
199      System.out.println("Deleting Namespace [" + MY_NAMESPACE_NAME + "].");
200      admin.deleteNamespace(MY_NAMESPACE_NAME);
201    }
202  }
203}