Skip to main content

Schema Support

In larger ZooKeeper applications you will end with many paths to ZNodes that have specific meanings and uses. E.g. "/myapp/clients/clusters/instances" or "/myapp/writers/locks". These paths can become unwieldy and difficult to reason about. Ideally, you should have a simple way to commonly refer to these paths, a way to validate how they are used, and a way to document what they are used for.

Curator provides a mechanism to:

  • Document your ZooKeeper paths
  • Validate operations on ZooKeeper paths
  • Map a simple string to a ZooKeeper path

When a Curator operation violates a schema, SchemaViolation is thrown.

Schema and SchemaSet

The basic specification is the Schema class:

FieldTypeRequiredDescription
nameStringYA unique name for this schema
pathStringYA full path to a ZNode or a regex pattern to a ZNode
documentationStringNUser displayable documentation for this schema
schemaValidatorSchemaValidatorNsee below
ephemeralcan/must/cannotNWhether the schema allows for ephemerals at the path
sequentialcan/must/cannotNWhether the schema allows for sequentials at the path
watchedcan/must/cannotNWhether the schema allows for watchers at the path
canBeDeletedtrue/falseNWhether the schema allows the path to be deleted
metadatamapNAny fields-to-values you want

All the Schema instances are combined into a SchemaSet and this can be set in the CuratorFrameworkFactory when creating a CuratorFramework instance. Schemas in a SchemaSet are applied in the following order:

  1. Exact match on full path (i.e. nonregex)
  2. Match on the first regex path, searched in the order given to the SchemaSet constructor

SchemaValidator

SchemaValidators are used to optionally validate a ZNode operation when the node is created or modified. It is a functor of the form:

boolean isValid(Schema schema, String path, byte[] data, List<ACL> acl);

Getting ZNode paths/schemas by name

Use SchemaSets to access ZNode paths by a simple name. E.g.,

CuratorFramework client = ...;
String path = SchemaSet.getNamedPath(client, "locks");
client.create().forPath(path);

Loading JSON Schema from a file/stream

An optional utility is provided to load SchemaSets from a JSON file or stream: SchemaSetLoader.

note

To avoid adding a new dependency to Curator, the Jackson library has been used with "provided" scope. You will need to add a dependency to jackson-core and jackson-databind to your project.

The JSON stream should be an array of schemas:

[
{
"name": "name", // required - name of the schema
"path": "path or pattern", // required - full path or regex pattern
"isRegex": true/false, // optional - true if path is a regular expression - default is false
"schemaValidator": "name", // optional - name of a schema validator - default is no validator
"documentation": "docs", // optional - user displayable docs - default is ""
"ephemeral": "allowance", // optional - "can", "must" or "cannot" - default is "can"
"sequential": "allowance", // optional - "can", "must" or "cannot" - default is "can"
"watched": "allowance", // optional - "can", "must" or "cannot" - default is "can"
"canBeDeleted": true/false, // optional - true if ZNode at path can be deleted - default is true
"metadata": { // optional - any fields -> values that you want
"field1": "value1",
"field2": "value2"
}
}
]

Examples

Example 1

[
{
"name": "test",
"path": "/a/b/c",
"ephemeral": "must",
"sequential": "cannot",
"metadata": {
"origin": "outside",
"type": "large"
}
}
]
  • This SchemaSet has only 1 schema
  • The schema applies only to the path "/a/b/c"
  • The ZNode "/a/b/c" must be ephemeral, cannot be sequential, can be watched, and can be deleted

Example 2

[
{
"name": "test",
"path": "/a/b/c",
"ephemeral": "must",
"sequential": "cannot"
},

{
"name": "test2",
"path": "/a/.*",
"isRegex": true,
"schemaValidator": "test",
"ephemeral": "cannot",
"canBeDeleted": false
}
]
  • This SchemaSet has 2 schemas
  • The first schema applies only to the path "/a/b/c"
  • The ZNode "/a/b/c" must be ephemeral, cannot be sequential, can be watched, and can be deleted
  • The second schema is regex and applies to any path that matches the expression "/a/.*"
  • The ZNodes that match "/a/.*" cannot be ephemeral, can be sequential, can be watched, and cannot be deleted
  • The second schema also has a schema validator. The schema validator named "test" (configured when constructing the SchemaSetLoader) will be called to validate ZNodes that match "/a/.*".