דוגמה: סביבה רגילה של Java App Engine

הדוגמה הזו היא אפליקציה של App Engine, שנכתבה ב-Java, שכותבת כמה ברכות של 'שלום עולם' לטבלה של Bigtable וקוראת אותן בחזרה. האפליקציה פועלת ב- Google Cloud בסביבה הרגילה של App Engine. האפליקציה משתמשת בזמן ריצה של Java 8. הקוד של האפליקציה הזו נמצא במאגר GitHub‏ GoogleCloudPlatform/java-docs-samples, בספרייה appengine-java8/bigtable.

סקירה כללית של דוגמת הקוד

דוגמת הקוד כוללת את המחלקות הבאות:

BigtableHelper

BigtableHelper מספק שיטה ליצירת חיבור ל-Bigtable. הוא גם שומר במטמון את החיבור ומספק שיטה לאחזור החיבור מהמטמון אם הוא קיים. יצירת חיבור היא פעולה יחסית יקרה, ולכן מומלץ ליצור חיבור יחיד ולעשות בו שימוש חוזר.

public static void connect() throws IOException {

  if (PROJECT_ID == null || INSTANCE_ID == null) {
    if (sc != null) {
      sc.log("environment variables BIGTABLE_PROJECT, and BIGTABLE_INSTANCE need to be defined.");
    }
    return;
  }

  connection = BigtableConfiguration.connect(PROJECT_ID, INSTANCE_ID);
}

/**
 * Get the shared connection to Cloud Bigtable.
 *
 * @return the connection
 */
public static Connection getConnection() {
  if (connection == null) {
    try {
      connect();
    } catch (IOException e) {
      if (sc != null) {
        sc.log("connect ", e);
      }
    }
  }
  if (connection == null) {
    if (sc != null) {
      sc.log("BigtableHelper-No Connection");
    }
  }
  return connection;
}

BigtableHelloWorld

BigtableHelloWorld משמש לכתיבת סדרת ברכות ל-Bigtable, לקריאת הברכות ולהצגתן. המחלקת מקבלת חיבור ל-Bigtable מ-BigtableHelper, משתמשת בחיבור כדי לקבל אובייקט Table, שמאפשר לקרוא ולכתוב ערכים, ואז משתמשת באובייקט Table כדי לכתוב לטבלה ולקרוא ממנה.


/**
 * A minimal application that connects to Cloud Bigtable using the native HBase API and performs
 * some basic operations.
 */
public class BigtableHelloWorld {

  // Refer to table metadata names by byte array in the HBase API
  private static final byte[] TABLE_NAME = Bytes.toBytes("Hello-Bigtable");
  private static final byte[] COLUMN_FAMILY_NAME = Bytes.toBytes("cf1");
  private static final byte[] COLUMN_NAME = Bytes.toBytes("greeting");

  // Write some friendly greetings to Cloud Bigtable
  private static final String[] GREETINGS = {
    "Hello World!", "Hello Cloud Bigtable!", "Hello HBase!"
  };

  /**
   * Create a table -- first time only.
   *
   * @param connection to Bigtable
   * @return the status
   */
  public static String create(Connection connection) {
    try {
      // The admin API lets us create, manage and delete tables
      Admin admin = connection.getAdmin();

      // Create a table with a single column family
      HTableDescriptor descriptor = new HTableDescriptor(TableName.valueOf(TABLE_NAME));
      descriptor.addFamily(new HColumnDescriptor(COLUMN_FAMILY_NAME));

      admin.createTable(descriptor);
    } catch (IOException e) {
      return "Table exists.";
    }
    return "Create table " + Bytes.toString(TABLE_NAME);
  }

  /** Connects to Cloud Bigtable, runs some basic operations and prints the results. */
  public static String doHelloWorld() {

    StringBuilder result = new StringBuilder();

    // Create the Bigtable connection, use try-with-resources to make sure it gets closed
    Connection connection = BigtableHelper.getConnection();
    result.append(create(connection));
    result.append("<br><br>");
    try (Table table = connection.getTable(TableName.valueOf(TABLE_NAME))) {

      // Retrieve the table we just created so we can do some reads and writes

      // Write some rows to the table
      result.append("Write some greetings to the table<br>");
      for (int i = 0; i < GREETINGS.length; i++) {
        // Each row has a unique row key.
        //
        // Note: This example uses sequential numeric IDs for simplicity, but
        // this can result in poor performance in a production application.
        // Since rows are stored in sorted order by key, sequential keys can
        // result in poor distribution of operations across nodes.
        //
        // For more information about how to design a Bigtable schema for the
        // best performance, see the documentation:
        //
        //     https://cloud.google.com/bigtable/docs/schema-design
        String rowKey = "greeting" + i;

        // Put a single row into the table. We could also pass a list of Puts to write a batch.
        Put put = new Put(Bytes.toBytes(rowKey));
        put.addColumn(COLUMN_FAMILY_NAME, COLUMN_NAME, Bytes.toBytes(GREETINGS[i]));
        table.put(put);
      }

      // Get the first greeting by row key
      String rowKey = "greeting0";
      Result getResult = table.get(new Get(Bytes.toBytes(rowKey)));
      String greeting = Bytes.toString(getResult.getValue(COLUMN_FAMILY_NAME, COLUMN_NAME));
      result.append("Get a single greeting by row key<br>");

      result.append("     ");
      result.append(rowKey);
      result.append("= ");
      result.append(greeting);
      result.append("<br>");

      // Now scan across all rows.
      Scan scan = new Scan();

      result.append("Scan for all greetings:");
      ResultScanner scanner = table.getScanner(scan);
      for (Result row : scanner) {
        byte[] valueBytes = row.getValue(COLUMN_FAMILY_NAME, COLUMN_NAME);
        result.append("    ");
        result.append(Bytes.toString(valueBytes));
        result.append("<br>");
      }

    } catch (IOException e) {
      result.append("Exception while running HelloWorld: " + e.getMessage() + "<br>");
      result.append(e.toString());
      return result.toString();
    }

    return result.toString();
  }
}