When programming Zookeeper in Java, Zookeeper client or Curator is used.
- Zookeeper client is embedded in Zookeeper server library
- Curator is a wrapper for Zookeeper client, which enables easier programming
There are something to consider when programming Zookeeper. The first point is connecting to Zookeeper.
Let’s suppose that you make a program which connects to Zookeeper and check if a znode exists.
Zookeeper client connection example – incorrect version
import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; public class ZookeeperConnectionTest1 { public static void main(String[] args) throws Exception{ String zooConnStr = "127.0.0.1:2181"; ZooKeeper zooKeeper = new ZooKeeper(zooConnStr, 60000, null); Stat stat = zooKeeper.exists("/testNode", null); if(stat == null) { System.out.println("testNode does not exist"); } } }
Above source seems to be working. (It might succeed) When creating ZooKeeper object, it connects to Zookeeper server. But it’s asynchronous. Therefore, at exists() step, the connection might not have been established. (In that case, exception occurs)
Zookeeper client connection example – fixed version
import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher.Event.KeeperState; public class ZookeeperConnectionTest2 implements Watcher{ private ZooKeeper zooKeeper; public static void main(String[] args) throws Exception{ String zooConnStr = "127.0.0.1:2181"; ZookeeperConnectionTest2 test = new ZookeeperConnectionTest2(); test.zooKeeper = new ZooKeeper(zooConnStr, 60000, test); synchronized(test) { test.wait(); } } @Override public void process(WatchedEvent event) { try { if(event.getState().equals(KeeperState.SyncConnected)) { Stat stat = this.zooKeeper.exists("/testNode", null); if(stat == null) { System.out.println("testNode does not exist"); } } } catch(Exception e) { e.printStackTrace(); } } }
Above source passes over a connection watcher when creating ZooKeeper object. At KeeperState.SyncConnected event, it processes the next step (to check a znode)
This works correctly. But it’s too lengthy. By with Apache Curator, you can simplify the source.
Curator connection example – final
import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.zookeeper.data.Stat; public class CuratorConnectionTest { public static void main(String[] args) throws Exception{ String zooConnStr = "127.0.0.1:2181"; CuratorFramework curator = CuratorFrameworkFactory.newClient(zooConnStr, new ExponentialBackoffRetry(100, 5)); curator.start(); curator.blockUntilConnected(); Stat stat = curator.checkExists().forPath("/testNode"); if(stat == null) { System.out.println("testNode does not exist"); } curator.close(); } }
CuratorFramework.blockUntilConnected() waits until the connection is established, which enables more simple code.