Low-level API for Apache ZooKeeper client library providing connection management, retry policies, and basic ZooKeeper operations
—
Comprehensive path manipulation utilities for ZooKeeper node operations, including path validation, tree operations, and node management. These utilities provide safe and efficient methods for working with ZooKeeper's hierarchical namespace.
Central utility class providing comprehensive ZooKeeper path manipulation and tree operation methods.
/**
* Utility class for ZooKeeper path operations and tree management
*/
public class ZKPaths {
/** ZooKeeper path separator constant */
public static final String PATH_SEPARATOR = "/";
/**
* Safely construct a path by joining parent and child components
* @param parent Parent path (can be null or empty for root)
* @param child Child node name
* @return Properly formatted ZooKeeper path
*/
public static String makePath(String parent, String child);
/**
* Safely construct a path by joining parent with multiple child components
* @param parent Parent path (can be null or empty for root)
* @param firstChild First child node name
* @param restChildren Additional child node names
* @return Properly formatted ZooKeeper path
*/
public static String makePath(String parent, String firstChild, String... restChildren);
/**
* Extract the node name from a full path
* @param path Full ZooKeeper path
* @return Node name (last component of path)
*/
public static String getNodeFromPath(String path);
/**
* Split a path into parent path and node name
* @param path Full ZooKeeper path
* @return PathAndNode object containing parent and node
*/
public static PathAndNode getPathAndNode(String path);
/**
* Split a path into individual components
* @param path ZooKeeper path to split
* @return List of path components (excluding empty root)
*/
public static List<String> split(String path);
/**
* Create all parent directories for a path (like mkdir -p)
* @param zookeeper ZooKeeper client instance
* @param path Path to create (parents will be created as needed)
* @throws KeeperException if ZooKeeper operation fails
* @throws InterruptedException if operation is interrupted
*/
public static void mkdirs(ZooKeeper zookeeper, String path) throws KeeperException, InterruptedException;
/**
* Create directories with control over creating the last node
* @param zookeeper ZooKeeper client instance
* @param path Path to create
* @param makeLastNode Whether to create the final path component
* @throws KeeperException if ZooKeeper operation fails
* @throws InterruptedException if operation is interrupted
*/
public static void mkdirs(ZooKeeper zookeeper, String path, boolean makeLastNode) throws KeeperException, InterruptedException;
/**
* Create directories with custom ACL provider
* @param zookeeper ZooKeeper client instance
* @param path Path to create
* @param makeLastNode Whether to create the final path component
* @param aclProvider ACL provider for created nodes
* @throws KeeperException if ZooKeeper operation fails
* @throws InterruptedException if operation is interrupted
*/
public static void mkdirs(ZooKeeper zookeeper, String path, boolean makeLastNode, InternalACLProvider aclProvider) throws KeeperException, InterruptedException;
/**
* Create directories with container support control
* @param zookeeper ZooKeeper client instance
* @param path Path to create
* @param makeLastNode Whether to create the final path component
* @param aclProvider ACL provider for created nodes
* @param asContainers Whether to create container nodes (if supported)
* @throws KeeperException if ZooKeeper operation fails
* @throws InterruptedException if operation is interrupted
*/
public static void mkdirs(ZooKeeper zookeeper, String path, boolean makeLastNode, InternalACLProvider aclProvider, boolean asContainers) throws KeeperException, InterruptedException;
/**
* Delete all children of a node, optionally deleting the node itself
* @param zookeeper ZooKeeper client instance
* @param path Path whose children should be deleted
* @param deleteSelf Whether to delete the path itself after children
* @throws KeeperException if ZooKeeper operation fails
* @throws InterruptedException if operation is interrupted
*/
public static void deleteChildren(ZooKeeper zookeeper, String path, boolean deleteSelf) throws KeeperException, InterruptedException;
/**
* Get sorted list of child nodes
* @param zookeeper ZooKeeper client instance
* @param path Parent path
* @return Sorted list of child node names
* @throws KeeperException if ZooKeeper operation fails
* @throws InterruptedException if operation is interrupted
*/
public static List<String> getSortedChildren(ZooKeeper zookeeper, String path) throws KeeperException, InterruptedException;
/**
* Get the appropriate CreateMode for container nodes (ZK 3.5+)
* @return CreateMode.CONTAINER if supported, otherwise CreateMode.PERSISTENT
*/
public static CreateMode getContainerCreateMode();
/**
* Check if ZooKeeper version supports container nodes
* @return true if container nodes are supported
*/
public static boolean hasContainerSupport();
/**
* Fix path for namespace by prepending namespace if needed
* @param namespace Namespace to apply (can be null)
* @param path Path to fix
* @return Path with namespace applied
*/
public static String fixForNamespace(String namespace, String path);
/**
* Fix path for namespace with sequential node support
* @param namespace Namespace to apply (can be null)
* @param path Path to fix
* @param isSequential Whether path will be used for sequential nodes
* @return Path with namespace applied
*/
public static String fixForNamespace(String namespace, String path, boolean isSequential);
/**
* Extract sequential suffix from a sequential node path
* @param path Path with potential sequential suffix
* @return Sequential suffix string, or null if not sequential
*/
public static String extractSequentialSuffix(String path);
}Usage Examples:
import org.apache.curator.utils.ZKPaths;
import org.apache.zookeeper.ZooKeeper;
// Path construction
String fullPath = ZKPaths.makePath("/app", "config"); // "/app/config"
String rootPath = ZKPaths.makePath(null, "root"); // "/root"
String nestedPath = ZKPaths.makePath("/a/b", "c"); // "/a/b/c"
// Path parsing
String nodeName = ZKPaths.getNodeFromPath("/app/config/database"); // "database"
ZKPaths.PathAndNode pathAndNode = ZKPaths.getPathAndNode("/app/config");
// pathAndNode.getPath() returns "/app", pathAndNode.getNode() returns "config"
List<String> components = ZKPaths.split("/app/config/database");
// Returns ["app", "config", "database"]
// Tree operations with ZooKeeper client
ZooKeeper zk = client.getZooKeeper();
// Create directory structure
ZKPaths.mkdirs(zk, "/app/config/database"); // Creates /app, /app/config, /app/config/database
// Clean up children
ZKPaths.deleteChildren(zk, "/app/config", false); // Delete children but keep /app/config
ZKPaths.deleteChildren(zk, "/temp", true); // Delete /temp and all children
// Get sorted children
List<String> children = ZKPaths.getSortedChildren(zk, "/app");
// Returns alphabetically sorted list of child node namesContainer class for holding a path split into parent directory and node name components.
/**
* Container for path and node name pairs
*/
public static class ZKPaths.PathAndNode {
/**
* Get the parent path component
* @return Parent path (null for root-level nodes)
*/
public String getPath();
/**
* Get the node name component
* @return Node name (last component of original path)
*/
public String getNode();
}Usage Examples:
// Split path into components
ZKPaths.PathAndNode pathAndNode = ZKPaths.getPathAndNode("/app/config/database");
String parentPath = pathAndNode.getPath(); // "/app/config"
String nodeName = pathAndNode.getNode(); // "database"
// Handle root-level paths
ZKPaths.PathAndNode rootNode = ZKPaths.getPathAndNode("/app");
String rootParent = rootNode.getPath(); // null (no parent)
String rootName = rootNode.getNode(); // "app"Path validation utilities ensuring ZooKeeper path compliance and safety.
/**
* Utility class for ZooKeeper path validation
*/
public class PathUtils {
/**
* Validate a ZooKeeper path and return normalized version
* @param path Path to validate
* @return Validated and normalized path
* @throws IllegalArgumentException if path is invalid
*/
public static String validatePath(String path) throws IllegalArgumentException;
/**
* Validate a ZooKeeper path with sequential node support
* @param path Path to validate
* @param isSequential Whether path will be used for sequential nodes
* @throws IllegalArgumentException if path is invalid
*/
public static void validatePath(String path, boolean isSequential) throws IllegalArgumentException;
}Usage Examples:
import org.apache.curator.utils.PathUtils;
try {
// Validate and normalize paths
String validPath = PathUtils.validatePath("/app/config"); // OK
String normalizedPath = PathUtils.validatePath("//app///config"); // Returns "/app/config"
// Validate for sequential nodes
PathUtils.validatePath("/app/counters/counter-", true); // OK for sequential
// These would throw IllegalArgumentException:
// PathUtils.validatePath(""); // Empty path
// PathUtils.validatePath("no-slash"); // Must start with /
// PathUtils.validatePath("/app/"); // Cannot end with / (except root)
} catch (IllegalArgumentException e) {
System.err.println("Invalid path: " + e.getMessage());
}Legacy utility for ensuring path existence - superseded by ZKPaths.mkdirs().
/**
* @deprecated Use ZKPaths.mkdirs() instead
* Utility to ensure ZooKeeper path existence
*/
@Deprecated
public class EnsurePath {
/**
* Create EnsurePath instance for a specific path
* @param path Path to ensure exists
*/
public EnsurePath(String path);
/**
* Ensure the path exists, creating parent directories as needed
* @param client CuratorZookeeperClient instance
* @throws Exception if path creation fails
*/
public void ensure(CuratorZookeeperClient client) throws Exception;
/**
* Create EnsurePath instance excluding the last path component
* @return EnsurePath for parent directory only
*/
public EnsurePath excludingLast();
}// Always use ZKPaths.makePath() for path construction
String configPath = ZKPaths.makePath("/app", "config");
String dbConfigPath = ZKPaths.makePath(configPath, "database");
String tablePath = ZKPaths.makePath(dbConfigPath, "users");
// Avoid manual string concatenation:
// String badPath = "/app" + "/" + "config"; // DON'T DO THIS// Create entire directory tree in one call
ZKPaths.mkdirs(zookeeper, "/app/config/database/connection");
// This creates all intermediate paths:
// /app
// /app/config
// /app/config/database
// /app/config/database/connection// Clean up temporary directories
String tempPath = "/temp/processing/" + UUID.randomUUID();
try {
// Create and use temp directory
ZKPaths.mkdirs(zookeeper, tempPath);
// ... do work ...
} finally {
// Clean up: delete temp directory and all contents
ZKPaths.deleteChildren(zookeeper, tempPath, true);
}// Use container nodes when available for automatic cleanup
CreateMode containerMode = ZKPaths.getContainerCreateMode();
if (ZKPaths.hasContainerSupport()) {
// ZooKeeper 3.5+ with container support
zookeeper.create("/app/locks", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, containerMode);
} else {
// Fallback for older ZooKeeper versions
zookeeper.create("/app/locks", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}Utility for safely closing resources, providing functionality removed from Guava v16.0.
/**
* Utility class for safely closing resources without throwing exceptions
*/
public class CloseableUtils {
/**
* Close a resource quietly, swallowing any IOException
* @param closeable Resource to close (can be null)
*/
public static void closeQuietly(Closeable closeable);
}Thread management and factory utilities for creating properly configured threads.
/**
* Utility class for thread management and factory creation
*/
public class ThreadUtils {
/**
* Check if exception represents an interruption and restore thread state
* @param e Exception to check
* @return true if exception was InterruptedException
*/
public static boolean checkInterrupted(Throwable e);
/**
* Create single thread executor with named threads
* @param processName Name prefix for threads
* @return ExecutorService with single thread
*/
public static ExecutorService newSingleThreadExecutor(String processName);
/**
* Create fixed thread pool with named threads
* @param qty Number of threads in pool
* @param processName Name prefix for threads
* @return ExecutorService with fixed thread pool
*/
public static ExecutorService newFixedThreadPool(int qty, String processName);
/**
* Create single thread scheduled executor with named threads
* @param processName Name prefix for threads
* @return ScheduledExecutorService with single thread
*/
public static ScheduledExecutorService newSingleThreadScheduledExecutor(String processName);
/**
* Create scheduled thread pool with named threads
* @param qty Number of threads in pool
* @param processName Name prefix for threads
* @return ScheduledExecutorService with thread pool
*/
public static ScheduledExecutorService newFixedThreadScheduledPool(int qty, String processName);
/**
* Create thread factory with Curator naming conventions
* @param processName Process name for thread naming
* @return ThreadFactory for creating named daemon threads
*/
public static ThreadFactory newThreadFactory(String processName);
/**
* Create generic thread factory
* @param processName Process name for thread naming
* @return ThreadFactory for creating named daemon threads
*/
public static ThreadFactory newGenericThreadFactory(String processName);
/**
* Generate process name from class
* @param clazz Class to generate name from
* @return Simple class name for process naming
*/
public static String getProcessName(Class<?> clazz);
}Utility for collecting and managing multiple exceptions during batch operations.
/**
* Utility for accumulating exceptions from multiple operations
*/
public class ExceptionAccumulator {
/**
* Create new exception accumulator
*/
public ExceptionAccumulator();
/**
* Add exception to accumulator
* @param e Exception to add (null exceptions are ignored)
*/
public void add(Throwable e);
/**
* Get accumulated exception, if any
* @return Exception combining all accumulated exceptions, or null if none
*/
public Exception getCombinedException();
}Managed executor service that implements Closeable for proper resource management.
/**
* ExecutorService wrapper that implements Closeable for automatic resource management
*/
public class CloseableExecutorService implements Closeable {
/**
* Create closeable executor service
* @param executorService Underlying executor service to wrap
*/
public CloseableExecutorService(ExecutorService executorService);
/**
* Get the underlying executor service
* @return Wrapped ExecutorService instance
*/
public ExecutorService getExecutorService();
/**
* Close executor service, shutting down gracefully
*/
@Override
public void close();
}Managed scheduled executor service extending CloseableExecutorService.
/**
* ScheduledExecutorService wrapper that implements Closeable for automatic resource management
*/
public class CloseableScheduledExecutorService extends CloseableExecutorService {
/**
* Create closeable scheduled executor service
* @param scheduledExecutorService Underlying scheduled executor to wrap
*/
public CloseableScheduledExecutorService(ScheduledExecutorService scheduledExecutorService);
/**
* Get the underlying scheduled executor service
* @return Wrapped ScheduledExecutorService instance
*/
public ScheduledExecutorService getScheduledExecutorService();
}String fullPath = "/app/config/database/connection";
// Extract components
String nodeName = ZKPaths.getNodeFromPath(fullPath); // "connection"
List<String> components = ZKPaths.split(fullPath); // ["app", "config", "database", "connection"]
// Split into parent and child
ZKPaths.PathAndNode pathAndNode = ZKPaths.getPathAndNode(fullPath);
String parentPath = pathAndNode.getPath(); // "/app/config/database"
String childName = pathAndNode.getNode(); // "connection"
// Validate before use
try {
PathUtils.validatePath(fullPath);
// Path is valid, safe to use
} catch (IllegalArgumentException e) {
// Handle invalid path
}Install with Tessl CLI
npx tessl i tessl/maven-org-apache-curator--curator-client