You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@curator.apache.org by ra...@apache.org on 2017/07/08 03:32:38 UTC
[6/6] curator git commit: Squashed commit of the following:
Squashed commit of the following:
commit 588dca66e6b60161bd66488edd2df211a8e2c3a6
Merge: 7e6551f3 8b28b120
Author: randgalt <ra...@apache.org>
Date: Fri Jul 7 22:28:15 2017 -0500
Merge branch 'master' into CURATOR-397
commit 7e6551f3fe3f1abbcf797739df20acc5a4e5be16
Author: randgalt <ra...@apache.org>
Date: Thu Jun 29 23:21:02 2017 -0500
completeChildrenAsZNodes() wasn't handling empty children listsw
commit 738c3617ee4887fefcf8dd5082b9b71c9f7021db
Author: randgalt <ra...@apache.org>
Date: Thu Jun 29 23:20:45 2017 -0500
no need to use EnsureContainers object
commit 09f9bc06accf7c42d3a5dcf3d92c20d706e56ea6
Author: randgalt <ra...@apache.org>
Date: Wed Jun 28 09:46:32 2017 -0500
Added asyncEnsureContainers
commit f7d410f8e11a840a36c7bb97313ed3fb7edf73ca
Author: randgalt <ra...@apache.org>
Date: Wed Jun 28 09:19:03 2017 -0500
It doesn't make sense for cached() to cache the root node. So, don't
commit b83bef9de0c980dfe21c85d0c08abb1bd75a06f5
Author: randgalt <ra...@apache.org>
Date: Wed Jun 28 00:07:29 2017 -0500
oops - orSetData() was returning null
commit 318bed14f050dd579f76a768bcc7c3125d832049
Author: randgalt <ra...@apache.org>
Date: Tue Jun 27 00:10:24 2017 -0500
version of AsyncLocker.release() that ignores unheld locks
commit eeabe8b5136e8a46569ede9ea193f6e2f10153b1
Author: randgalt <ra...@apache.org>
Date: Wed Jun 14 16:10:35 2017 -0500
completeChildrenAsZNodes was treating zPaths as node names
commit f0bcd0476e30a876f7995d191d8811fadb1a201e
Author: randgalt <ra...@apache.org>
Date: Tue Jun 13 07:34:25 2017 -0500
Added lockAsyncIf to AsyncLock
commit fbf25adcf88b4198fdecd18a494b615c70bf763c
Author: randgalt <ra...@apache.org>
Date: Sat Jun 10 22:22:08 2017 -0500
Made the API of AsyncLocker cleaner
commit e943763f0d299b5e69e6a7f4e871024b7aa95503
Author: randgalt <ra...@apache.org>
Date: Sat Jun 10 20:46:19 2017 -0500
Added AsyncLocker
commit 93f11ed09e0cc6e9c6b80b1a88796d027f4f3d7a
Author: randgalt <ra...@apache.org>
Date: Sat Jun 10 19:52:15 2017 -0500
1. remove siblings added childrenAsZNodes
2. Add util to unwrap stages of ZNodes
commit 55df07e6ab5417943d485e88f7efa89df0b6e52d
Author: randgalt <ra...@apache.org>
Date: Fri Jun 9 23:55:20 2017 -0500
Added list()
commit f32a5fb4eeb63251ad769f54f7fee255c2bee61e
Author: randgalt <ra...@apache.org>
Date: Fri Jun 9 23:54:51 2017 -0500
Added '0' versions of Typed classes as a convenience so that the same idiom can be used even if there are no real type arguments
commit 523f0c8095fcde7033b9caa4c5423301085b0e16
Author: randgalt <ra...@apache.org>
Date: Fri Jun 9 18:01:58 2017 -0500
Added readThrough methods
commit 6428a9238892eba6e9f89551ed4602d2a7c5a04f
Author: randgalt <ra...@apache.org>
Date: Thu May 18 15:32:38 2017 +0200
Added a test for ACLs
commit 7a15af6ac5a58f1aba5dd6569d11b3a46fc45f9d
Author: randgalt <ra...@apache.org>
Date: Thu May 11 17:10:43 2017 +0200
CachedModeledFramework now handles unresolved paths where the final node is a parameter.
commit bb36c48ef420d48e345368d03e4696f22d394126
Author: randgalt <ra...@apache.org>
Date: Thu May 11 16:53:30 2017 +0200
updated doc for new auto-resolve behavior
commit 3338c05c997068c93fe4f889f4d0c1ee3fc3a776
Author: randgalt <ra...@apache.org>
Date: Thu May 11 16:03:53 2017 +0200
renamed at() to child()
commit 05cab2ec57208d3aa87202ff2d4f44146d5ba6b5
Author: randgalt <ra...@apache.org>
Date: Thu May 11 16:01:59 2017 +0200
Updated sub/pub test to use new resolving features so that at() isn't necessary
commit 6ea7221ab48dd0597e3b0f2ba4cdc33147ff7d4d
Author: randgalt <ra...@apache.org>
Date: Thu May 11 15:55:31 2017 +0200
1. Support partially resolved paths
2. Added method to get siblings
3. Auto resolve unresolved paths on set/update using the model being set/updated
commit 7ed263cc37d1c6eacfe676f7c78096d7086b9c59
Author: randgalt <ra...@apache.org>
Date: Thu May 11 14:04:57 2017 +0200
doc fixes
commit ed00d50f81cb224f9e2690aaa425adae6b0da0bd
Author: randgalt <ra...@apache.org>
Date: Thu May 11 13:52:51 2017 +0200
doc fixes
commit 6037c7b270b12dce273aa67939a78a4c00b5155f
Author: randgalt <ra...@apache.org>
Date: Thu May 11 12:53:49 2017 +0200
further refinement of previous change. Not all completion handlers should be in the cache's thread. But, allow for the default async to use it
commit 396d98a51495ec1c60156dcd0d6d553644e43689
Author: randgalt <ra...@apache.org>
Date: Wed May 10 23:38:07 2017 +0200
More tests, refactoring
commit 6485f1650e37e392e6122f8b13ff432ee0321666
Author: randgalt <ra...@apache.org>
Date: Wed May 10 19:23:00 2017 +0200
CachedModeledFrameworkImpl wasn't using executor in right way. Completions need to happen async not setting of the value. This required creating CachedStage which proxies all non-async methods to their async counterparts using the CachedModeledFrameworkImpl's executor
commit 80ca587e5e543568f06780ad8a8f874b94333218
Author: randgalt <ra...@apache.org>
Date: Wed May 10 16:09:55 2017 +0200
more tests
commit 49743a487e3c159029906bb334989e6f1c82f6a8
Author: randgalt <ra...@apache.org>
Date: Wed May 10 15:00:05 2017 +0200
Allow the {id} in ZPaths to use any value. This is very useful for making paths easier to read and debug. So, you can now do: '/root/{org}/employee/{emp id}'
commit cba43b342400461e0d4f0dfd894b69a8b1891438
Author: randgalt <ra...@apache.org>
Date: Wed May 10 14:09:12 2017 +0200
doc updates
commit 13e17cbbfe089554f47d64449eea1302b9b6bd19
Author: randgalt <ra...@apache.org>
Date: Wed May 10 12:43:59 2017 +0200
minor update
commit a7d2e058e4fedb00c408694f185b54ec4259bf94
Author: randgalt <ra...@apache.org>
Date: Wed May 10 11:58:04 2017 +0200
final versioned APIs and doc
commit beac06f136f26dd3dabb754dcb999876d614244b
Author: randgalt <ra...@apache.org>
Date: Tue May 9 23:16:54 2017 +0200
Added Versioned facade for easy management of models with versions
commit 23a1487984b576b878e3a88287f74d9381e5dec7
Author: randgalt <ra...@apache.org>
Date: Mon May 8 19:11:22 2017 +0200
Work on testing modeled schema
commit 555e1d4684e233e1caa910be67a4ff892253d9c7
Merge: e4a7e091 32a7755b
Author: randgalt <ra...@apache.org>
Date: Mon May 8 18:36:48 2017 +0200
Merge branch 'master' into CURATOR-397
commit e4a7e09172c7d9d14081233dec88690ecba6df9e
Author: randgalt <ra...@apache.org>
Date: Mon May 8 05:42:17 2017 +0200
some refactoring, refinement
commit c002e22e5a613cd8426c2e8b407ab06957908526
Author: randgalt <ra...@apache.org>
Date: Sun May 7 10:26:48 2017 +0200
removed ZPath 'resolving'. It doesn't add much value and muddies up the code
commit e95b885ebf0240e61d8de1c2644f8fb11cc2eca5
Author: randgalt <ra...@apache.org>
Date: Sun May 7 09:58:07 2017 +0200
Allow setting a version for orSetData()
commit 1110ab3bbc55748c053adcd909cc0d82be84309d
Author: randgalt <ra...@apache.org>
Date: Sun May 7 09:55:28 2017 +0200
Support setting the version when doing a create or set operation
commit c18783924af4b4c3f11d098165c85bf313f454c2
Author: randgalt <ra...@apache.org>
Date: Sun May 7 09:41:55 2017 +0200
Added variant to readAsZNode
commit fe0a88b3b7b9fccf9da022bc0a13e440b1f8435c
Author: randgalt <ra...@apache.org>
Date: Fri May 5 18:38:46 2017 -0400
better exception handling for serialization issues
commit f2370b7710b85850936f48404c6959d45ed03626
Author: randgalt <ra...@apache.org>
Date: Thu May 4 23:15:14 2017 -0500
1. Allow for an Executor service to be passed to the cache
2. CachedModeledFramework must complete the stages via a thread as the caller is expected async processing
commit 29b09ceb5d305419428760e07d572dd4b920cb74
Author: randgalt <ra...@apache.org>
Date: Thu May 4 15:35:05 2017 -0500
updated doc
commit 0bc3a9bd2e63bee511b0d78f584f862e875c8365
Author: randgalt <ra...@apache.org>
Date: Thu May 4 10:30:13 2017 -0500
some refactoring and doc
commit 1793675c136bf0ba89a33f9c5490e9ab5c7f0000
Author: randgalt <ra...@apache.org>
Date: Thu May 4 10:16:55 2017 -0500
Allow type model specs and typed clients to be created in "one shot". This made writing the sub-pub example simpler and easier to understand.
commit 5ac1a3314e372d8bd22ef7bba704b5621a1638b8
Author: randgalt <ra...@apache.org>
Date: Wed May 3 22:59:47 2017 -0500
finished docs for the pub-sub example
commit c97fae4ef6a06301f2a794df6e23411b303f8cf1
Merge: 71e28e1a f898959e
Author: randgalt <ra...@apache.org>
Date: Wed May 3 22:18:38 2017 -0500
Merge branch 'master' into CURATOR-397
commit 71e28e1a6b97171b3c54da0a4dc82564247e7f24
Author: randgalt <ra...@apache.org>
Date: Wed May 3 21:50:59 2017 -0500
starting read me for the sub-pub example
commit aa86931b9392b0d6f0cf6ff161afd82e9e3749f1
Author: randgalt <ra...@apache.org>
Date: Wed May 3 17:02:31 2017 -0500
added lots of doc
commit ea47c6c990c9dab9f91fa76c074d1a4251df2f9e
Author: randgalt <ra...@apache.org>
Date: Wed May 3 14:20:43 2017 -0500
Another big refactoring. NodeName only needs to be used internally by ZPath as all other resolve methods forward to it. This is cleaner.
commit c8a57d5387d9d34287b9e47808f47832e7758b3e
Merge: 37927efa d7d84c55
Author: randgalt <ra...@apache.org>
Date: Wed May 3 08:17:36 2017 -0500
Merge branch 'CURATOR-407' into CURATOR-397
commit 37927efa65ca755407f1032ef45cb46a11372184
Author: randgalt <ra...@apache.org>
Date: Wed May 3 07:42:13 2017 -0500
refactoring
commit 69f1829d0f63badb0e16ff0bd4d53f3c4a8df541
Author: randgalt <ra...@apache.org>
Date: Tue May 2 22:01:29 2017 -0500
added some doc
commit 0917e314b4cbb75e24e86c942b9d6501f84e8572
Author: randgalt <ra...@apache.org>
Date: Tue May 2 21:37:38 2017 -0500
pub-sub example is now working - needs copious docs
commit 713bf4670e494a74b083431929b86dbfe6bd7f75
Author: randgalt <ra...@apache.org>
Date: Tue May 2 20:45:23 2017 -0500
Work-in-progress. Using example sub/pub to flesh out issues and as an integration test. Working on bugs found
commit 1fcb63a5c7f29ddbfaedfdd18273ccabff21990e
Author: randgalt <ra...@apache.org>
Date: Tue May 2 17:32:38 2017 -0500
Working on strongly typed parameters plus an example that uses it
commit 26c7adbb04a8c20a7d04111253c82ddef28e4f26
Merge: ef9df2b7 ed3082ec
Author: randgalt <ra...@apache.org>
Date: Tue May 2 15:27:27 2017 -0500
Merge branch 'master' into CURATOR-397
commit ef9df2b7915ced99e227e2c2cd6f9ec12c7d7309
Author: randgalt <ra...@apache.org>
Date: Tue May 2 12:58:50 2017 -0500
wip
commit 56c6c85a2f26ef914574139e4c1c657b5a7573a5
Author: randgalt <ra...@apache.org>
Date: Tue May 2 01:11:13 2017 -0500
fixed startsWith
commit c3db1810a10e442626ee0c2f759a3f61da19375a
Author: randgalt <ra...@apache.org>
Date: Tue May 2 00:12:02 2017 -0500
Abstraction for creating ZPaths with strongly typed parameters
commit 6e21af2c565d95b7c281dd5211487a0682ab1a1a
Author: randgalt <ra...@apache.org>
Date: Mon May 1 23:07:58 2017 -0500
refactoring
commit 2cbbf999294181dbefeccebabd9c6de867142e2c
Author: randgalt <ra...@apache.org>
Date: Mon May 1 22:56:36 2017 -0500
Major rework of caching. Having the wrapped caches adds little value. Focus on the integrated caching in the modeled client instance
commit e40ed181655a83e705e6d74704d2fa2d1f93a7bc
Merge: 3d593105 35f5d274
Author: randgalt <ra...@apache.org>
Date: Mon May 1 14:55:59 2017 -0500
Merge branch 'CURATOR-3.0' into CURATOR-397
commit 3d593105d852ece596f7a55f312528ed23ccb69f
Author: randgalt <ra...@apache.org>
Date: Sun Apr 30 19:09:28 2017 -0500
more work on new caching apis
commit b58d1ccba2878c0b2f12928b4e957f536c24fed8
Author: randgalt <ra...@apache.org>
Date: Sun Apr 30 15:43:03 2017 -0500
resurrected TestCachedModeledCuratorFramework
commit 8418c5604cfeb186a3bd94e310a8001ab2bd5ee6
Author: randgalt <ra...@apache.org>
Date: Sun Apr 30 15:36:56 2017 -0500
licenses
commit 16fb7b18b77153578dd489d0e1509a11eff0c6f5
Author: randgalt <ra...@apache.org>
Date: Sun Apr 30 15:36:18 2017 -0500
Added new method of integrated caching. Needs testing, etc.
commit a4636098f6a6a679c06f337f981fd17d6b383218
Author: randgalt <ra...@apache.org>
Date: Sun Apr 30 14:12:18 2017 -0500
make parameter the empty string
commit 70936c8c479558f737d3e86914af58d3855aa964
Author: randgalt <ra...@apache.org>
Date: Sun Apr 30 14:08:28 2017 -0500
Added readChildren()
commit 50b054cc6af009c721e859398efcef5023f3cd3b
Author: randgalt <ra...@apache.org>
Date: Sun Apr 30 14:02:07 2017 -0500
removed integrated caching for now - it was getting too cumbersome. I have some other ideas
commit 11cb97036ebc8639bd22799d99569511deac098b
Author: randgalt <ra...@apache.org>
Date: Sat Apr 29 13:52:36 2017 -0500
more examples, added transactions
commit fa6bff6e5b34960fb8df37097561d4b02d47be24
Author: randgalt <ra...@apache.org>
Date: Fri Apr 28 12:11:08 2017 -0500
updated example
commit 38f6306ba109a61709e88b5acad233d0ba8dff26
Author: randgalt <ra...@apache.org>
Date: Wed Apr 26 17:05:39 2017 -0500
Added resolving methods to the model spec too
commit 52b334c30d82227ad7da3559976fa932fbbc5763
Author: randgalt <ra...@apache.org>
Date: Wed Apr 26 16:53:17 2017 -0500
added a resolving version that takes suppliers for parameters
commit 22fdb298db42a10ab74902b623e1696d22c2021f
Author: randgalt <ra...@apache.org>
Date: Wed Apr 26 16:10:59 2017 -0500
Added some tests/fixes
commit 5ebcfa32d7b00d5c2fc2eb4268a46fea2f98083d
Author: randgalt <ra...@apache.org>
Date: Wed Apr 26 15:45:10 2017 -0500
start of a mechanism to have variable/parameterized paths
commit 0cafc9199f3136f4f22703793bd56c73319d3161
Author: randgalt <ra...@apache.org>
Date: Tue Apr 25 14:29:35 2017 -0500
fixed typo bug with the cached values in ZPath - also made them more efficient
commit 3a3e6dd2d90fd2cf70507f247d1dcc1e59204721
Author: randgalt <ra...@apache.org>
Date: Tue Apr 25 13:30:11 2017 -0500
Created/abstracted CuratorModelSpec so that models can be specified independently of a CuratorFramework instance, etc. i.e. they can all be created at startup. The CuratorModelSpec also can generate a Schema object
commit 63225ba7562c48d9ac53bfaa50aa8ff0a790eb9c
Author: randgalt <ra...@apache.org>
Date: Tue Apr 25 12:33:30 2017 -0500
basics of write-through caching added. needs more work and testing
commit 6188fe6cee6b2a433f1c686adc660216a0aa1648
Author: randgalt <ra...@apache.org>
Date: Tue Apr 18 09:43:48 2017 -0500
Added getChildren
commit e512b5ee52bb9515493d0c077728acd6359caabd
Merge: 691f17d0 00ffe779
Author: randgalt <ra...@apache.org>
Date: Mon Apr 17 19:43:32 2017 -0500
Merge branch 'CURATOR-3.0' into CURATOR-397
commit 691f17d034647359a0d4e29f04f674cf589fb00b
Author: randgalt <ra...@apache.org>
Date: Sun Apr 9 17:01:03 2017 -0500
update example index
commit 7c8f3fb62f6c9c7042cf07e78df7c00427392278
Author: randgalt <ra...@apache.org>
Date: Sun Apr 9 16:58:58 2017 -0500
added more examples
commit 792aef2094e215edf77bf836b0f4dc43bb2cb232
Author: randgalt <ra...@apache.org>
Date: Sun Apr 9 14:27:15 2017 -0500
renamed ModeledCuratorFramework so it isn't so long
commit 34c594a8e6c3730f06bb159709265e0d50b389db
Author: randgalt <ra...@apache.org>
Date: Sun Apr 9 13:21:49 2017 -0500
fixed some typos and a bad link in the examples help
commit aadb72b62d6c781704f4ac977717c07a86a2694d
Author: randgalt <ra...@apache.org>
Date: Sun Apr 9 08:53:05 2017 -0500
cleaned up ModeledCacheEvent definition
commit bf43232bd9f30efa0482203f895e4adb207ab247
Author: randgalt <ra...@apache.org>
Date: Sun Apr 9 08:47:02 2017 -0500
doc
commit e0a27daef0b4dd363171b9ffde6eb4230cd8efd6
Author: randgalt <ra...@apache.org>
Date: Sun Apr 9 07:03:50 2017 -0500
Make ModeledNodeCache use the same listener as the others
commit 301e989268a81537645bbdc3c71af4166550abd1
Author: randgalt <ra...@apache.org>
Date: Sun Apr 9 06:40:34 2017 -0500
finished initial tests
commit d518417e5c1bd2d5e4cd1a31833a28eb9bc9bc0a
Author: randgalt <ra...@apache.org>
Date: Sat Apr 8 23:29:39 2017 -0500
tests
commit 45daa69bbf2a9ca0cfaa4c1ac20d53ce0314feb9
Author: randgalt <ra...@apache.org>
Date: Sat Apr 8 23:00:16 2017 -0500
ModeledDetails isn't needed
commit dd390b6e1b100add85dd9d340dfbae9873b84bd0
Author: randgalt <ra...@apache.org>
Date: Sat Apr 8 22:35:51 2017 -0500
doc
commit e8c68188d04df30eb91751f09360bb267fbe1c25
Author: randgalt <ra...@apache.org>
Date: Sat Apr 8 22:35:33 2017 -0500
doc
commit 019caeea6aba36e77c64073003e66d62aa60b761
Author: randgalt <ra...@apache.org>
Date: Sat Apr 8 22:14:06 2017 -0500
added tree cache wrapper
commit 4efc38f3d16d111c3a96c4eb28212b2cc8a08188
Author: randgalt <ra...@apache.org>
Date: Sat Apr 8 21:36:07 2017 -0500
wip on wrapping caches
commit 0f0db1c386471dd4babdf3f26b37b1d9056b3f7d
Author: randgalt <ra...@apache.org>
Date: Sat Apr 8 15:15:12 2017 -0500
more doc
commit 1dab81b5afedc4a0669312b386936baf7715c080
Author: randgalt <ra...@apache.org>
Date: Sat Apr 8 15:03:49 2017 -0500
adding docs
commit 8237fde0aabf7088b6ddcaf56a7fba1f8b1d3441
Author: randgalt <ra...@apache.org>
Date: Sat Apr 8 13:52:06 2017 -0500
WIP - strongly type DSL for Curator
Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/0f5d10da
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/0f5d10da
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/0f5d10da
Branch: refs/heads/master
Commit: 0f5d10da38626494ae4d0e3339a2a35f270b0edd
Parents: 8b28b12
Author: randgalt <ra...@apache.org>
Authored: Fri Jul 7 22:31:42 2017 -0500
Committer: randgalt <ra...@apache.org>
Committed: Fri Jul 7 22:31:42 2017 -0500
----------------------------------------------------------------------
curator-examples/pom.xml | 23 +-
.../src/main/java/async/AsyncExamples.java | 127 ++++++
.../src/main/java/modeled/ContainerType.java | 68 +++
.../java/modeled/ModeledCuratorExamples.java | 67 +++
.../java/modeled/ModeledCuratorExamplesAlt.java | 52 +++
.../src/main/java/modeled/PersonId.java | 70 +++
.../src/main/java/modeled/PersonModel.java | 120 +++++
.../src/main/java/modeled/PersonModelSpec.java | 46 ++
.../src/main/java/pubsub/Clients.java | 76 ++++
.../src/main/java/pubsub/Publisher.java | 146 ++++++
curator-examples/src/main/java/pubsub/README.md | 93 ++++
.../src/main/java/pubsub/SubPubTest.java | 220 +++++++++
.../src/main/java/pubsub/Subscriber.java | 84 ++++
.../java/pubsub/messages/LocationAvailable.java | 55 +++
.../main/java/pubsub/messages/UserCreated.java | 64 +++
.../src/main/java/pubsub/models/Group.java | 47 ++
.../src/main/java/pubsub/models/Instance.java | 76 ++++
.../main/java/pubsub/models/InstanceType.java | 27 ++
.../src/main/java/pubsub/models/Message.java | 67 +++
.../src/main/java/pubsub/models/Priority.java | 26 ++
.../src/main/resources/log4j.properties | 24 +
.../src/site/confluence/index.confluence | 5 +-
.../curator/framework/api/CreateBuilder.java | 10 +
.../framework/imps/CreateBuilderImpl.java | 17 +-
.../apache/curator/framework/schema/Schema.java | 2 +-
.../framework/recipes/cache/NodeCache.java | 15 +
.../recipes/cache/PathChildrenCache.java | 2 +-
.../apache/curator/test/BaseClassForTests.java | 10 +-
curator-x-async/pom.xml | 18 +
.../org/apache/curator/x/async/AsyncStage.java | 15 +-
.../apache/curator/x/async/AsyncWrappers.java | 297 ++++++++++++
.../curator/x/async/api/AsyncCreateBuilder.java | 28 ++
.../x/async/api/AsyncCuratorFrameworkDsl.java | 1 -
.../x/async/details/AsyncCreateBuilderImpl.java | 21 +
.../x/async/modeled/JacksonModelSerializer.java | 124 +++++
.../x/async/modeled/ModelSerializer.java | 43 ++
.../curator/x/async/modeled/ModelSpec.java | 217 +++++++++
.../x/async/modeled/ModelSpecBuilder.java | 138 ++++++
.../x/async/modeled/ModeledFramework.java | 371 +++++++++++++++
.../async/modeled/ModeledFrameworkBuilder.java | 154 +++++++
.../curator/x/async/modeled/NodeName.java | 39 ++
.../curator/x/async/modeled/Resolvable.java | 48 ++
.../apache/curator/x/async/modeled/ZNode.java | 74 +++
.../apache/curator/x/async/modeled/ZPath.java | 279 ++++++++++++
.../modeled/cached/CachedModeledFramework.java | 123 +++++
.../x/async/modeled/cached/ModeledCache.java | 46 ++
.../modeled/cached/ModeledCacheListener.java | 106 +++++
.../details/CachedModeledFrameworkImpl.java | 342 ++++++++++++++
.../x/async/modeled/details/ModelSpecImpl.java | 239 ++++++++++
.../x/async/modeled/details/ModelStage.java | 171 +++++++
.../async/modeled/details/ModeledCacheImpl.java | 211 +++++++++
.../modeled/details/ModeledFrameworkImpl.java | 450 +++++++++++++++++++
.../details/VersionedModeledFrameworkImpl.java | 85 ++++
.../x/async/modeled/details/ZNodeImpl.java | 56 +++
.../x/async/modeled/details/ZPathImpl.java | 289 ++++++++++++
.../x/async/modeled/typed/TypedModelSpec.java | 87 ++++
.../x/async/modeled/typed/TypedModelSpec0.java | 61 +++
.../x/async/modeled/typed/TypedModelSpec10.java | 61 +++
.../x/async/modeled/typed/TypedModelSpec2.java | 61 +++
.../x/async/modeled/typed/TypedModelSpec3.java | 61 +++
.../x/async/modeled/typed/TypedModelSpec4.java | 61 +++
.../x/async/modeled/typed/TypedModelSpec5.java | 61 +++
.../x/async/modeled/typed/TypedModelSpec6.java | 61 +++
.../x/async/modeled/typed/TypedModelSpec7.java | 61 +++
.../x/async/modeled/typed/TypedModelSpec8.java | 61 +++
.../x/async/modeled/typed/TypedModelSpec9.java | 61 +++
.../modeled/typed/TypedModeledFramework.java | 93 ++++
.../modeled/typed/TypedModeledFramework0.java | 63 +++
.../modeled/typed/TypedModeledFramework10.java | 63 +++
.../modeled/typed/TypedModeledFramework2.java | 63 +++
.../modeled/typed/TypedModeledFramework3.java | 63 +++
.../modeled/typed/TypedModeledFramework4.java | 63 +++
.../modeled/typed/TypedModeledFramework5.java | 63 +++
.../modeled/typed/TypedModeledFramework6.java | 63 +++
.../modeled/typed/TypedModeledFramework7.java | 63 +++
.../modeled/typed/TypedModeledFramework8.java | 63 +++
.../modeled/typed/TypedModeledFramework9.java | 63 +++
.../x/async/modeled/typed/TypedZPath.java | 92 ++++
.../x/async/modeled/typed/TypedZPath0.java | 52 +++
.../x/async/modeled/typed/TypedZPath10.java | 52 +++
.../x/async/modeled/typed/TypedZPath2.java | 52 +++
.../x/async/modeled/typed/TypedZPath3.java | 52 +++
.../x/async/modeled/typed/TypedZPath4.java | 52 +++
.../x/async/modeled/typed/TypedZPath5.java | 52 +++
.../x/async/modeled/typed/TypedZPath6.java | 52 +++
.../x/async/modeled/typed/TypedZPath7.java | 52 +++
.../x/async/modeled/typed/TypedZPath8.java | 52 +++
.../x/async/modeled/typed/TypedZPath9.java | 52 +++
.../x/async/modeled/versioned/Versioned.java | 69 +++
.../versioned/VersionedModeledFramework.java | 56 +++
.../src/site/confluence/async.confluence | 212 +++++++++
.../src/site/confluence/index.confluence | 213 +--------
.../confluence/modeled-components.confluence | 186 ++++++++
.../site/confluence/modeled-typed.confluence | 89 ++++
.../src/site/confluence/modeled.confluence | 48 ++
curator-x-async/src/site/site.xml | 6 +-
.../x/async/CompletableBaseClassForTests.java | 65 +++
.../curator/x/async/TestAsyncWrappers.java | 73 +++
.../curator/x/async/TestBasicOperations.java | 35 +-
.../modeled/TestCachedModeledFramework.java | 167 +++++++
.../x/async/modeled/TestModeledFramework.java | 178 ++++++++
.../async/modeled/TestModeledFrameworkBase.java | 64 +++
.../curator/x/async/modeled/TestZPath.java | 126 ++++++
.../x/async/modeled/models/TestModel.java | 115 +++++
.../x/async/modeled/models/TestNewerModel.java | 137 ++++++
.../x/async/modeled/models/TestSimpleModel.java | 84 ++++
.../src/test/resources/log4j.properties | 27 ++
curator-x-rpc/src/site/site.xml | 2 +-
pom.xml | 12 +
src/site/site.xml | 4 +-
110 files changed, 9380 insertions(+), 244 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/pom.xml
----------------------------------------------------------------------
diff --git a/curator-examples/pom.xml b/curator-examples/pom.xml
index f612cc2..cc65570 100644
--- a/curator-examples/pom.xml
+++ b/curator-examples/pom.xml
@@ -50,9 +50,30 @@
</dependency>
<dependency>
+ <groupId>org.apache.curator</groupId>
+ <artifactId>curator-x-async</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
- <scope>test</scope>
</dependency>
</dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/async/AsyncExamples.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/async/AsyncExamples.java b/curator-examples/src/main/java/async/AsyncExamples.java
new file mode 100644
index 0000000..43db219
--- /dev/null
+++ b/curator-examples/src/main/java/async/AsyncExamples.java
@@ -0,0 +1,127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package async;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.x.async.AsyncCuratorFramework;
+import org.apache.curator.x.async.AsyncEventException;
+import org.apache.curator.x.async.WatchMode;
+import org.apache.zookeeper.WatchedEvent;
+import java.util.concurrent.CompletionStage;
+
+/**
+ * Examples using the asynchronous DSL
+ */
+public class AsyncExamples
+{
+ public static AsyncCuratorFramework wrap(CuratorFramework client)
+ {
+ // wrap a CuratorFramework instance so that it can be used async.
+ // do this once and re-use the returned AsyncCuratorFramework instance
+ return AsyncCuratorFramework.wrap(client);
+ }
+
+ public static void create(CuratorFramework client, String path, byte[] payload)
+ {
+ AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client); // normally you'd wrap early in your app and reuse the instance
+
+ // create a node at the given path with the given payload asynchronously
+ async.create().forPath(path, payload).whenComplete((name, exception) -> {
+ if ( exception != null )
+ {
+ // there was a problem
+ exception.printStackTrace();
+ }
+ else
+ {
+ System.out.println("Created node name is: " + name);
+ }
+ });
+ }
+
+ public static void createThenWatch(CuratorFramework client, String path)
+ {
+ AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client); // normally you'd wrap early in your app and reuse the instance
+
+ // this example shows to asynchronously use watchers for both event
+ // triggering and connection problems. If you don't need to be notified
+ // of connection problems, use the simpler approach shown in createThenWatchSimple()
+
+ // create a node at the given path with the given payload asynchronously
+ // then watch the created node
+ async.create().forPath(path).whenComplete((name, exception) -> {
+ if ( exception != null )
+ {
+ // there was a problem creating the node
+ exception.printStackTrace();
+ }
+ else
+ {
+ handleWatchedStage(async.watched().checkExists().forPath(path).event());
+ }
+ });
+ }
+
+ public static void createThenWatchSimple(CuratorFramework client, String path)
+ {
+ AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client); // normally you'd wrap early in your app and reuse the instance
+
+ // create a node at the given path with the given payload asynchronously
+ // then watch the created node
+ async.create().forPath(path).whenComplete((name, exception) -> {
+ if ( exception != null )
+ {
+ // there was a problem creating the node
+ exception.printStackTrace();
+ }
+ else
+ {
+ // because "WatchMode.successOnly" is used the watch stage is only triggered when
+ // the EventType is a node event
+ async.with(WatchMode.successOnly).watched().checkExists().forPath(path).event().thenAccept(event -> {
+ System.out.println(event.getType());
+ System.out.println(event);
+ });
+ }
+ });
+ }
+
+ private static void handleWatchedStage(CompletionStage<WatchedEvent> watchedStage)
+ {
+ // async handling of Watchers is complicated because watchers can trigger multiple times
+ // and CompletionStage don't support this behavior
+
+ // thenAccept() handles normal watcher triggering.
+ watchedStage.thenAccept(event -> {
+ System.out.println(event.getType());
+ System.out.println(event);
+ // etc.
+ });
+
+ // exceptionally is called if there is a connection problem in which case
+ // watchers trigger to signal the connection problem. "reset()" must be called
+ // to reset the watched stage
+ watchedStage.exceptionally(exception -> {
+ AsyncEventException asyncEx = (AsyncEventException)exception;
+ asyncEx.printStackTrace(); // handle the error as needed
+ handleWatchedStage(asyncEx.reset());
+ return null;
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/modeled/ContainerType.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/modeled/ContainerType.java b/curator-examples/src/main/java/modeled/ContainerType.java
new file mode 100644
index 0000000..a36cfaa
--- /dev/null
+++ b/curator-examples/src/main/java/modeled/ContainerType.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package modeled;
+
+public class ContainerType
+{
+ private final int typeId;
+
+ public ContainerType()
+ {
+ this(0);
+ }
+
+ public ContainerType(int typeId)
+ {
+ this.typeId = typeId;
+ }
+
+ public int getTypeId()
+ {
+ return typeId;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+
+ ContainerType that = (ContainerType)o;
+
+ return typeId == that.typeId;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return typeId;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ContainerType{" + "typeId=" + typeId + '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/modeled/ModeledCuratorExamples.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/modeled/ModeledCuratorExamples.java b/curator-examples/src/main/java/modeled/ModeledCuratorExamples.java
new file mode 100644
index 0000000..e7e363c
--- /dev/null
+++ b/curator-examples/src/main/java/modeled/ModeledCuratorExamples.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package modeled;
+
+import org.apache.curator.x.async.AsyncCuratorFramework;
+import org.apache.curator.x.async.modeled.JacksonModelSerializer;
+import org.apache.curator.x.async.modeled.ModelSpec;
+import org.apache.curator.x.async.modeled.ModeledFramework;
+import org.apache.curator.x.async.modeled.ZPath;
+import java.util.function.Consumer;
+
+public class ModeledCuratorExamples
+{
+ public static ModeledFramework<PersonModel> wrap(AsyncCuratorFramework client)
+ {
+ JacksonModelSerializer<PersonModel> serializer = JacksonModelSerializer.build(PersonModel.class);
+
+ // build a model specification - you can pre-build all the model specifications for your app at startup
+ ModelSpec<PersonModel> modelSpec = ModelSpec.builder(ZPath.parse("/example/path"), serializer).build();
+
+ // wrap a CuratorFramework instance so that it can be used "modeled".
+ // do this once and re-use the returned ModeledFramework instance.
+ // ModeledFramework instances are tied to a given path
+ return ModeledFramework.wrap(client, modelSpec);
+ }
+
+ public static void createOrUpdate(ModeledFramework<PersonModel> modeled, PersonModel model)
+ {
+ // change the affected path to be modeled's base path plus id: i.e. "/example/path/{id}"
+ ModeledFramework<PersonModel> atId = modeled.child(model.getId().getId());
+
+ // by default ModeledFramework instances update the node if it already exists
+ // so this will either create or update the node
+ atId.set(model); // note - this is async
+ }
+
+ public static void readPerson(ModeledFramework<PersonModel> modeled, String id, Consumer<PersonModel> receiver)
+ {
+ // read the person with the given ID and asynchronously call the receiver after it is read
+ modeled.child(id).read().whenComplete((person, exception) -> {
+ if ( exception != null )
+ {
+ exception.printStackTrace(); // handle the error
+ }
+ else
+ {
+ receiver.accept(person);
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/modeled/ModeledCuratorExamplesAlt.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/modeled/ModeledCuratorExamplesAlt.java b/curator-examples/src/main/java/modeled/ModeledCuratorExamplesAlt.java
new file mode 100644
index 0000000..859a1f1
--- /dev/null
+++ b/curator-examples/src/main/java/modeled/ModeledCuratorExamplesAlt.java
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package modeled;
+
+import org.apache.curator.x.async.modeled.ModeledFramework;
+import java.util.function.Consumer;
+
+public class ModeledCuratorExamplesAlt
+{
+ public static void createOrUpdate(PersonModelSpec modelSpec, PersonModel model)
+ {
+ // change the affected path to be modeled's base path plus id: i.e. "/example/path/{id}"
+ ModeledFramework<PersonModel> resolved = modelSpec.resolved(model.getContainerType(), model.getId());
+
+ // by default ModeledFramework instances update the node if it already exists
+ // so this will either create or update the node
+ resolved.set(model); // note - this is async
+ }
+
+ public static void readPerson(PersonModelSpec modelSpec, ContainerType containerType, PersonId id, Consumer<PersonModel> receiver)
+ {
+ ModeledFramework<PersonModel> resolved = modelSpec.resolved(containerType, id);
+
+ // read the person with the given ID and asynchronously call the receiver after it is read
+ resolved.read().whenComplete((person, exception) -> {
+ if ( exception != null )
+ {
+ exception.printStackTrace(); // handle the error
+ }
+ else
+ {
+ receiver.accept(person);
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/modeled/PersonId.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/modeled/PersonId.java b/curator-examples/src/main/java/modeled/PersonId.java
new file mode 100644
index 0000000..eabc286
--- /dev/null
+++ b/curator-examples/src/main/java/modeled/PersonId.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package modeled;
+
+import java.util.Objects;
+
+public class PersonId
+{
+ private final String id;
+
+ public PersonId()
+ {
+ this("");
+ }
+
+ public PersonId(String id)
+ {
+ this.id = Objects.requireNonNull(id, "id cannot be null");
+ }
+
+ public String getId()
+ {
+ return id;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+
+ PersonId personId = (PersonId)o;
+
+ return id.equals(personId.id);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return id.hashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "PersonId{" + "id='" + id + '\'' + '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/modeled/PersonModel.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/modeled/PersonModel.java b/curator-examples/src/main/java/modeled/PersonModel.java
new file mode 100644
index 0000000..f9b9102
--- /dev/null
+++ b/curator-examples/src/main/java/modeled/PersonModel.java
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package modeled;
+
+import java.util.Objects;
+
+public class PersonModel
+{
+ private final PersonId id;
+ private final ContainerType containerType;
+ private final String firstName;
+ private final String lastName;
+ private final int age;
+
+ public PersonModel()
+ {
+ this(new PersonId(), new ContainerType(), null, null, 0);
+ }
+
+ public PersonModel(PersonId id, ContainerType containerType, String firstName, String lastName, int age)
+ {
+ this.id = Objects.requireNonNull(id, "id cannot be null");
+ this.containerType = Objects.requireNonNull(containerType, "containerType cannot be null");
+ this.firstName = Objects.requireNonNull(firstName, "firstName cannot be null");
+ this.lastName = Objects.requireNonNull(lastName, "lastName cannot be null");
+ this.age = age;
+ }
+
+ public PersonId getId()
+ {
+ return id;
+ }
+
+ public ContainerType getContainerType()
+ {
+ return containerType;
+ }
+
+ public String getFirstName()
+ {
+ return firstName;
+ }
+
+ public String getLastName()
+ {
+ return lastName;
+ }
+
+ public int getAge()
+ {
+ return age;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+
+ PersonModel that = (PersonModel)o;
+
+ if ( age != that.age )
+ {
+ return false;
+ }
+ if ( !id.equals(that.id) )
+ {
+ return false;
+ }
+ if ( !containerType.equals(that.containerType) )
+ {
+ return false;
+ }
+ //noinspection SimplifiableIfStatement
+ if ( !firstName.equals(that.firstName) )
+ {
+ return false;
+ }
+ return lastName.equals(that.lastName);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = id.hashCode();
+ result = 31 * result + containerType.hashCode();
+ result = 31 * result + firstName.hashCode();
+ result = 31 * result + lastName.hashCode();
+ result = 31 * result + age;
+ return result;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "PersonModel{" + "id=" + id + ", containerType=" + containerType + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", age=" + age + '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/modeled/PersonModelSpec.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/modeled/PersonModelSpec.java b/curator-examples/src/main/java/modeled/PersonModelSpec.java
new file mode 100644
index 0000000..f90f616
--- /dev/null
+++ b/curator-examples/src/main/java/modeled/PersonModelSpec.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package modeled;
+
+import org.apache.curator.x.async.AsyncCuratorFramework;
+import org.apache.curator.x.async.modeled.JacksonModelSerializer;
+import org.apache.curator.x.async.modeled.ModelSpec;
+import org.apache.curator.x.async.modeled.ModeledFramework;
+import org.apache.curator.x.async.modeled.ZPath;
+
+public class PersonModelSpec
+{
+ private final AsyncCuratorFramework client;
+ private final ModelSpec<PersonModel> modelSpec;
+
+ public PersonModelSpec(AsyncCuratorFramework client)
+ {
+ this.client = client;
+
+ JacksonModelSerializer<PersonModel> serializer = JacksonModelSerializer.build(PersonModel.class);
+ ZPath path = ZPath.parseWithIds("/example/{id}/path/{id}");
+ modelSpec = ModelSpec.builder(path, serializer).build();
+ }
+
+ public ModeledFramework<PersonModel> resolved(ContainerType containerType, PersonId personId)
+ {
+ ModelSpec<PersonModel> resolved = modelSpec.resolved(containerType.getTypeId(), personId.getId());
+ return ModeledFramework.wrap(client, resolved);
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/Clients.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/Clients.java b/curator-examples/src/main/java/pubsub/Clients.java
new file mode 100644
index 0000000..c0a8136
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/Clients.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package pubsub;
+
+import org.apache.curator.x.async.modeled.JacksonModelSerializer;
+import org.apache.curator.x.async.modeled.ModelSpec;
+import org.apache.curator.x.async.modeled.ModelSpecBuilder;
+import org.apache.curator.x.async.modeled.ModeledFramework;
+import org.apache.curator.x.async.modeled.typed.TypedModeledFramework;
+import org.apache.curator.x.async.modeled.typed.TypedModeledFramework2;
+import org.apache.zookeeper.CreateMode;
+import pubsub.messages.LocationAvailable;
+import pubsub.messages.UserCreated;
+import pubsub.models.Group;
+import pubsub.models.Instance;
+import pubsub.models.InstanceType;
+import pubsub.models.Priority;
+import java.util.concurrent.TimeUnit;
+
+public class Clients
+{
+ /**
+ * A client template for LocationAvailable instances
+ */
+ public static final TypedModeledFramework2<LocationAvailable, Group, Priority> locationAvailableClient = TypedModeledFramework2.from(
+ ModeledFramework.builder(),
+ builder(LocationAvailable.class),
+ "/root/pubsub/messages/locations/{group}/{priority}/{id}"
+ );
+
+ /**
+ * A client template for UserCreated instances
+ */
+ public static final TypedModeledFramework2<UserCreated, Group, Priority> userCreatedClient = TypedModeledFramework2.from(
+ ModeledFramework.builder(),
+ builder(UserCreated.class),
+ "/root/pubsub/messages/users/{group}/{priority}/{id}"
+ );
+
+ /**
+ * A client template for Instance instances
+ */
+ public static final TypedModeledFramework<Instance, InstanceType> instanceClient = TypedModeledFramework.from(
+ ModeledFramework.builder(),
+ builder(Instance.class),
+ "/root/pubsub/instances/{instance-type}/{id}"
+ );
+
+ private static <T> ModelSpecBuilder<T> builder(Class<T> clazz)
+ {
+ return ModelSpec.builder(JacksonModelSerializer.build(clazz))
+ .withTtl(TimeUnit.MINUTES.toMillis(10)) // for our pub-sub example, messages are valid for 10 minutes
+ .withCreateMode(CreateMode.PERSISTENT_WITH_TTL)
+ ;
+ }
+
+ private Clients()
+ {
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/Publisher.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/Publisher.java b/curator-examples/src/main/java/pubsub/Publisher.java
new file mode 100644
index 0000000..5c8f7af
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/Publisher.java
@@ -0,0 +1,146 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package pubsub;
+
+import org.apache.curator.framework.api.transaction.CuratorOp;
+import org.apache.curator.x.async.AsyncCuratorFramework;
+import org.apache.curator.x.async.modeled.ModeledFramework;
+import org.apache.curator.x.async.modeled.typed.TypedModeledFramework2;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import pubsub.messages.LocationAvailable;
+import pubsub.messages.UserCreated;
+import pubsub.models.Group;
+import pubsub.models.Instance;
+import pubsub.models.Message;
+import pubsub.models.Priority;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class Publisher
+{
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private final AsyncCuratorFramework client;
+
+ public Publisher(AsyncCuratorFramework client)
+ {
+ this.client = Objects.requireNonNull(client, "client cannot be null");
+ }
+
+ /**
+ * Publish the given instance using the Instance client template
+ *
+ * @param instance instance to publish
+ */
+ public void publishInstance(Instance instance)
+ {
+ ModeledFramework<Instance> resolvedClient = Clients.instanceClient.resolved(client, instance.getType());
+ resolvedClient.set(instance).exceptionally(e -> {
+ log.error("Could not publish instance: " + instance, e);
+ return null;
+ });
+ }
+
+ /**
+ * Publish the given instances using the Instance client template in a transaction
+ *
+ * @param instances instances to publish
+ */
+ public void publishInstances(List<Instance> instances)
+ {
+ List<CuratorOp> operations = instances.stream()
+ .map(instance -> Clients.instanceClient
+ .resolved(client, instance.getType())
+ .createOp(instance)
+ )
+ .collect(Collectors.toList());
+ client.transaction().forOperations(operations).exceptionally(e -> {
+ log.error("Could not publish instances: " + instances, e);
+ return null;
+ });
+ }
+
+ /**
+ * Publish the given LocationAvailable using the LocationAvailable client template
+ *
+ * @param group group
+ * @param locationAvailable message to publish
+ */
+ public void publishLocationAvailable(Group group, LocationAvailable locationAvailable)
+ {
+ publishMessage(Clients.locationAvailableClient, group, locationAvailable);
+ }
+
+ /**
+ * Publish the given UserCreated using the UserCreated client template
+ *
+ * @param group group
+ * @param userCreated message to publish
+ */
+ public void publishUserCreated(Group group, UserCreated userCreated)
+ {
+ publishMessage(Clients.userCreatedClient, group, userCreated);
+ }
+
+ /**
+ * Publish the given LocationAvailables using the LocationAvailable client template in a transaction
+ *
+ * @param group group
+ * @param locationsAvailable messages to publish
+ */
+ public void publishLocationsAvailable(Group group, List<LocationAvailable> locationsAvailable)
+ {
+ publishMessages(Clients.locationAvailableClient, group, locationsAvailable);
+ }
+
+ /**
+ * Publish the given UserCreateds using the UserCreated client template in a transaction
+ *
+ * @param group group
+ * @param usersCreated messages to publish
+ */
+ public void publishUsersCreated(Group group, List<UserCreated> usersCreated)
+ {
+ publishMessages(Clients.userCreatedClient, group, usersCreated);
+ }
+
+ private <T extends Message> void publishMessage(TypedModeledFramework2<T, Group, Priority> typedClient, Group group, T message)
+ {
+ ModeledFramework<T> resolvedClient = typedClient.resolved(client, group, message.getPriority());
+ resolvedClient.set(message).exceptionally(e -> {
+ log.error("Could not publish message: " + message, e);
+ return null;
+ });
+ }
+
+ private <T extends Message> void publishMessages(TypedModeledFramework2<T, Group, Priority> typedClient, Group group, List<T> messages)
+ {
+ List<CuratorOp> operations = messages.stream()
+ .map(message -> typedClient
+ .resolved(client, group, message.getPriority())
+ .createOp(message)
+ )
+ .collect(Collectors.toList());
+ client.transaction().forOperations(operations).exceptionally(e -> {
+ log.error("Could not publish messages: " + messages, e);
+ return null;
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/README.md
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/README.md b/curator-examples/src/main/java/pubsub/README.md
new file mode 100644
index 0000000..f6d5971
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/README.md
@@ -0,0 +1,93 @@
+# Pub-Sub Example
+This example models a publish and subscribe system (note: it is not meant for production) using
+the strongly typed modeled APIs in Apache Curator.
+
+## Design Notes
+
+In this example, there are three models that can be published: `Instance`, `LocationAvailable`
+and `UserCreated`. Instances have an `InstanceType`; LocationAvailable and UserCreated both have
+a `Priority` and are associated with a `Group`. (Note: these names/objects are meant for
+illustrative purposes only and are completely contrived)
+
+Each model is stored at a unique path in ZooKeeper:
+
+* Instance: `/root/pubsub/instances/TYPE/ID`
+* LocationAvailable: `/root/pubsub/messages/locations/GROUP/PRIORITY/ID`
+* UserCreated: `/root/pubsub/messages/users/GROUP/PRIORITY/ID`
+
+All models are stored using a TTL so that they automatically get deleted after 10 minutes.
+
+## Clients
+
+This example uses the "typed" models (`TypedModelSpec`, etc.). The typed paths, models and
+clients are meant to be created early in your application and re-used as needed. Thus, you
+can model your ZooKeeper usage and the rest of your application can use them without worrying
+about correct paths, types, etc.
+
+`TypedModeledFramework` is a template that produces a `ModeledFramework` by applying
+parameters to the `TypedZPath` in the contained `TypedModelSpec`. Curator provides variants
+that accept from 1 to 10 parameters (`TypedModeledFramework`, `TypedModeledFramework2`,
+`TypedModeledFramework3`, etc.).
+
+In this example, the TypedModeledFrameworks are defined in `Clients.java`. E.g.
+
+```
+public static final TypedModeledFramework2<LocationAvailable, Group, Priority> locationAvailableClient =
+ TypedModeledFramework2.from(
+ ModeledFramework.builder(),
+ builder(LocationAvailable.class),
+ "/root/pubsub/messages/locations/{group}/{priority}"
+ );
+```
+
+## Publisher
+
+`Publisher.java` shows how to use the ModeledFramework to write models. There are methods to
+write single instances and to write lists of instances in a transaction. Each publish method
+resolves the appropriate typed client and then calls its `set()` method with the given model.
+
+## Subscriber
+
+`Subscriber.java` uses CachedModeledFrameworks to listen for changes on the parent nodes for
+all of the models in this example. Each of the methods resolves the appropriate typed client
+and then starts the cache (via `cached()`).
+
+## SubPubTest
+
+`SubPubTest.java` is a class that exercises this example.
+
+* `start()` uses `Subscriber` to start a `CachedModeledFramework` for each combination of
+the Instance + InstanceType, LocationAvailable + Group + Priority, and UserCreated + Group + Priority. It then adds a simple listener to each cache that merely prints the class name
+and path whenever an update occurs (see `generalListener()`).
+* `start()` also starts a scheduled task that runs every second. This task calls
+`publishSomething()`
+* `publishSomething()` randomly publishes either a single Instance, LocationAvailable,
+UserCreated or a list of those.
+
+`SubPubTest.java` has a `main()` method. When you run you should see something similar to this:
+
+```
+Publishing 9 instances
+Subscribed Instance @ /root/pubsub/instances/proxy/1
+Subscribed Instance @ /root/pubsub/instances/web/2
+Subscribed Instance @ /root/pubsub/instances/cache/4
+Subscribed Instance @ /root/pubsub/instances/proxy/9
+Subscribed Instance @ /root/pubsub/instances/database/3
+Subscribed Instance @ /root/pubsub/instances/cache/5
+Subscribed Instance @ /root/pubsub/instances/database/6
+Subscribed Instance @ /root/pubsub/instances/cache/7
+Subscribed Instance @ /root/pubsub/instances/cache/8
+Publishing 1 userCreated
+Subscribed UserCreated @ /root/pubsub/messages/users/main/high/10
+Publishing 9 locationsAvailable
+Subscribed LocationAvailable @ /root/pubsub/messages/locations/admin/low/11
+Subscribed LocationAvailable @ /root/pubsub/messages/locations/admin/medium/12
+Subscribed LocationAvailable @ /root/pubsub/messages/locations/admin/medium/13
+Subscribed LocationAvailable @ /root/pubsub/messages/locations/admin/medium/14
+Subscribed LocationAvailable @ /root/pubsub/messages/locations/admin/medium/16
+Subscribed LocationAvailable @ /root/pubsub/messages/locations/admin/high/15
+Subscribed LocationAvailable @ /root/pubsub/messages/locations/admin/medium/17
+...
+```
+
+It runs for 1 minute and then exits.
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/SubPubTest.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/SubPubTest.java b/curator-examples/src/main/java/pubsub/SubPubTest.java
new file mode 100644
index 0000000..354d568
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/SubPubTest.java
@@ -0,0 +1,220 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package pubsub;
+
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.TestingServer;
+import org.apache.curator.x.async.AsyncCuratorFramework;
+import org.apache.curator.x.async.modeled.cached.CachedModeledFramework;
+import org.apache.curator.x.async.modeled.cached.ModeledCacheListener;
+import pubsub.messages.LocationAvailable;
+import pubsub.messages.UserCreated;
+import pubsub.models.Group;
+import pubsub.models.Instance;
+import pubsub.models.InstanceType;
+import pubsub.models.Priority;
+import java.io.Closeable;
+import java.io.IOException;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class SubPubTest implements Closeable
+{
+ private final TestingServer testingServer;
+ private final AsyncCuratorFramework client;
+ private final ScheduledExecutorService executorService;
+ private final List<CachedModeledFramework<Instance>> instanceSubscribers = new ArrayList<>();
+ private final List<CachedModeledFramework<LocationAvailable>> locationAvailableSubscribers = new ArrayList<>();
+ private final List<CachedModeledFramework<UserCreated>> userCreatedSubscribers = new ArrayList<>();
+
+ private static final AtomicLong nextId = new AtomicLong(1);
+
+ // arrays of random values used for this example
+ private static final Group[] groups = {new Group("main"), new Group("admin")};
+ private static final String[] hostnames = {"host1", "host2", "host3"};
+ private static final Integer[] ports = {80, 443, 9999};
+ private static final String[] locations = {"dc1", "dc2", "eu", "us"};
+ private static final Duration[] durations = {Duration.ofSeconds(1), Duration.ofMinutes(1), Duration.ofHours(1)};
+ private static final String[] positions = {"worker", "manager", "executive"};
+
+ public static void main(String[] args)
+ {
+ try ( SubPubTest subPubTest = new SubPubTest() )
+ {
+ subPubTest.start();
+ TimeUnit.MINUTES.sleep(1); // run the test for a minute then exit
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public SubPubTest() throws Exception
+ {
+ this.testingServer = new TestingServer();
+ client = AsyncCuratorFramework.wrap(CuratorFrameworkFactory.newClient(testingServer.getConnectString(), new RetryOneTime(1)));
+ executorService = Executors.newSingleThreadScheduledExecutor();
+ }
+
+ public void start()
+ {
+ client.unwrap().start();
+
+ Publisher publisher = new Publisher(client);
+ Subscriber subscriber = new Subscriber(client);
+
+ // start a subscriber/cache for Instances of each InstanceType
+ instanceSubscribers.addAll(
+ Arrays.stream(InstanceType.values())
+ .map(subscriber::startInstanceSubscriber)
+ .collect(Collectors.toList())
+ );
+
+ // start a subscriber/cache for LocationAvailables of each combination of Group and Priority
+ locationAvailableSubscribers.addAll(
+ Arrays.stream(Priority.values())
+ .flatMap(priority -> Arrays.stream(groups).map(group -> subscriber.startLocationAvailableSubscriber(group, priority)))
+ .collect(Collectors.toList())
+ );
+
+ // start a subscriber/cache for UserCreateds of each combination of Group and Priority
+ userCreatedSubscribers.addAll(
+ Arrays.stream(Priority.values())
+ .flatMap(priority -> Arrays.stream(groups).map(group -> subscriber.startUserCreatedSubscriber(group, priority)))
+ .collect(Collectors.toList())
+ );
+
+ // add listeners for each of the caches
+ instanceSubscribers.forEach(s -> s.listenable().addListener(generalListener()));
+ locationAvailableSubscribers.forEach(s -> s.listenable().addListener(generalListener()));
+ userCreatedSubscribers.forEach(s -> s.listenable().addListener(generalListener()));
+
+ // schedule the publisher task once a second
+ executorService.scheduleAtFixedRate(() -> publishSomething(publisher), 1, 1, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void close() throws IOException
+ {
+ executorService.shutdownNow();
+ try
+ {
+ executorService.awaitTermination(5, TimeUnit.SECONDS);
+ }
+ catch ( InterruptedException ignore )
+ {
+ Thread.currentThread().interrupt();
+ }
+
+ userCreatedSubscribers.forEach(CachedModeledFramework::close);
+ locationAvailableSubscribers.forEach(CachedModeledFramework::close);
+ instanceSubscribers.forEach(CachedModeledFramework::close);
+ client.unwrap().close();
+ testingServer.close();
+ }
+
+ private void publishSomething(Publisher publisher)
+ {
+ // randomly do some publishing - either single items or lists of items in a transaction
+ switch ( ThreadLocalRandom.current().nextInt(6) )
+ {
+ case 0:
+ {
+ Instance instance = new Instance(nextId(), random(InstanceType.values()), random(hostnames), random(ports));
+ System.out.println("Publishing 1 instance");
+ publisher.publishInstance(instance);
+ break;
+ }
+
+ case 1:
+ {
+ List<Instance> instances = IntStream.range(1, 10)
+ .mapToObj(__ -> new Instance(nextId(), random(InstanceType.values()), random(hostnames), random(ports)))
+ .collect(Collectors.toList());
+ System.out.println(String.format("Publishing %d instances", instances.size()));
+ publisher.publishInstances(instances);
+ break;
+ }
+
+ case 2:
+ {
+ LocationAvailable locationAvailable = new LocationAvailable(nextId(), random(Priority.values()), random(locations), random(durations));
+ System.out.println("Publishing 1 locationAvailable");
+ publisher.publishLocationAvailable(random(groups), locationAvailable);
+ break;
+ }
+
+ case 3:
+ {
+ List<LocationAvailable> locationsAvailable = IntStream.range(1, 10)
+ .mapToObj(__ -> new LocationAvailable(nextId(), random(Priority.values()), random(locations), random(durations)))
+ .collect(Collectors.toList());
+ System.out.println(String.format("Publishing %d locationsAvailable", locationsAvailable.size()));
+ publisher.publishLocationsAvailable(random(groups), locationsAvailable);
+ break;
+ }
+
+ case 4:
+ {
+ UserCreated userCreated = new UserCreated(nextId(), random(Priority.values()), random(locations), random(positions));
+ System.out.println("Publishing 1 userCreated");
+ publisher.publishUserCreated(random(groups), userCreated);
+ break;
+ }
+
+ case 5:
+ {
+ List<UserCreated> usersCreated = IntStream.range(1, 10)
+ .mapToObj(__ -> new UserCreated(nextId(), random(Priority.values()), random(locations), random(positions)))
+ .collect(Collectors.toList());
+ System.out.println(String.format("Publishing %d usersCreated", usersCreated.size()));
+ publisher.publishUsersCreated(random(groups), usersCreated);
+ break;
+ }
+ }
+ }
+
+ private <T> ModeledCacheListener<T> generalListener()
+ {
+ return (type, path, stat, model) -> System.out.println(String.format("Subscribed %s @ %s", model.getClass().getSimpleName(), path));
+ }
+
+ @SafeVarargs
+ private final <T> T random(T... tab)
+ {
+ int index = ThreadLocalRandom.current().nextInt(tab.length);
+ return tab[index];
+ }
+
+ private String nextId()
+ {
+ return Long.toString(nextId.getAndIncrement());
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/Subscriber.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/Subscriber.java b/curator-examples/src/main/java/pubsub/Subscriber.java
new file mode 100644
index 0000000..94a6247
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/Subscriber.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package pubsub;
+
+import org.apache.curator.x.async.AsyncCuratorFramework;
+import org.apache.curator.x.async.modeled.cached.CachedModeledFramework;
+import org.apache.curator.x.async.modeled.typed.TypedModeledFramework2;
+import pubsub.messages.LocationAvailable;
+import pubsub.messages.UserCreated;
+import pubsub.models.Group;
+import pubsub.models.Instance;
+import pubsub.models.InstanceType;
+import pubsub.models.Message;
+import pubsub.models.Priority;
+
+public class Subscriber
+{
+ private final AsyncCuratorFramework client;
+
+ public Subscriber(AsyncCuratorFramework client)
+ {
+ this.client = client;
+ }
+
+ /**
+ * Start a subscriber (a CachedModeledFramework instance) using the LocationAvailable client template
+ *
+ * @param group group to listen for
+ * @param priority priority to listen for
+ * @return CachedModeledFramework instance (already started)
+ */
+ public CachedModeledFramework<LocationAvailable> startLocationAvailableSubscriber(Group group, Priority priority)
+ {
+ return startSubscriber(Clients.locationAvailableClient, group, priority);
+ }
+
+ /**
+ * Start a subscriber (a CachedModeledFramework instance) using the UserCreated client template
+ *
+ * @param group group to listen for
+ * @param priority priority to listen for
+ * @return CachedModeledFramework instance (already started)
+ */
+ public CachedModeledFramework<UserCreated> startUserCreatedSubscriber(Group group, Priority priority)
+ {
+ return startSubscriber(Clients.userCreatedClient, group, priority);
+ }
+
+ /**
+ * Start a subscriber (a CachedModeledFramework instance) using the Instance client template
+ *
+ * @param instanceType type to listen for
+ * @return CachedModeledFramework instance (already started)
+ */
+ public CachedModeledFramework<Instance> startInstanceSubscriber(InstanceType instanceType)
+ {
+ CachedModeledFramework<Instance> resolved = Clients.instanceClient.resolved(client, instanceType).cached();
+ resolved.start();
+ return resolved;
+ }
+
+ private <T extends Message> CachedModeledFramework<T> startSubscriber(TypedModeledFramework2<T, Group, Priority> typedClient, Group group, Priority priority)
+ {
+ CachedModeledFramework<T> resolved = typedClient.resolved(client, group, priority).cached();
+ resolved.start();
+ return resolved;
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/messages/LocationAvailable.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/messages/LocationAvailable.java b/curator-examples/src/main/java/pubsub/messages/LocationAvailable.java
new file mode 100644
index 0000000..dd90107
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/messages/LocationAvailable.java
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package pubsub.messages;
+
+import pubsub.models.Message;
+import pubsub.models.Priority;
+import java.time.Duration;
+import java.util.Objects;
+
+public class LocationAvailable extends Message
+{
+ private final String name;
+ private final Duration availableUntil;
+
+ public LocationAvailable()
+ {
+ this(Priority.low, "", Duration.ZERO);
+ }
+
+ public LocationAvailable(Priority priority, String name, Duration availableUntil)
+ {
+ super(priority);
+ this.name = Objects.requireNonNull(name, "name cannot be null");
+ this.availableUntil = Objects.requireNonNull(availableUntil, "availableUntil cannot be null");
+ }
+
+ public LocationAvailable(String id, Priority priority, String name, Duration availableUntil)
+ {
+ super(id, priority);
+ this.name = Objects.requireNonNull(name, "name cannot be null");
+ this.availableUntil = Objects.requireNonNull(availableUntil, "availableUntil cannot be null");
+ }
+
+ @Override
+ public String toString()
+ {
+ return "LocationAvailable{" + "name='" + name + '\'' + ", availableUntil=" + availableUntil + "} " + super.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/messages/UserCreated.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/messages/UserCreated.java b/curator-examples/src/main/java/pubsub/messages/UserCreated.java
new file mode 100644
index 0000000..bf753a8
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/messages/UserCreated.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package pubsub.messages;
+
+import pubsub.models.Message;
+import pubsub.models.Priority;
+import java.util.Objects;
+
+public class UserCreated extends Message
+{
+ private final String name;
+ private final String position;
+
+ public UserCreated()
+ {
+ this(Priority.low, "","");
+ }
+
+ public UserCreated(Priority priority, String name, String position)
+ {
+ super(priority);
+ this.name = Objects.requireNonNull(name, "name cannot be null");
+ this.position = Objects.requireNonNull(position, "position cannot be null");
+ }
+
+ public UserCreated(String id, Priority priority, String name, String position)
+ {
+ super(id, priority);
+ this.name = Objects.requireNonNull(name, "name cannot be null");
+ this.position = Objects.requireNonNull(position, "position cannot be null");
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getPosition()
+ {
+ return position;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "UserCreated{" + "name='" + name + '\'' + ", position='" + position + '\'' + "} " + super.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/models/Group.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/models/Group.java b/curator-examples/src/main/java/pubsub/models/Group.java
new file mode 100644
index 0000000..07d149f
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/models/Group.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package pubsub.models;
+
+import org.apache.curator.x.async.modeled.NodeName;
+
+public class Group implements NodeName
+{
+ private final String groupName;
+
+ public Group()
+ {
+ this("");
+ }
+
+ public Group(String groupName)
+ {
+ this.groupName = groupName;
+ }
+
+ public String getGroupName()
+ {
+ return groupName;
+ }
+
+ @Override
+ public String nodeName()
+ {
+ return groupName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/models/Instance.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/models/Instance.java b/curator-examples/src/main/java/pubsub/models/Instance.java
new file mode 100644
index 0000000..981f113
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/models/Instance.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package pubsub.models;
+
+import org.apache.curator.x.async.modeled.NodeName;
+import java.util.Objects;
+import java.util.UUID;
+
+public class Instance implements NodeName
+{
+ private final String id;
+ private final InstanceType type;
+ private final String hostname;
+ private final int port;
+
+ public Instance()
+ {
+ this(UUID.randomUUID().toString(), InstanceType.proxy, "", 0);
+ }
+
+ public Instance(String id, InstanceType type, String hostname, int port)
+ {
+ this.id = Objects.requireNonNull(id, "id cannot be null");
+ this.type = Objects.requireNonNull(type, "type cannot be null");
+ this.hostname = Objects.requireNonNull(hostname, "hostname cannot be null");
+ this.port = port;
+ }
+
+ public String getId()
+ {
+ return id;
+ }
+
+ public InstanceType getType()
+ {
+ return type;
+ }
+
+ public String getHostname()
+ {
+ return hostname;
+ }
+
+ public int getPort()
+ {
+ return port;
+ }
+
+ @Override
+ public String nodeName()
+ {
+ return id;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Instance{" + "id='" + id + '\'' + ", type=" + type + ", hostname='" + hostname + '\'' + ", port=" + port + '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/models/InstanceType.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/models/InstanceType.java b/curator-examples/src/main/java/pubsub/models/InstanceType.java
new file mode 100644
index 0000000..176048c
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/models/InstanceType.java
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package pubsub.models;
+
+public enum InstanceType
+{
+ database,
+ cache,
+ web,
+ proxy
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/0f5d10da/curator-examples/src/main/java/pubsub/models/Message.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/pubsub/models/Message.java b/curator-examples/src/main/java/pubsub/models/Message.java
new file mode 100644
index 0000000..7d92e99
--- /dev/null
+++ b/curator-examples/src/main/java/pubsub/models/Message.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package pubsub.models;
+
+import org.apache.curator.x.async.modeled.NodeName;
+import java.util.Objects;
+import java.util.UUID;
+
+public abstract class Message implements NodeName
+{
+ private final String id;
+ private final Priority priority;
+
+ protected Message()
+ {
+ this(UUID.randomUUID().toString(), Priority.low);
+ }
+
+ protected Message(Priority priority)
+ {
+ this(UUID.randomUUID().toString(), priority);
+ }
+
+ protected Message(String id, Priority priority)
+ {
+ this.id = Objects.requireNonNull(id, "id cannot be null");
+ this.priority = Objects.requireNonNull(priority, "messageType cannot be null");
+ }
+
+ public String getId()
+ {
+ return id;
+ }
+
+ public Priority getPriority()
+ {
+ return priority;
+ }
+
+ @Override
+ public String nodeName()
+ {
+ return id;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Message{" + "id='" + id + '\'' + ", priority=" + priority + '}';
+ }
+}