The Ledger API
The ledger API is a lower-level API for BookKeeper that enables you to interact with ledgers directly.
The Java ledger API client
To get started with the Java client for BookKeeper, install the bookkeeper-server library as a dependency in your Java application.
For a more in-depth tutorial that involves a real use case for BookKeeper, see the Example application guide.
Installation
The BookKeeper Java client library is available via Maven Central and can be installed using Maven, Gradle, and other build tools.
Maven
If you're using Maven, add this to your pom.xml build configuration file:
<!-- in your <properties> block -->
<bookkeeper.version>4.17.3</bookkeeper.version>
<!-- in your <dependencies> block -->
<dependency>
<groupId>org.apache.bookkeeper</groupId>
<artifactId>bookkeeper-server</artifactId>
<version>${bookkeeper.version}</version>
</dependency>
BookKeeper uses google protobuf and guava libraries a lot. If your application might include different versions of protobuf or guava introduced by other dependencies, you can choose to use the shaded library, which relocate classes of protobuf and guava into a different namespace to avoid conflicts.
<!-- in your <properties> block -->
<bookkeeper.version>4.17.3</bookkeeper.version>
<!-- in your <dependencies> block -->
<dependency>
<groupId>org.apache.bookkeeper</groupId>
<artifactId>bookkeeper-server-shaded</artifactId>
<version>${bookkeeper.version}</version>
</dependency>
Gradle
If you're using Gradle, add this to your build.gradle build configuration file:
dependencies {
compile group: 'org.apache.bookkeeper', name: 'bookkeeper-server', version: '4.17.3'
}
// Alternatively:
dependencies {
compile 'org.apache.bookkeeper:bookkeeper-server:4.17.3'
}
Similarly as using maven, you can also configure to use the shaded jars.
// use the `bookkeeper-server-shaded` jar
dependencies {
compile 'org.apache.bookkeeper:bookkeeper-server-shaded:4.17.3'
}
Connection string
When interacting with BookKeeper using the Java client, you need to provide your client with a connection string, for which you have three options:
- Provide your entire ZooKeeper connection string, for example
zk1:2181,zk2:2181,zk3:2181. - Provide a host and port for one node in your ZooKeeper cluster, for example
zk1:2181. In general, it's better to provide a full connection string (in case the ZooKeeper node you attempt to connect to is down). - If your ZooKeeper cluster can be discovered via DNS, you can provide the DNS name, for example
my-zookeeper-cluster.com.
Creating a new client
In order to create a new BookKeeper client object, you need to pass in a connection string. Here is an example client object using a ZooKeeper connection string:
try {
String connectionString = "127.0.0.1:2181"; // For a single-node, local ZooKeeper cluster
BookKeeper bkClient = new BookKeeper(connectionString);
} catch (InterruptedException | IOException | KeeperException e) {
e.printStackTrace();
}
If you're running BookKeeper locally, using the
localbookiecommand, use"127.0.0.1:2181"for your connection string, as in the example above.
There are, however, other ways that you can create a client object:
-
By passing in a
ClientConfigurationobject. Here's an example:ClientConfiguration config = new ClientConfiguration();
config.setZkServers(zkConnectionString);
config.setAddEntryTimeout(2000);
BookKeeper bkClient = new BookKeeper(config); -
By specifying a
ClientConfigurationand aZooKeeperclient object:ClientConfiguration config = new ClientConfiguration();
config.setAddEntryTimeout(5000);
ZooKeeper zkClient = new ZooKeeper(/* client args */);
BookKeeper bkClient = new BookKeeper(config, zkClient); -
Using the
forConfigmethod:BookKeeper bkClient = BookKeeper.forConfig(conf).build();
Creating ledgers
The easiest way to create a ledger using the Java client is via the createLedger method, which creates a new ledger synchronously and returns a LedgerHandle. You must specify at least a DigestType and a password.
Here's an example:
byte[] password = "some-password".getBytes();
LedgerHandle handle = bkClient.createLedger(BookKeeper.DigestType.MAC, password);
You can also create ledgers asynchronously
Create ledgers asynchronously
class LedgerCreationCallback implements AsyncCallback.CreateCallback {
public void createComplete(int returnCode, LedgerHandle handle, Object ctx) {
System.out.println("Ledger successfully created");
}
}
client.asyncCreateLedger(
3,
2,
BookKeeper.DigestType.MAC,
password,
new LedgerCreationCallback(),
"some context"
);
Adding entries to ledgers
long entryId = ledger.addEntry("Some entry data".getBytes());
Add entries asynchronously
Reading entries from ledgers
Enumerator<LedgerEntry> entries = handle.readEntries(1, 99);
To read all possible entries from the ledger:
Enumerator<LedgerEntry> entries =
handle.readEntries(0, handle.getLastAddConfirmed());
while (entries.hasNextElement()) {
LedgerEntry entry = entries.nextElement();
System.out.println("Successfully read entry " + entry.getId());
}