Now that KijiSchema is managing your phonebook table, the next step is to start writing and reading contacts.

Writing to a Table

Clearly, you need a way to add your ever-increasing set of friends to the phonebook. KijiSchema supports writing to Kiji tables with the KijiTableWriter class. The phonebook example includes code that uses a KijiTableWriter to write to the phonebook table.

The class is included in the phonebook example source (located under $KIJI_HOME/examples/phonebook/src/main/java/org/kiji/examples/phonebook/). It implements a command-line tool that asks a user for contact information and then uses that information to populate the columns in a row in the Kiji table phonebook for that contact. To start, loads an HBase configuration.


(Loading the HBase configuration is necessary for running on top of HBase, but not on top of Cassandra.)

The code then connects to Kiji and opens the phonebook table for writing. A Kiji instance is specified by a KijiURI. To create a KijiURI, you use a KijiURI.KijiURIBuilder instance. We have written the AddEntry class such that the user can specify a Kiji instance URI on the command line; this user-specified URI is stored as a string in mKijiUri, which we use to produce a KijiURI object:

kiji =, getConf());
table = kiji.openTable(TABLE_NAME); // TABLE_NAME is "phonebook"
writer = table.openTableWriter();

Adding the phonebook entry

We then create an EntityId using the contact's first and last name. The EntityId uniquely identifies the row for the contact in the Kiji table.

final EntityId user = table.getEntityId(first + "," + last);

We write the contact information gained from the user to the appropriate columns in the contact's row of the Kiji table phonebook. The column names are specified as constants in the class. For example, the first name is written as:

writer.put(user, Fields.INFO_FAMILY, Fields.FIRST_NAME, timestamp, first);


We are done with the Kiji instance, table and writer we opened earlier. We close or release these objects to free resources (for example, connections to HBase) that they use. We close or release these objects in the reverse order we opened them in.


Something important to note is that the Kiji instance and Kiji table are released rather than closed. Kiji instances and tables are often long-lived objects that many aspects of your system may hold reference to. Rather than require that you define a single "owner" of this object who closes it when the system is finished using it, you can use reference counting to manage this object's lifetime.

When a Kiji instance is created with, or a 'KijiTable' is opened with Kiji.openTable(name), it has an automatic reference count of 1. You should call kiji.release() or table.release() or use ResourceUtils.releaseOrLog(kiji) or ResourceUtils.releaseOrLog(table) to discard these reference.

If another class or method gets a reference to an already-opened Kiji instance, you should call kiji.retain() to increment its reference count. That same class or method is responsible for calling kiji.release() when it no longer holds the reference.

A Kiji object or KijiTable will close itself and free its underlying resources when its reference count drops to 0.

Running the Example

You run the class AddEntry with the kiji command-line tool as follows:

$KIJI_HOME/bin/kiji jar \
    $KIJI_HOME/examples/phonebook/lib/kiji-phonebook-1.1.7.jar \
    org.kiji.examples.phonebook.AddEntry \

The syntax shown here is the preferred mechanism to run your own main(...) method with Kiji and its dependencies properly on the classpath.

The interactive prompts (with sample responses) should look like:

First name: Renuka
Last name: Apte
Email address:
Telephone: 415-111-2222
Address line 1: 375 Alabama St
Address line 2:
City: SF
State: CA
Zip: 94110


Now we can verify that our entry got into the phonebook table using the command kiji-scan, which will scan rows from our Kiji table, or kiji-get, to read back a single row. Note that the kiji-scan command does not currently work in Cassandra-backed Kiji instances.

Before running either command, we must ensure that the org.kiji.examples.phonebook.Address Avro record class (mentioned in the DDL and used by AddEntry) is on our classpath. If you have not already done so, put the phonebook jar file on your Kiji classpath:

export KIJI_CLASSPATH="$KIJI_HOME/examples/phonebook/lib/*"

Now use kiji scan:

$KIJI_HOME/bin/kiji scan ${KIJI}/phonebook
Scanning kiji table: kiji://localhost:2181/phonebook/phonebook/
entity-id=['Renuka,Apte'] [1384235579766] info:firstname
entity-id=['Renuka,Apte'] [1384235579766] info:lastname
entity-id=['Renuka,Apte'] [1384235579766] info:email
entity-id=['Renuka,Apte'] [1384235579766] info:telephone
entity-id=['Renuka,Apte'] [1384235579766] info:address
                                 {"addr1": "375 Alabama St", "apt": null, "addr2": null, "city": "SF", "state": "CA", "zip": 94110}

Or run kiji get:

$KIJI_HOME/bin/kiji get ${KIJI}/phonebook --entity-id="['Renuka,Apte']"
Looking up entity: ['Renuka,Apte'] from kiji table: kiji-cassandra://localhost:2181/localhost:9042/phonebook/phonebook/
entity-id=['Renuka,Apte'] [1384235579766] info:firstname
entity-id=['Renuka,Apte'] [1384235579766] info:lastname
entity-id=['Renuka,Apte'] [1384235579766] info:email
entity-id=['Renuka,Apte'] [1384235579766] info:telephone
entity-id=['Renuka,Apte'] [1384235579766] info:address
                                 {"addr1": "375 Alabama St", "apt": null, "addr2": null, "city": "SF", "state": "CA", "zip": 94110}

Reading From a Table

Now that we've added a contact to your phonebook, we should be able to read this contact from the table. KijiSchema supports reading from Kiji tables with the KijiTableReader class. We have included an example of retrieving a single contact from the Kiji table using the contact's first and last names.

We connect to Kiji and our phonebook table in the same way we did above.

kiji =, getConf());
table = kiji.openTable(TABLE_NAME); // TABLE_NAME is "phonebook"

Since we are interested in reading from our table, we open a KijiTableReader.

reader = table.openTableReader();

Looking up the requested entry

Create an EntityId to retrieve a contact using the contact's first and last name:

final EntityId entityId = table.getEntityId(mFirst + "," + mLast);

Create a data request to specify the desired columns from the Kiji Table.

final KijiDataRequestBuilder reqBuilder = KijiDataRequest.builder();
    .add(Fields.INFO_FAMILY, Fields.FIRST_NAME)
    .add(Fields.INFO_FAMILY, Fields.LAST_NAME)
    .add(Fields.INFO_FAMILY, Fields.EMAIL)
    .add(Fields.INFO_FAMILY, Fields.TELEPHONE)
    .add(Fields.INFO_FAMILY, Fields.ADDRESS);
final KijiDataRequest dataRequest =;

We now retrieve our result by passing the EntityId and data request to our table reader. Doing so results in a KijiRowData containing the data read from the table.

final KijiRowData rowData = reader.get(entityId, dataRequest);

Running the Example

You can run the following command to perform a lookup using the example:

$KIJI_HOME/bin/kiji jar \
    $KIJI_HOME/examples/phonebook/lib/kiji-phonebook-1.1.7.jar \
    org.kiji.examples.phonebook.Lookup \
    --kiji=${KIJI} \
    --first=Renuka --last=Apte
Renuka Apte:, tel=415-111-2222, addr={"addr1": "375 Alabama St", "apt": null, "addr2": null, "city": "SF", "state": "CA", "zip": 94110}