# A Simple HOWTO for Using
Berkeley DB Java Edition
on the
Android Platform

3.3.62, June 04, 2008

## Overview

JE can be used with the Google Android platform. This document discusses how to create a simple program and UI which will allow a user to do trivial JE "gets" and "puts" from within Android.

## Installation

- Start by downloading and installing the Android SDK. Put the Android "tools" directory in your path so that you pick up the command line tools.

## Steps With Android Eclipse Plugin

- Follow the installation instructions to install and configure the Android Eclipse plugin.
- Go to `"File->New->Other Project->Android->Android Project"`. Then provide a Project name, application name , package name (`com.sleepycat.je`), and activity name (`JEExample`).
- Unpack the JE distribution (referred to as `<je-dir>` in this document), copy the contents of the `<je-dir>/src` directory to the directory where you want to store this Eclipse project's source code (referred to as `<eclipse-je-android-dir>` in this document).
- Go to `<eclipse-je-android-dir>/src` and delete the following directories: `com/sleepycat/je/jmx` and `com/sleepycat/je/jca`. Also delete these two source files: `com/sleepycat/persist/model/ClassEnhancer.java` and `com/sleepycat/persist/model/ClassEnhancerTask.java`.
- Make a new directory `com/sleepycat/je/xa` in `<eclipse-je-android-dir>/src` and copy `XAException.java`, `XAResource.java` and `Xid.java` (shown at the bottom of this page) into this new directory.
- In `<eclipse-je-android-dir>/src`, change the
  `import javax.transaction.xa`
  to
  `import com.sleepycat.je.xa`
  in following source files:
  `com/sleepycat/je/XAEnvironment.java`,
  `com/sleepycat/je/txn/Txn.java`,
  `com/sleepycat/je/txn/TxnManager.java`,
  `com/sleepycat/je/txn/TxnPrepare.java`,
  `com/sleepycat/je/log/LNFileReader.java`,
  `com/sleepycat/je/log/LogUtils.java`.
- Copy
  `JEExample.java` to `<eclipse-je-android-dir>/src/com/sleepycat/je`,
  `main.xml` to `res/layout/main.xml` and
  `strings.xml` to `res/values/strings.xml`
  These files are shown at the bottom of this page.
- Build a new Configure Launch for this project, then run it as an Android project.

## Steps Without Android Eclipse Plugin

- Create a `work` directory (referred to as `<work-dir>` in this document).
- Make a new directory `<work-dir>/je`, copy `<je-dir>/src` to `<work-dir>/je`.
- Go to `<work-dir>/je/src` and delete the following directories: `com/sleepycat/je/jmx` and `com/sleepycat/je/jca`. Also delete these two source files: `com/sleepycat/persist/model/ClassEnhancer.java` and `com/sleepycat/persist/model/ClassEnhancerTask.java`.
- Make a new directory `com/sleepycat/je/xa` in `<work-dir>/je/src` and copy `XAException.java`, `XAResource.java` and `Xid.java` (shown at the bottom of this page) into this new directory.
- In `<work-dir>/je/src`, change the
  `import javax.transaction.xa`
  to
  `import com.sleepycat.je.xa`
  in following source files:
  `com/sleepycat/je/XAEnvironment.java`,
  `com/sleepycat/je/txn/Txn.java`,
  `com/sleepycat/je/txn/TxnManager.java`,
  `com/sleepycat/je/txn/TxnPrepare.java`,
  `com/sleepycat/je/log/LNFileReader.java`,
  `com/sleepycat/je/log/LogUtils.java`.
- Review `<android-home>/docs/intro/hello-android.html` for instructions on how to create a project. Do
  `activityCreator --out <work-dir> com.sleepycat.je.JEExample`
  This creates `<work-dir>/src/com/sleepycat/je/JEExample.java`
- Replace the generated contents of `<work-dir>/src/com/sleepycat/je/JEExample.java`, `<work-dir>/res/layout/main.xml`, `<work-dir>/res/values/strings.xml` with the source code for `JEExample.java`, `main.xml` and `strings.xml` shown at the bottom of this page.
- Go to the `<android-installation-home>/tools`, open and edit the `dx.bat` file, change the last line from `"call java -Djava.ext.dirs=%frameworkdir% -jar %jarpath% %*"` to `"call java -Xms256M -Xmx512M -Djava.ext.dirs=%frameworkdir% -jar %jarpath% %*"`.
- Run the Android emulator.
- In `<work-dir>`, do
  `ant install`
  This will compile `JEExample.java` as well as convert the resulting class files to dex files. This also creates `<work-dir>/bin/JEExample-debug.apk` and starts this application on the emulator.

## Run the test

- Create the JE environment directory by doing:
  `adb shell mkdir /data/je`
  You can remove the JE Environment files by doing:
  `adb shell rm /data/je/*`
- Run the JEExample application in the emulator by clicking on the Home icon, then the Applications folder, then the JEExample icon. A screen titled "JEExample" should appear with a TextEdit box, a "Put Data" button, and a "Get Data" button.
- Put some key/data pairs into the JE database by entering (e.g.)
  `k1/data1`
  and pressing the "Put Data" button.
- Retrieve ("get") key/data pairs from the JE database by entering (e.g.)
  `k1`
  and pressing the "Get Data" button.

## Source Code

- com.sleepycat.je.xa package.

      XAException.java

      package com.sleepycat.je.xa;

      public class XAException extends Exception {

          public static final int XA_RBBASE = 0;
          public static final int XA_RBROLLBACK = 0;
          public static final int XAER_INVAL = 0;
          public static final int XAER_NOTA = 0;
          public static final int XAER_DUPID = 0;
          public static final int XA_RBPROTO = 0;
          public static final int XAER_PROTO = 0;
          public XAException() {}
          public XAException(String s) {}
          public XAException(int e) {}
      }

      XAResource.java

      package com.sleepycat.je.xa;

      public interface XAResource {
          public static final int TMENDRSCAN = 0;
          public static final int TMFAIL = 0;
          public static final int TMJOIN = 0;
          public static final int TMNOFLAGS = 0;
          public static final int TMONEPHASE = 0;
          public static final int TMRESUME = 0;
          public static final int TMSTARTRSCAN = 0;
          public static final int TMSUCCESS = 0;
          public static final int TMSUSPEND = 0;
          public static final int XA_RDONLY = 0;
          public static final int XA_OK = 0;
          boolean setTransactionTimeout(int a)
              throws XAException;
          void start(Xid a, int b)
              throws XAException;
          void end(Xid a, int b)
              throws XAException;
          int prepare(Xid a)
              throws XAException;
          void commit(Xid a, boolean b)
              throws XAException;
          void forget(Xid a)
              throws XAException;
          Xid[] recover(int a)
              throws XAException;
          void rollback(Xid a)
              throws XAException;
          int getTransactionTimeout()
              throws XAException;
          boolean isSameRM(XAResource a)
              throws XAException;
      }

      Xid.java

      package com.sleepycat.je.xa;

      public interface Xid {
          int getFormatId();
          byte[] getGlobalTransactionId();
          byte[] getBranchQualifier();
      }

- JEExample.java

      package com.sleepycat.je;

      import android.app.Activity;
      import android.app.AlertDialog;
      import android.content.DialogInterface;
      import android.util.Log;
      import android.os.Bundle;
      import android.view.View;
      import android.widget.Button;
      import android.widget.EditText;
      import android.widget.TextView;

      import java.io.File;

      import com.sleepycat.je.Database;
      import com.sleepycat.je.DatabaseConfig;
      import com.sleepycat.je.DatabaseEntry;
      import com.sleepycat.je.DatabaseException;
      import com.sleepycat.je.Environment;
      import com.sleepycat.je.EnvironmentConfig;
      import com.sleepycat.je.OperationStatus;
      import com.sleepycat.je.Transaction;

      public class JEExample extends Activity {

          @Override
          public void onCreate(Bundle icicle) {
              super.onCreate(icicle);

              try {
                  final File envDir = new File("/data/je");
                  final EnvironmentConfig envConfig = new EnvironmentConfig();
                  envConfig.setTransactional(true);
                  envConfig.setAllowCreate(true);
                  final Environment env = new Environment(envDir, envConfig);
                  final DatabaseConfig dbConfig = new DatabaseConfig();
                  dbConfig.setTransactional(true);
                  dbConfig.setAllowCreate(true);
                  dbConfig.setSortedDuplicates(true);
                  final Database db = env.openDatabase(null, "exampledb", dbConfig);

                  setContentView(R.layout.main);
                  final Button button1 = (Button) findViewById(R.id.do_put);
                  button1.setOnClickListener(new Button.OnClickListener() {
                      public void onClick(View v) {

                          final EditText editText =
                              (EditText) findViewById(R.id.entry);
                          final String keyData = editText.getText().toString();
                          final int idx = keyData.indexOf("/");
                          String key = null;
                          String data = null;
                          String result = null;
                          if (idx < 0) {
                              result = "enter key/data to put";
                          } else {
                              key = keyData.substring(0, idx);
                              data = keyData.substring(idx + 1);
                              result = key + "/" + data;
                              final DatabaseEntry keyEntry =
                                  new DatabaseEntry(key.getBytes());
                              final DatabaseEntry dataEntry =
                                  new DatabaseEntry(data.getBytes());

                              try {
                                  final Transaction txn =
                                      env.beginTransaction(null, null);
                                  final OperationStatus res =
                                      db.put(txn, keyEntry, dataEntry);
                                  if (res != OperationStatus.SUCCESS) {
                                      result = "Error: " + res.toString();
                                  }
                                  txn.commit();
                              } catch (DatabaseException DE) {
                                  result = "Caught exception: " + DE.toString();
                              }
                          }
                          Log.d("JE", "did put of: " + result);

                          if (result.contains("Caught exception:")) {
                          	new AlertDialog.Builder(JEExample.this).
                          	    setTitle("Put Data").setMessage(result).
                          	    setPositiveButton("Quit", new DialogInterface.OnClickListener() {
                          		    public void onClick(DialogInterface dialog, int whichButton) {
                          		    }
                          		}).show();
                          } else {
                          	new AlertDialog.Builder(JEExample.this).
                      	        setTitle("Put Data").setMessage("You put the key/data pair: " + result).
                      	        setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
                      		        public void onClick(DialogInterface dialog, int whichButton) {
                      		        }
                      		    }).show();
                          }
                      }
                  });

                  final Button button2 = (Button) findViewById(R.id.do_get);
                  button2.setOnClickListener(new Button.OnClickListener() {
                      public void onClick(View v) {

                          final EditText editText =
                              (EditText) findViewById(R.id.entry);
                          final String key = editText.getText().toString();
                          final DatabaseEntry keyEntry =
                              new DatabaseEntry(key.getBytes());
                          final DatabaseEntry dataEntry = new DatabaseEntry();
                          String result = null;
                          try {
                              final Transaction txn =
                                  env.beginTransaction(null, null);
                              final OperationStatus res =
                                  db.get(txn, keyEntry, dataEntry, null);
                              if (res != OperationStatus.SUCCESS) {
                                  result = "Error: " + res.toString();
                              } else {
                                  result = new String(dataEntry.getData());
                              }
                              txn.commit();
                          } catch (DatabaseException DE) {
                              result = "Caught exception: " + DE.toString();
                          }
                          Log.d("JE", "did get of: " + result);
                          if (result.contains("Caught exception:")) {
                          	new AlertDialog.Builder(JEExample.this).
                      	        setTitle("Get Data").setMessage(result).
                      	        setPositiveButton("Quit", new DialogInterface.OnClickListener() {
                      		        public void onClick(DialogInterface dialog, int whichButton) {
                      		        }
                      		    }).show();
                          } else {
                          	new AlertDialog.Builder(JEExample.this).
                      	        setTitle("Get Data").setMessage("Get result: " + result).
                      	        setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
                      		        public void onClick(DialogInterface dialog, int whichButton) {
                      		        }
                      		    }).show();
                          }
                      }
                  });
              } catch (Exception DE) {
                  TextView tv = new TextView(this);
                  tv.setText("blew chunks " + DE);
                  setContentView(tv);
              }
          }
      }

- res/layout/main.xml

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          >

        <TextView android:id="@+id/label"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="JEExample"
          />

        <EditText android:id="@+id/entry"
                  android:layout_width="fill_parent"
                  android:layout_height="wrap_content"
                  android:background="@android:drawable/editbox_background"
                  android:layout_below="@id/label"
          />

        <Button android:id="@+id/do_put"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/button_put"
          />

        <Button android:id="@+id/do_get"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/button_get"
          />
      </LinearLayout>

- res/values/strings.xml

      <?xml version="1.0" encoding="utf-8"?>
      <resources>
          <string name="app_name">JEExample</string>
          <string name="button_put">Put Data</string>
          <string name="button_get">Get Data</string>
      </resources>

Please report bugs to the Berkeley DB Java Edition OTN forum.