Docs: persistence best practices / guidelines

Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/fe4668cc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/fe4668cc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/fe4668cc

Branch: refs/heads/master
Commit: fe4668ccc05eb6e953de1d4172014d63efa462bd
Parents: 4ae4e6a
Author: Aled Sage <[email protected]>
Authored: Tue Mar 10 17:24:32 2015 +0000
Committer: Aled Sage <[email protected]>
Committed: Tue Mar 10 17:24:32 2015 +0000

----------------------------------------------------------------------
 docs/guide/ops/persistence/index.md | 75 +++++++++++++++++++++++++-------
 1 file changed, 59 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/fe4668cc/docs/guide/ops/persistence/index.md
----------------------------------------------------------------------
diff --git a/docs/guide/ops/persistence/index.md 
b/docs/guide/ops/persistence/index.md
index 1a8fe55..ab8e724 100644
--- a/docs/guide/ops/persistence/index.md
+++ b/docs/guide/ops/persistence/index.md
@@ -250,33 +250,76 @@ Writing Persistable Code
 The most common problem on rebind is that custom entity code has not been 
written in a way
 that can be persisted and/or rebound.
 
-The rule of thumb when implementing new entities, locations and policies is 
that all state
-must be persistable. All state must be stored as config or as attributes, and 
must be
-serializable (e.g. avoid the use of anonymous inner classes).
+The rule of thumb when implementing new entities, locations, policies and 
enrichers is that 
+all state must be persistable. All state must be stored as config or as 
attributes, and must be
+serializable. For making backwards compatibility simpler, the persisted state 
should be clean.
 
-Below is a guide for when implementing an entity in Java (or any other JVM 
language):
+Below are tips and best practices for when implementing an entity in Java (or 
any other 
+JVM language).
 
-* Don't store state in artibrary fields - the field will not be persisted 
(this is a design
+How to store entity state:
+
+* Config keys and values are persisted.
+* Store an entity's runtime state as attributes.
+* Don't store state in arbitrary fields - the field will not be persisted 
(this is a design
   decision, because Brooklyn cannot intercept the field being written to, so 
cannot know
   when to persist).
-* Store runtime state as attributes.
+* Don't just modify the retrieved attribute value (e.g. 
`getAttribute(MY_LIST).add("a")` is bad).
+  The value may not be persisted unless setAttribute() is called.
+* For special cases, it is possible to call `entity.requestPerist()` which 
will trigger
+  asynchronous persistence of the entity.
+* Overriding (and customizing) of `getRebindSupport()` is discouraged - this 
will change
+  in a future version.
+
+
+How to store policy/enricher/location state:
+
+* Store values as config keys where applicable.
+* Unfortunately these (currently) do not have attributes. Normally the state 
of a policy 
+  or enricher is transient - on rebind it starts afresh, for example with 
monitoring the 
+  performance or health metrics rather than relying on the persisted values.
+* For special cases, you can annotate a field with `@SetFromFlag` for it be 
persisted. 
+  When you call `requestPersist()` then values of these fields will be 
scheduled to be 
+  persisted. *Warning: the `@SetFromFlag` functionality may change in future 
versions.*
+
+Persistable state:
+
 * Ensure values can be serialized. This (currently) uses xstream, which means 
it does not
-  need to implement `Serializable`. However, if declaring your own classes 
that are to be
-  persisted as state of the entity then declare them as static (or top-level) 
classes 
-  rather than anonymous inner classes or non-static inner classes.
+  need to implement `Serializable`.
+* Always use static (or top-level) classes. Otherwise it will try to also 
persist the outer 
+  instance!
+* Any reference to an entity or location will be automatically swapped out for 
marker, and 
+  re-injected with the new entity/location instance on rebind. The same 
applies for policies,
+  enrichers, feeds, catalog items and `ManagementContext`.
+
+Behaviour on rebind:
+
 * By extending `SoftwareProcess`, entities get a lot of the rebind logic for 
free. For 
   example, the default `rebind()` method will call `connectSensors()`.
+  See [`SoftwareProcess` 
Lifecycle]({{site.path.guide}}/java/entities.html#SoftwareProcess-lifecycle)
+  for more details.
 * If necessary, implement rebind. The `entity.rebind()` is called 
automatically by the
   Brooklyn framework on rebind, after configuring the entity's 
config/attributes but before 
   the entity is managed.
   Note that `init()` will not be called on rebind.
-* For special cases, it is possible to call `entity.requestPerist()` which 
will trigger
-  asynchronous persistence of the entity.
-
-For locations, policies and enrichers they (currently) do not have attributes. 
However,
-config is persisted automatically. Normally the state of a policy or enricher 
is transient - 
-on rebind it starts afresh, for example with monitoring the performance or 
health metrics
-rather than relying on the persisted values.
+* Feeds will be persisted if and only if `entity.addFeed(...)` was called. 
Otherwise the
+  feed needs to be re-registered on rebind. *Warning: this behaviour may 
change in future version.*
+* All functions/predicates used with persisted feeds must themselves be 
persistable - 
+  use of anonymous inner classes is strongly discouraged.
+* Subscriptions (e.g. from calls to `subscribe(...)` for sensor events) are 
not persisted.
+  They must be re-registered on rebind.  *Warning: this behaviour may change 
in future version.*
+
+Below are tips to make backwards-compatibility easier for persisted state: 
+
+* Never use anonymous inner classes - even in static contexts. The 
auto-generated class names 
+  are brittle, making backwards compatibility harder.
+* Always use sensible field names (and use `transient` whenever you don't want 
it persisted).
+  The field names are part of the persisted state.
+* Consider using Value Objects for persisted values. This can give clearer 
separation of 
+  responsibilities in your code, and clearer control of what fields are being 
persisted.
+* Consider writing transformers to handle backwards-incompatible code changes.
+  Brooklyn supports applying transformations to the persisted state, which can 
be done as 
+  part of an upgrade process.
 
 
 Persisted State Backup

Reply via email to