You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/07/03 11:42:11 UTC

[1/6] git commit: BROOKLYN-14: exception handling for rebind policies

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 7ddca7248 -> abf21bdc4


BROOKLYN-14: exception handling for rebind policies

- Also adds PersistenceExceptionHandler


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

Branch: refs/heads/master
Commit: 391b3bb84ab0c325332846aadb3c58710030a010
Parents: 40c69e5
Author: Aled Sage <al...@gmail.com>
Authored: Mon Jun 30 15:30:33 2014 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Mon Jun 30 21:53:16 2014 +0100

----------------------------------------------------------------------
 .../rebind/PersistenceExceptionHandler.java     |  32 +++
 .../brooklyn/entity/rebind/RebindContext.java   |   3 +-
 .../entity/rebind/RebindExceptionHandler.java   |  15 ++
 .../brooklyn/entity/rebind/RebindManager.java   |   2 +
 .../mementos/BrooklynMementoPersister.java      |   7 +-
 .../entity/rebind/BasicEntityRebindSupport.java |  18 +-
 .../rebind/ImmediateDeltaChangeListener.java    |  22 ++-
 .../rebind/PeriodicDeltaChangeListener.java     |  24 +--
 .../rebind/PersistenceExceptionHandlerImpl.java | 102 ++++++++++
 .../entity/rebind/RebindContextImpl.java        |  21 +-
 .../rebind/RebindExceptionHandlerImpl.java      | 196 +++++++++++++++++--
 .../entity/rebind/RebindManagerImpl.java        |  54 ++++-
 .../AbstractBrooklynMementoPersister.java       |   5 +-
 .../BrooklynMementoPersisterInMemory.java       |  22 ++-
 .../BrooklynMementoPersisterToFile.java         |   9 +-
 .../BrooklynMementoPersisterToMultiFile.java    |  19 +-
 .../BrooklynMementoPersisterToObjectStore.java  |  55 +++---
 .../NonDeploymentManagementContext.java         |   6 +
 .../entity/rebind/RebindFailuresTest.java       |  78 ++++++++
 .../brooklyn/entity/rebind/RebindTestUtils.java |   8 +-
 .../rebind/RecordingRebindExceptionHandler.java |   2 +-
 .../BrooklynMementoPersisterTestFixture.java    |   2 +-
 ...BrooklynMementoPersisterToMultiFileTest.java |   3 +-
 .../HighAvailabilityManagerSplitBrainTest.java  |   3 +-
 .../ha/HighAvailabilityManagerTestFixture.java  |   3 +-
 .../AbstractWebAppFixtureIntegrationTest.java   |   5 +-
 .../brooklyn/launcher/BrooklynLauncher.java     |   5 +-
 27 files changed, 608 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/api/src/main/java/brooklyn/entity/rebind/PersistenceExceptionHandler.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/entity/rebind/PersistenceExceptionHandler.java b/api/src/main/java/brooklyn/entity/rebind/PersistenceExceptionHandler.java
new file mode 100644
index 0000000..4f8cbce
--- /dev/null
+++ b/api/src/main/java/brooklyn/entity/rebind/PersistenceExceptionHandler.java
@@ -0,0 +1,32 @@
+package brooklyn.entity.rebind;
+
+import brooklyn.entity.Entity;
+import brooklyn.location.Location;
+import brooklyn.mementos.Memento;
+import brooklyn.policy.Enricher;
+import brooklyn.policy.Policy;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Handler called on all exceptions to do with persistence.
+ * 
+ * @author aled
+ */
+@Beta
+public interface PersistenceExceptionHandler {
+
+    void stop();
+
+    void onGenerateLocationMementoFailed(Location location, Exception e);
+
+    void onGenerateEntityMementoFailed(Entity entity, Exception e);
+    
+    void onGeneratePolicyMementoFailed(Policy policy, Exception e);
+    
+    void onGenerateEnricherMementoFailed(Enricher enricher, Exception e);
+
+    void onPersistMementoFailed(Memento memento, Exception e);
+    
+    void onDeleteMementoFailed(String id, Exception e);
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/api/src/main/java/brooklyn/entity/rebind/RebindContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/entity/rebind/RebindContext.java b/api/src/main/java/brooklyn/entity/rebind/RebindContext.java
index 2d8e364..a94f907 100644
--- a/api/src/main/java/brooklyn/entity/rebind/RebindContext.java
+++ b/api/src/main/java/brooklyn/entity/rebind/RebindContext.java
@@ -25,5 +25,6 @@ public interface RebindContext {
     Enricher getEnricher(String id);
 
     Class<?> loadClass(String typeName) throws ClassNotFoundException;
-
+    
+    RebindExceptionHandler getExceptionHandler();
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/api/src/main/java/brooklyn/entity/rebind/RebindExceptionHandler.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/entity/rebind/RebindExceptionHandler.java b/api/src/main/java/brooklyn/entity/rebind/RebindExceptionHandler.java
index 016dc66..48ff96a 100644
--- a/api/src/main/java/brooklyn/entity/rebind/RebindExceptionHandler.java
+++ b/api/src/main/java/brooklyn/entity/rebind/RebindExceptionHandler.java
@@ -1,6 +1,7 @@
 package brooklyn.entity.rebind;
 
 import brooklyn.entity.Entity;
+import brooklyn.entity.basic.EntityLocal;
 import brooklyn.location.Location;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.Policy;
@@ -51,18 +52,32 @@ public interface RebindExceptionHandler {
 
     void onCreatePolicyFailed(String id, String type, Exception e);
 
+    void onCreateEnricherFailed(String id, String type, Exception e);
+
     void onLocationNotFound(String id);
     
     void onEntityNotFound(String id);
     
     void onPolicyNotFound(String id);
 
+    void onPolicyNotFound(String id, String context);
+
+    void onEnricherNotFound(String id);
+
+    void onEnricherNotFound(String id, String context);
+
     void onRebindEntityFailed(Entity entity, Exception e);
 
     void onRebindLocationFailed(Location location, Exception e);
 
     void onRebindPolicyFailed(Policy policy, Exception e);
 
+    void onRebindEnricherFailed(Enricher enricher, Exception e);
+
+    void onAddPolicyFailed(EntityLocal entity, Policy policy, Exception e);
+
+    void onAddEnricherFailed(EntityLocal entity, Enricher enricher, Exception e);
+
     void onManageLocationFailed(Location location, Exception e);
 
     void onManageEntityFailed(Entity entity, Exception e);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/api/src/main/java/brooklyn/entity/rebind/RebindManager.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/entity/rebind/RebindManager.java b/api/src/main/java/brooklyn/entity/rebind/RebindManager.java
index c390a46..fb4462d 100644
--- a/api/src/main/java/brooklyn/entity/rebind/RebindManager.java
+++ b/api/src/main/java/brooklyn/entity/rebind/RebindManager.java
@@ -32,6 +32,8 @@ public interface RebindManager {
     
     public void setPersister(BrooklynMementoPersister persister);
 
+    public void setPersister(BrooklynMementoPersister persister, PersistenceExceptionHandler exceptionHandler);
+
     @VisibleForTesting
     public BrooklynMementoPersister getPersister();
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/api/src/main/java/brooklyn/mementos/BrooklynMementoPersister.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/mementos/BrooklynMementoPersister.java b/api/src/main/java/brooklyn/mementos/BrooklynMementoPersister.java
index 94630ed..016c10f 100644
--- a/api/src/main/java/brooklyn/mementos/BrooklynMementoPersister.java
+++ b/api/src/main/java/brooklyn/mementos/BrooklynMementoPersister.java
@@ -6,6 +6,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import brooklyn.entity.Entity;
+import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandler;
 import brooklyn.entity.rebind.RebindManager;
 import brooklyn.location.Location;
@@ -37,9 +38,9 @@ public interface BrooklynMementoPersister {
      */
     BrooklynMemento loadMemento(LookupContext lookupContext, RebindExceptionHandler exceptionHandler) throws IOException;
     
-    void checkpoint(BrooklynMemento memento);
-    
-    void delta(Delta delta);
+    void checkpoint(BrooklynMemento memento, PersistenceExceptionHandler exceptionHandler);
+
+    void delta(Delta delta, PersistenceExceptionHandler exceptionHandler);
 
     void stop();
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
index 0bb51f3..fe17217 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
@@ -160,10 +160,13 @@ public class BasicEntityRebindSupport implements RebindSupport<EntityMemento> {
         for (String policyId : memento.getPolicies()) {
             AbstractPolicy policy = (AbstractPolicy) rebindContext.getPolicy(policyId);
             if (policy != null) {
-                entity.addPolicy(policy);
+                try {
+                    entity.addPolicy(policy);
+                } catch (Exception e) {
+                    rebindContext.getExceptionHandler().onAddPolicyFailed(entity, policy, e);
+                }
             } else {
-                LOG.warn("Policy not found; discarding policy {} of entity {}({})",
-                        new Object[] {policyId, memento.getType(), memento.getId()});
+                rebindContext.getExceptionHandler().onPolicyNotFound(policyId, "of entity "+entity);
             }
         }
     }
@@ -172,10 +175,13 @@ public class BasicEntityRebindSupport implements RebindSupport<EntityMemento> {
         for (String enricherId : memento.getEnrichers()) {
             AbstractEnricher enricher = (AbstractEnricher) rebindContext.getEnricher(enricherId);
             if (enricher != null) {
-                entity.addEnricher(enricher);
+                try {
+                    entity.addEnricher(enricher);
+                } catch (Exception e) {
+                    rebindContext.getExceptionHandler().onAddEnricherFailed(entity, enricher, e);
+                }
             } else {
-                LOG.warn("Enricher not found; discarding enricher {} of entity {}({})",
-                        new Object[] {enricherId, memento.getType(), memento.getId()});
+                rebindContext.getExceptionHandler().onEnricherNotFound(enricherId, "of entity "+entity);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/ImmediateDeltaChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/ImmediateDeltaChangeListener.java b/core/src/main/java/brooklyn/entity/rebind/ImmediateDeltaChangeListener.java
index 36df495..f54eb80 100644
--- a/core/src/main/java/brooklyn/entity/rebind/ImmediateDeltaChangeListener.java
+++ b/core/src/main/java/brooklyn/entity/rebind/ImmediateDeltaChangeListener.java
@@ -19,15 +19,21 @@ import com.google.common.collect.Maps;
  * (for any serializing / file-based persister implementation).
  * 
  * @author aled
+ * 
+ * @deprecated since 0.7; unused code
  */
+@Deprecated
 public class ImmediateDeltaChangeListener implements ChangeListener {
 
     private final BrooklynMementoPersister persister;
+    private final PersistenceExceptionHandler exceptionHandler;
     
     private volatile boolean running = true;
 
     public ImmediateDeltaChangeListener(BrooklynMementoPersister persister) {
         this.persister = persister;
+        exceptionHandler = PersistenceExceptionHandlerImpl.builder()
+                .build();
     }
     
     @Override
@@ -94,7 +100,7 @@ public class ImmediateDeltaChangeListener implements ChangeListener {
              */
             synchronized (new Object()) {}
 
-            persister.delta(delta);
+            persister.delta(delta, exceptionHandler);
         }
     }
     
@@ -103,7 +109,7 @@ public class ImmediateDeltaChangeListener implements ChangeListener {
         if (running && persister != null) {
             PersisterDeltaImpl delta = new PersisterDeltaImpl();
             delta.removedEntityIds.add(entity.getId());
-            persister.delta(delta);
+            persister.delta(delta, exceptionHandler);
         }
     }
 
@@ -112,7 +118,7 @@ public class ImmediateDeltaChangeListener implements ChangeListener {
         if (running && persister != null) {
             PersisterDeltaImpl delta = new PersisterDeltaImpl();
             delta.removedLocationIds.add(location.getId());
-            persister.delta(delta);
+            persister.delta(delta, exceptionHandler);
         }
     }
 
@@ -121,7 +127,7 @@ public class ImmediateDeltaChangeListener implements ChangeListener {
         if (running && persister != null) {
             PersisterDeltaImpl delta = new PersisterDeltaImpl();
             delta.removedPolicyIds.add(policy.getId());
-            persister.delta(delta);
+            persister.delta(delta, exceptionHandler);
         }
     }
 
@@ -130,7 +136,7 @@ public class ImmediateDeltaChangeListener implements ChangeListener {
         if (running && persister != null) {
             PersisterDeltaImpl delta = new PersisterDeltaImpl();
             delta.removedEnricherIds.add(enricher.getId());
-            persister.delta(delta);
+            persister.delta(delta, exceptionHandler);
         }
     }
 
@@ -139,7 +145,7 @@ public class ImmediateDeltaChangeListener implements ChangeListener {
         if (running && persister != null) {
             PersisterDeltaImpl delta = new PersisterDeltaImpl();
             delta.locations.add(((LocationInternal)location).getRebindSupport().getMemento());
-            persister.delta(delta);
+            persister.delta(delta, exceptionHandler);
         }
     }
     
@@ -148,7 +154,7 @@ public class ImmediateDeltaChangeListener implements ChangeListener {
         if (running && persister != null) {
             PersisterDeltaImpl delta = new PersisterDeltaImpl();
             delta.policies.add(policy.getRebindSupport().getMemento());
-            persister.delta(delta);
+            persister.delta(delta, exceptionHandler);
         }
     }
     
@@ -157,7 +163,7 @@ public class ImmediateDeltaChangeListener implements ChangeListener {
         if (running && persister != null) {
             PersisterDeltaImpl delta = new PersisterDeltaImpl();
             delta.enrichers.add(enricher.getRebindSupport().getMemento());
-            persister.delta(delta);
+            persister.delta(delta, exceptionHandler);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java b/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
index afb8565..9230d45 100644
--- a/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
+++ b/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
@@ -66,6 +66,8 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
     
     private final BrooklynMementoPersister persister;
 
+    private final PersistenceExceptionHandler exceptionHandler;
+    
     private final Duration period;
     
     private final AtomicLong writeCount = new AtomicLong();
@@ -83,9 +85,10 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
     
     private final Semaphore persistingMutex = new Semaphore(1);
     
-    public PeriodicDeltaChangeListener(ExecutionManager executionManager, BrooklynMementoPersister persister, long periodMillis) {
+    public PeriodicDeltaChangeListener(ExecutionManager executionManager, BrooklynMementoPersister persister, PersistenceExceptionHandler exceptionHandler, long periodMillis) {
         this.executionManager = executionManager;
         this.persister = persister;
+        this.exceptionHandler = exceptionHandler;
         this.period = Duration.of(periodMillis, TimeUnit.MILLISECONDS);
         
         this.persistPoliciesEnabled = BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_POLICY_PERSISTENCE_PROPERTY);
@@ -199,28 +202,28 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
                     try {
                         persisterDelta.locations.add(((LocationInternal)location).getRebindSupport().getMemento());
                     } catch (Exception e) {
-                        handleGenerateMementoException(e, "location "+location.getClass().getSimpleName()+"("+location.getId()+")");
+                        exceptionHandler.onGenerateLocationMementoFailed(location, e);
                     }
                 }
                 for (Entity entity : prevDeltaCollector.entities) {
                     try {
                         persisterDelta.entities.add(((EntityInternal)entity).getRebindSupport().getMemento());
                     } catch (Exception e) {
-                        handleGenerateMementoException(e, "entity "+entity.getEntityType().getSimpleName()+"("+entity.getId()+")");
+                        exceptionHandler.onGenerateEntityMementoFailed(entity, e);
                     }
                 }
                 for (Policy policy : prevDeltaCollector.policies) {
                     try {
                         persisterDelta.policies.add(policy.getRebindSupport().getMemento());
                     } catch (Exception e) {
-                        handleGenerateMementoException(e, "policy "+policy.getClass().getSimpleName()+"("+policy.getId()+")");
+                        exceptionHandler.onGeneratePolicyMementoFailed(policy, e);
                     }
                 }
                 for (Enricher enricher : prevDeltaCollector.enrichers) {
                     try {
                         persisterDelta.enrichers.add(enricher.getRebindSupport().getMemento());
                     } catch (Exception e) {
-                        handleGenerateMementoException(e, "enricher "+enricher.getClass().getSimpleName()+"("+enricher.getId()+")");
+                        exceptionHandler.onGenerateEnricherMementoFailed(enricher, e);
                     }
                 }
                 persisterDelta.removedLocationIds = prevDeltaCollector.removedLocationIds;
@@ -238,7 +241,7 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
                 synchronized (new Object()) {}
 
                 // Tell the persister to persist it
-                persister.delta(persisterDelta);
+                persister.delta(persisterDelta, exceptionHandler);
             }
         } catch (Exception e) {
             if (isActive()) {
@@ -253,15 +256,6 @@ public class PeriodicDeltaChangeListener implements ChangeListener {
         }
     }
     
-    protected void handleGenerateMementoException(Exception e, String context) {
-        Exceptions.propagateIfFatal(e);
-        if (isActive()) {
-            LOG.warn("Problem generating memento for "+context, e);
-        } else {
-            LOG.debug("Problem generating memento for "+context+", but no longer active (ignoring)", e);
-        }
-    }
-    
     @Override
     public synchronized void onManaged(Entity entity) {
         if (LOG.isTraceEnabled()) LOG.trace("onManaged: {}", entity);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/PersistenceExceptionHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/PersistenceExceptionHandlerImpl.java b/core/src/main/java/brooklyn/entity/rebind/PersistenceExceptionHandlerImpl.java
new file mode 100644
index 0000000..470bbb6
--- /dev/null
+++ b/core/src/main/java/brooklyn/entity/rebind/PersistenceExceptionHandlerImpl.java
@@ -0,0 +1,102 @@
+package brooklyn.entity.rebind;
+
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.Entity;
+import brooklyn.location.Location;
+import brooklyn.mementos.Memento;
+import brooklyn.policy.Enricher;
+import brooklyn.policy.Policy;
+import brooklyn.util.exceptions.Exceptions;
+
+import com.google.common.collect.Sets;
+
+public class PersistenceExceptionHandlerImpl implements PersistenceExceptionHandler {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PersistenceExceptionHandlerImpl.class);
+    
+    private final AtomicBoolean active = new AtomicBoolean(true);
+
+    private final Set<String> prevFailedMementoGenerators = Sets.newConcurrentHashSet();
+    private final Set<String> prevFailedPersisters = Sets.newConcurrentHashSet();
+    
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    // Builder is here to copy pattern in RebindExceptionHandler, and to make it easier to edit API in the future
+    public static class Builder {
+        public PersistenceExceptionHandler build() {
+            return new PersistenceExceptionHandlerImpl(this);
+        }
+    }
+    
+    public PersistenceExceptionHandlerImpl(Builder builder) {
+    }
+
+    @Override
+    public void stop() {
+        active.set(false);
+    }
+    
+    @Override
+    public void onGenerateEntityMementoFailed(Entity entity, Exception e) {
+        String errmsg = "generate memento for entity "+entity.getEntityType().getSimpleName()+"("+entity.getId()+")";
+        onErrorImpl(errmsg, e, prevFailedMementoGenerators.add(entity.getId()));
+    }
+    
+    @Override
+    public void onGenerateLocationMementoFailed(Location location, Exception e) {
+        String errmsg = "generate memento for location "+location.getClass().getSimpleName()+"("+location.getId()+")";
+        onErrorImpl(errmsg, e, prevFailedMementoGenerators.add(location.getId()));
+    }
+    
+    @Override
+    public void onGeneratePolicyMementoFailed(Policy policy, Exception e) {
+        String errmsg = "generate memento for policy "+policy.getClass().getSimpleName()+"("+policy.getId()+")";
+        onErrorImpl(errmsg, e, prevFailedMementoGenerators.add(policy.getId()));
+    }
+    
+    @Override
+    public void onGenerateEnricherMementoFailed(Enricher enricher, Exception e) {
+        String errmsg = "generate memento for enricher "+enricher.getClass().getSimpleName()+"("+enricher.getId()+")";
+        onErrorImpl(errmsg, e, prevFailedMementoGenerators.add(enricher.getId()));
+    }
+    
+    @Override
+    public void onPersistMementoFailed(Memento memento, Exception e) {
+        String errmsg = "persist for "+memento.getClass().getSimpleName()+" "+memento.getType()+"("+memento.getId()+")";
+        onErrorImpl(errmsg, e, prevFailedPersisters.add(memento.getId()));
+    }
+    
+    @Override
+    public void onDeleteMementoFailed(String id, Exception e) {
+        String errmsg = "delete for memento "+id;
+        onErrorImpl(errmsg, e, prevFailedPersisters.add(id));
+    }
+    
+    protected void onErrorImpl(String errmsg, Exception e, boolean isRepeat) {
+        Exceptions.propagateIfFatal(e);
+        if (isActive()) {
+            if (isRepeat) {
+                if (LOG.isDebugEnabled()) LOG.debug("Repeating problem: "+errmsg, e);
+            } else {
+                LOG.warn("Problem: "+errmsg, e);
+            }
+        } else {
+            if (isRepeat) {
+                if (LOG.isTraceEnabled()) LOG.trace("Repeating problem: "+errmsg+"; but no longer active (ignoring)", e);
+            } else {
+                if (LOG.isDebugEnabled()) LOG.debug("Problem: "+errmsg+"; but no longer active (ignoring)", e);
+            }
+        }
+    }
+
+    protected boolean isActive() {
+        return active.get();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
index 30c88ab..8393f53 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindContextImpl.java
@@ -1,5 +1,7 @@
 package brooklyn.entity.rebind;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import java.util.Map;
 
 import brooklyn.entity.Entity;
@@ -16,9 +18,11 @@ public class RebindContextImpl implements RebindContext {
     private final Map<String, Policy> policies = Maps.newLinkedHashMap();
     private final Map<String, Enricher> enrichers = Maps.newLinkedHashMap();
     private final ClassLoader classLoader;
+    private final RebindExceptionHandler exceptionHandler;
     
-    public RebindContextImpl(ClassLoader classLoader) {
-        this.classLoader = classLoader;
+    public RebindContextImpl(RebindExceptionHandler exceptionHandler, ClassLoader classLoader) {
+        this.exceptionHandler = checkNotNull(exceptionHandler, "exceptionHandler");
+        this.classLoader = checkNotNull(classLoader, "classLoader");
     }
 
     public void registerEntity(String id, Entity entity) {
@@ -37,6 +41,14 @@ public class RebindContextImpl implements RebindContext {
         enrichers.put(id, enricher);
     }
     
+    public void unregisterPolicy(Policy policy) {
+        policies.remove(policy.getId());
+    }
+
+    public void unregisterEnricher(Enricher enricher) {
+        enrichers.remove(enricher.getId());
+    }
+
     @Override
     public Entity getEntity(String id) {
         return entities.get(id);
@@ -61,4 +73,9 @@ public class RebindContextImpl implements RebindContext {
     public Class<?> loadClass(String className) throws ClassNotFoundException {
         return classLoader.loadClass(className);
     }
+
+    @Override
+    public RebindExceptionHandler getExceptionHandler() {
+        return exceptionHandler;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/RebindExceptionHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindExceptionHandlerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindExceptionHandlerImpl.java
index aaf8645..937d58d 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindExceptionHandlerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindExceptionHandlerImpl.java
@@ -9,6 +9,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import brooklyn.entity.Entity;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.rebind.RebindManager.RebindFailureMode;
 import brooklyn.location.Location;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.Policy;
@@ -20,13 +22,12 @@ import com.google.common.collect.Sets;
 
 public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
 
-    // TODO should we have just a single List<Exception> field, rather than separating out
-    // all the exception types?
-    
     private static final Logger LOG = LoggerFactory.getLogger(RebindExceptionHandlerImpl.class);
 
     protected final RebindManager.RebindFailureMode danglingRefFailureMode;
     protected final RebindManager.RebindFailureMode rebindFailureMode;
+    protected final RebindFailureMode addPolicyFailureMode;
+    protected final RebindFailureMode loadPolicyFailureMode;
 
     protected final Set<String> missingEntities = Sets.newLinkedHashSet();
     protected final Set<String> missingLocations = Sets.newLinkedHashSet();
@@ -35,13 +36,49 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
     protected final Set<String> creationFailedEntities = Sets.newLinkedHashSet();
     protected final Set<String> creationFailedLocations = Sets.newLinkedHashSet();
     protected final Set<String> creationFailedPolicies = Sets.newLinkedHashSet();
+    protected final Set<String> creationFailedEnrichers = Sets.newLinkedHashSet();
+    protected final Set<Exception> addPolicyFailures = Sets.newLinkedHashSet();
+    protected final Set<Exception> loadPolicyFailures = Sets.newLinkedHashSet();
     protected final List<Exception> exceptions = Lists.newArrayList();
     
-    public RebindExceptionHandlerImpl(RebindManager.RebindFailureMode danglingRefFailureMode, RebindManager.RebindFailureMode rebindFailureMode) {
-        this.danglingRefFailureMode = checkNotNull(danglingRefFailureMode, "danglingRefFailureMode");
-        this.rebindFailureMode = checkNotNull(rebindFailureMode, "rebindFailureMode");
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private RebindManager.RebindFailureMode danglingRefFailureMode = RebindManager.RebindFailureMode.CONTINUE;
+        private RebindManager.RebindFailureMode rebindFailureMode = RebindManager.RebindFailureMode.FAIL_AT_END;
+        private RebindManager.RebindFailureMode addPolicyFailureMode = RebindManager.RebindFailureMode.CONTINUE;
+        private RebindManager.RebindFailureMode deserializePolicyFailureMode = RebindManager.RebindFailureMode.CONTINUE;
+
+        public Builder danglingRefFailureMode(RebindManager.RebindFailureMode val) {
+            danglingRefFailureMode = val;
+            return this;
+        }
+        public Builder rebindFailureMode(RebindManager.RebindFailureMode val) {
+            rebindFailureMode = val;
+            return this;
+        }
+        public Builder addPolicyFailureMode(RebindManager.RebindFailureMode val) {
+            addPolicyFailureMode = val;
+            return this;
+        }
+        public Builder loadPolicyFailureMode(RebindManager.RebindFailureMode val) {
+            deserializePolicyFailureMode = val;
+            return this;
+        }
+        public RebindExceptionHandler build() {
+            return new RebindExceptionHandlerImpl(this);
+        }
     }
 
+    public RebindExceptionHandlerImpl(Builder builder) {
+        this.danglingRefFailureMode = checkNotNull(builder.danglingRefFailureMode, "danglingRefFailureMode");
+        this.rebindFailureMode = checkNotNull(builder.rebindFailureMode, "rebindFailureMode");
+        this.addPolicyFailureMode = checkNotNull(builder.addPolicyFailureMode, "addPolicyFailureMode");
+        this.loadPolicyFailureMode = checkNotNull(builder.deserializePolicyFailureMode, "deserializePolicyFailureMode");
+    }
+    
     @Override
     public void onLoadBrooklynMementoFailed(String msg, Exception e) {
         onLoadMementoFailure(msg, e);
@@ -59,17 +96,45 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
     
     @Override
     public void onLoadPolicyMementoFailed(String msg, Exception e) {
-        onLoadMementoFailure(msg, e);
+        Exceptions.propagateIfFatal(e);
+        String errmsg = "problem loading memento: "+msg;
+        
+        switch (loadPolicyFailureMode) {
+        case FAIL_FAST:
+            throw new IllegalStateException("Rebind: aborting due to "+errmsg, e);
+        case FAIL_AT_END:
+            loadPolicyFailures.add(new IllegalStateException(errmsg, e));
+            break;
+        case CONTINUE:
+            LOG.warn(errmsg+"; continuing", e);
+            break;
+        default:
+            throw new IllegalStateException("Unexpected state '"+loadPolicyFailureMode+"' for loadPolicyFailureMode");
+        }
     }
     
     @Override
     public void onLoadEnricherMementoFailed(String msg, Exception e) {
-        onLoadMementoFailure(msg, e);
+        Exceptions.propagateIfFatal(e);
+        String errmsg = "problem loading memento: "+msg;
+        
+        switch (loadPolicyFailureMode) {
+        case FAIL_FAST:
+            throw new IllegalStateException("Rebind: aborting due to "+errmsg, e);
+        case FAIL_AT_END:
+            loadPolicyFailures.add(new IllegalStateException(errmsg, e));
+            break;
+        case CONTINUE:
+            LOG.warn(errmsg+"; continuing", e);
+            break;
+        default:
+            throw new IllegalStateException("Unexpected state '"+loadPolicyFailureMode+"' for loadPolicyFailureMode");
+        }
     }
     
     protected void onLoadMementoFailure(String msg, Exception e) {
         Exceptions.propagateIfFatal(e);
-        String errmsg = "problem loading mementos: "+msg;
+        String errmsg = "problem loading memento: "+msg;
         exceptions.add(new IllegalStateException(errmsg, e));
         onErrorImpl(errmsg, e);
     }
@@ -145,6 +210,15 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
         exceptions.add(new IllegalStateException(errmsg, e));
         onErrorImpl(errmsg, e);
     }
+    
+    @Override
+    public void onCreateEnricherFailed(String id, String type, Exception e) {
+        Exceptions.propagateIfFatal(e);
+        String errmsg = "problem creating policy "+id+" of type "+type;
+        creationFailedEnrichers.add(id);
+        exceptions.add(new IllegalStateException(errmsg, e));
+        onErrorImpl(errmsg, e);
+    }
 
     @Override
     public void onLocationNotFound(String id) {
@@ -167,13 +241,34 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
             onErrorImpl(errmsg);
         }
     }
-    
+
     @Override
     public void onPolicyNotFound(String id) {
+        onPolicyNotFound(id, null);
+    }
+    
+    @Override
+    public void onPolicyNotFound(String id, String context) {
         if (creationFailedPolicies.contains(id)) {
             // already know about this; ignore
         } else {
-            String errmsg = "policy'"+id+"' not found";
+            String errmsg = "policy '"+id+"' not found" + (context == null ? "" : "("+context+")");
+            exceptions.add(new IllegalStateException(errmsg));
+            onErrorImpl(errmsg);
+        }
+    }
+
+    @Override
+    public void onEnricherNotFound(String id) {
+        onEnricherNotFound(id, null);
+    }
+    
+    @Override
+    public void onEnricherNotFound(String id, String context) {
+        if (creationFailedEnrichers.contains(id)) {
+            // already know about this; ignore
+        } else {
+            String errmsg = "enricher '"+id+"' not found" + (context == null ? "" : "("+context+")");
             exceptions.add(new IllegalStateException(errmsg));
             onErrorImpl(errmsg);
         }
@@ -202,8 +297,77 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
         Exceptions.propagateIfFatal(e);
         String errmsg = "problem rebinding plicy "+policy.getId()+" ("+policy+")";
         
-        exceptions.add(new IllegalStateException(errmsg, e));
-        onErrorImpl(errmsg, e);
+        switch (addPolicyFailureMode) {
+        case FAIL_FAST:
+            throw new IllegalStateException("Rebind: aborting due to "+errmsg, e);
+        case FAIL_AT_END:
+            addPolicyFailures.add(new IllegalStateException(errmsg, e));
+            break;
+        case CONTINUE:
+            LOG.warn(errmsg+"; continuing", e);
+            creationFailedPolicies.add(policy.getId());
+            break;
+        default:
+            throw new IllegalStateException("Unexpected state '"+addPolicyFailureMode+"' for addPolicyFailureMode");
+        }
+    }
+
+    @Override
+    public void onRebindEnricherFailed(Enricher enricher, Exception e) {
+        Exceptions.propagateIfFatal(e);
+        String errmsg = "problem rebinding enricher "+enricher.getId()+" ("+enricher+")";
+        
+        switch (addPolicyFailureMode) {
+        case FAIL_FAST:
+            throw new IllegalStateException("Rebind: aborting due to "+errmsg, e);
+        case FAIL_AT_END:
+            addPolicyFailures.add(new IllegalStateException(errmsg, e));
+            break;
+        case CONTINUE:
+            LOG.warn(errmsg+"; continuing", e);
+            creationFailedEnrichers.add(enricher.getId());
+            break;
+        default:
+            throw new IllegalStateException("Unexpected state '"+addPolicyFailureMode+"' for addPolicyFailureMode");
+        }
+    }
+
+    @Override
+    public void onAddPolicyFailed(EntityLocal entity, Policy policy, Exception e) {
+        Exceptions.propagateIfFatal(e);
+        String errmsg = "problem adding policy "+policy.getId()+" ("+policy+") to entity "+entity.getId()+" ("+entity+")";
+        
+        switch (addPolicyFailureMode) {
+        case FAIL_FAST:
+            throw new IllegalStateException("Rebind: aborting due to "+errmsg, e);
+        case FAIL_AT_END:
+            addPolicyFailures.add(new IllegalStateException(errmsg, e));
+            break;
+        case CONTINUE:
+            LOG.warn(errmsg+"; continuing", e);
+            break;
+        default:
+            throw new IllegalStateException("Unexpected state '"+addPolicyFailureMode+"' for addPolicyFailureMode");
+        }
+    }
+
+    @Override
+    public void onAddEnricherFailed(EntityLocal entity, Enricher enricher, Exception e) {
+        Exceptions.propagateIfFatal(e);
+        String errmsg = "problem adding enricher "+enricher.getId()+" ("+enricher+") to entity "+entity.getId()+" ("+entity+")";
+
+        switch (addPolicyFailureMode) {
+        case FAIL_FAST:
+            throw new IllegalStateException("Rebind: aborting due to "+errmsg, e);
+        case FAIL_AT_END:
+            addPolicyFailures.add(new IllegalStateException(errmsg, e));
+            break;
+        case CONTINUE:
+            LOG.warn(errmsg+"; continuing", e);
+            break;
+        default:
+            throw new IllegalStateException("Unexpected state '"+addPolicyFailureMode+"' for addPolicyFailureMode");
+        }
     }
 
     @Override
@@ -255,6 +419,12 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
         if (e != null) {
             allExceptions.add(e);
         }
+        if (addPolicyFailureMode != RebindManager.RebindFailureMode.CONTINUE) {
+            allExceptions.addAll(addPolicyFailures);
+        }
+        if (loadPolicyFailureMode != RebindManager.RebindFailureMode.CONTINUE) {
+            allExceptions.addAll(loadPolicyFailures);
+        }
         if (danglingRefFailureMode != RebindManager.RebindFailureMode.CONTINUE) {
             if (missingEntities.size() > 0) {
                 allExceptions.add(new IllegalStateException("Missing referenced entit"+(missingEntities.size() == 1 ? "y" : "ies")+": "+missingEntities));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index b1c5465..81c4f7b 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -74,6 +74,12 @@ public class RebindManagerImpl implements RebindManager {
     public static final ConfigKey<RebindFailureMode> REBIND_FAILURE_MODE =
             ConfigKeys.newConfigKey(RebindFailureMode.class, "rebind.failureMode.rebind",
                     "Action to take if a failure occurs during rebind", RebindFailureMode.FAIL_AT_END);
+    public static final ConfigKey<RebindFailureMode> ADD_POLICY_FAILURE_MODE =
+            ConfigKeys.newConfigKey(RebindFailureMode.class, "rebind.failureMode.addPolicy",
+                    "Action to take if a failure occurs when adding a policy or enricher", RebindFailureMode.CONTINUE);
+    public static final ConfigKey<RebindFailureMode> LOAD_POLICY_FAILURE_MODE =
+            ConfigKeys.newConfigKey(RebindFailureMode.class, "rebind.failureMode.loadPolicy",
+                    "Action to take if a failure occurs when loading a policy or enricher", RebindFailureMode.CONTINUE);
     
     public static final Logger LOG = LoggerFactory.getLogger(RebindManagerImpl.class);
 
@@ -92,6 +98,8 @@ public class RebindManagerImpl implements RebindManager {
     private final boolean persistEnrichersEnabled;
     private RebindFailureMode danglingRefFailureMode;
     private RebindFailureMode rebindFailureMode;
+    private RebindFailureMode addPolicyFailureMode;
+    private RebindFailureMode loadPolicyFailureMode;
 
     /**
      * For tracking if rebinding, for {@link AbstractEnricher#isRebinding()} etc.
@@ -125,6 +133,8 @@ public class RebindManagerImpl implements RebindManager {
 
         danglingRefFailureMode = managementContext.getConfig().getConfig(DANGLING_REFERENCE_FAILURE_MODE);
         rebindFailureMode = managementContext.getConfig().getConfig(REBIND_FAILURE_MODE);
+        addPolicyFailureMode = managementContext.getConfig().getConfig(ADD_POLICY_FAILURE_MODE);
+        loadPolicyFailureMode = managementContext.getConfig().getConfig(LOAD_POLICY_FAILURE_MODE);
     }
 
     /**
@@ -144,12 +154,19 @@ public class RebindManagerImpl implements RebindManager {
 
     @Override
     public void setPersister(BrooklynMementoPersister val) {
+        PersistenceExceptionHandler exceptionHandler = PersistenceExceptionHandlerImpl.builder()
+                .build();
+        setPersister(val, exceptionHandler);
+    }
+
+    @Override
+    public void setPersister(BrooklynMementoPersister val, PersistenceExceptionHandler exceptionHandler) {
         if (persister != null && persister != val) {
             throw new IllegalStateException("Dynamically changing persister is not supported: old="+persister+"; new="+val);
         }
         this.persister = checkNotNull(val, "persister");
         
-        this.realChangeListener = new PeriodicDeltaChangeListener(managementContext.getExecutionManager(), persister, periodicPersistPeriod.toMilliseconds());
+        this.realChangeListener = new PeriodicDeltaChangeListener(managementContext.getExecutionManager(), persister, exceptionHandler, periodicPersistPeriod.toMilliseconds());
         this.changeListener = new SafeChangeListener(realChangeListener);
         
         if (running) {
@@ -206,7 +223,12 @@ public class RebindManagerImpl implements RebindManager {
     
     @Override
     public List<Application> rebind(final ClassLoader classLoader) throws IOException {
-        RebindExceptionHandler exceptionHandler = new RebindExceptionHandlerImpl(danglingRefFailureMode, rebindFailureMode);
+        RebindExceptionHandler exceptionHandler = RebindExceptionHandlerImpl.builder()
+                .danglingRefFailureMode(danglingRefFailureMode)
+                .rebindFailureMode(rebindFailureMode)
+                .addPolicyFailureMode(addPolicyFailureMode)
+                .loadPolicyFailureMode(loadPolicyFailureMode)
+                .build();
         return rebind(classLoader, exceptionHandler);
     }
 
@@ -240,7 +262,7 @@ public class RebindManagerImpl implements RebindManager {
             Map<String,Policy> policies = Maps.newLinkedHashMap();
             Map<String,Enricher> enrichers = Maps.newLinkedHashMap();
             
-            final RebindContextImpl rebindContext = new RebindContextImpl(classLoader);
+            final RebindContextImpl rebindContext = new RebindContextImpl(exceptionHandler, classLoader);
             LookupContext realLookupContext = new RebindContextLookupContext(managementContext, rebindContext, exceptionHandler);
             
             // Two-phase deserialization.
@@ -310,10 +332,14 @@ public class RebindManagerImpl implements RebindManager {
                 LOG.debug("RebindManager instantiating enrichers: {}", memento.getEnricherIds());
                 for (EnricherMemento enricherMemento : memento.getEnricherMementos().values()) {
                     if (LOG.isDebugEnabled()) LOG.debug("RebindManager instantiating enricher {}", enricherMemento);
-                    
-                    Enricher enricher = newEnricher(enricherMemento, reflections);
-                    enrichers.put(enricherMemento.getId(), enricher);
-                    rebindContext.registerEnricher(enricherMemento.getId(), enricher);
+
+                    try {
+                        Enricher enricher = newEnricher(enricherMemento, reflections);
+                        enrichers.put(enricherMemento.getId(), enricher);
+                        rebindContext.registerEnricher(enricherMemento.getId(), enricher);
+                    } catch (Exception e) {
+                        exceptionHandler.onCreateEnricherFailed(enricherMemento.getId(), enricherMemento.getType(), e);
+                    }
                 }
             } else {
                 LOG.debug("Not rebinding enrichers; feature disabled: {}", memento.getEnricherIds());
@@ -351,6 +377,7 @@ public class RebindManagerImpl implements RebindManager {
                             policy.getRebindSupport().reconstruct(rebindContext, policyMemento);
                         } catch (Exception e) {
                             exceptionHandler.onRebindPolicyFailed(policy, e);
+                            rebindContext.unregisterPolicy(policy);
                         }
                     }
                 }
@@ -363,7 +390,18 @@ public class RebindManagerImpl implements RebindManager {
                     Enricher enricher = rebindContext.getEnricher(enricherMemento.getId());
                     if (LOG.isDebugEnabled()) LOG.debug("RebindManager reconstructing enricher {}", enricherMemento);
         
-                    enricher.getRebindSupport().reconstruct(rebindContext, enricherMemento);
+                    if (enricher == null) {
+                        // usually because of creation-failure, when not using fail-fast
+                        exceptionHandler.onEnricherNotFound(enricherMemento.getId());
+                    } else {
+                        try {
+                            enricher.getRebindSupport().reconstruct(rebindContext, enricherMemento);
+                        } catch (Exception e) {
+                            exceptionHandler.onRebindEnricherFailed(enricher, e);
+                            rebindContext.unregisterEnricher(enricher);
+                        }
+                    }
+
                 }
             }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java b/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
index 7424e38..04e69e7 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
@@ -1,6 +1,7 @@
 package brooklyn.entity.rebind.persister;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandler;
 import brooklyn.entity.rebind.dto.BrooklynMementoManifestImpl;
 import brooklyn.entity.rebind.dto.MutableBrooklynMemento;
@@ -51,12 +52,12 @@ public abstract class AbstractBrooklynMementoPersister implements BrooklynMement
     }
     
     @Override
-    public void checkpoint(BrooklynMemento newMemento) {
+    public void checkpoint(BrooklynMemento newMemento, PersistenceExceptionHandler exceptionHandler) {
         memento.reset(checkNotNull(newMemento, "memento"));
     }
 
     @Override
-    public void delta(Delta delta) {
+    public void delta(Delta delta, PersistenceExceptionHandler exceptionHanlder) {
         memento.removeEntities(delta.removedEntityIds());
         memento.removeLocations(delta.removedLocationIds());
         memento.removePolicies(delta.removedPolicyIds());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
index b0e0478..08d8f03 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
@@ -13,6 +13,8 @@ import java.util.concurrent.TimeoutException;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.proxying.EntityProxy;
+import brooklyn.entity.rebind.PersistenceExceptionHandler;
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
 import brooklyn.entity.rebind.RebindExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandlerImpl;
 import brooklyn.entity.rebind.RebindManager;
@@ -69,14 +71,14 @@ public class BrooklynMementoPersisterInMemory extends AbstractBrooklynMementoPer
     }
 
     @Override
-    public void checkpoint(BrooklynMemento newMemento) {
-        super.checkpoint(newMemento);
+    public void checkpoint(BrooklynMemento newMemento, PersistenceExceptionHandler exceptionHandler) {
+        super.checkpoint(newMemento, exceptionHandler);
         if (checkPersistable) reserializeMemento();
     }
 
     @Override
-    public void delta(Delta delta) {
-        super.delta(delta);
+    public void delta(Delta delta, PersistenceExceptionHandler exceptionHandler) {
+        super.delta(delta, exceptionHandler);
         if (checkPersistable) reserializeMemento();
     }
     
@@ -87,9 +89,13 @@ public class BrooklynMementoPersisterInMemory extends AbstractBrooklynMementoPer
             try {
                 // TODO Duplicate code for LookupContext in RebindManager
                 BrooklynMementoPersisterToMultiFile persister = new BrooklynMementoPersisterToMultiFile(tempDir , classLoader);
-                RebindExceptionHandler exceptionHandler = new RebindExceptionHandlerImpl(RebindManager.RebindFailureMode.FAIL_AT_END, RebindManager.RebindFailureMode.FAIL_AT_END);
-                persister.checkpoint(memento);
-                final BrooklynMementoManifest manifest = persister.loadMementoManifest(exceptionHandler);
+                RebindExceptionHandler rebindExceptionHandler = RebindExceptionHandlerImpl.builder()
+                        .danglingRefFailureMode(RebindManager.RebindFailureMode.FAIL_AT_END)
+                        .rebindFailureMode(RebindManager.RebindFailureMode.FAIL_AT_END)
+                        .build();
+                PersistenceExceptionHandler persistenceExceptionHandler = PersistenceExceptionHandlerImpl.builder().build();
+                persister.checkpoint(memento, persistenceExceptionHandler);
+                final BrooklynMementoManifest manifest = persister.loadMementoManifest(rebindExceptionHandler);
                 LookupContext dummyLookupContext = new LookupContext() {
                     @Override
                     public ManagementContext lookupManagementContext() {
@@ -144,7 +150,7 @@ public class BrooklynMementoPersisterInMemory extends AbstractBrooklynMementoPer
                 };
 
                 // Not actually reconstituting, because need to use a real lookupContext to reconstitute all the entities
-                persister.loadMemento(dummyLookupContext, exceptionHandler);
+                persister.loadMemento(dummyLookupContext, rebindExceptionHandler);
             } finally {
                 Os.deleteRecursively(tempDir);
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToFile.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToFile.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToFile.java
index a0c479b..ed70e44 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToFile.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToFile.java
@@ -8,6 +8,7 @@ import java.util.concurrent.TimeoutException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandler;
 import brooklyn.mementos.BrooklynMemento;
 import brooklyn.util.exceptions.Exceptions;
@@ -83,11 +84,11 @@ public class BrooklynMementoPersisterToFile extends AbstractBrooklynMementoPersi
     }
     
     @Override
-    public void checkpoint(BrooklynMemento newMemento) {
+    public void checkpoint(BrooklynMemento newMemento, PersistenceExceptionHandler exceptionHandler) {
         Stopwatch stopwatch = Stopwatch.createStarted();
         synchronized (mutex) {
             long timeObtainedMutex = stopwatch.elapsed(TimeUnit.MILLISECONDS);
-            super.checkpoint(newMemento);
+            super.checkpoint(newMemento, exceptionHandler);
             long timeCheckpointed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
             writeMemento();
             long timeWritten = stopwatch.elapsed(TimeUnit.MILLISECONDS);
@@ -100,11 +101,11 @@ public class BrooklynMementoPersisterToFile extends AbstractBrooklynMementoPersi
     }
     
     @Override
-    public void delta(Delta delta) {
+    public void delta(Delta delta, PersistenceExceptionHandler exceptionHandler) {
         Stopwatch stopwatch = Stopwatch.createStarted();
         synchronized (mutex) {
             long timeObtainedMutex = stopwatch.elapsed(TimeUnit.MILLISECONDS);
-            super.delta(delta);
+            super.delta(delta, exceptionHandler);
             long timeDeltad = stopwatch.elapsed(TimeUnit.MILLISECONDS);
             writeMemento();
             long timeWritten = stopwatch.elapsed(TimeUnit.MILLISECONDS);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
index c2a1a85..c2bbdd0 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
@@ -14,14 +14,8 @@ import java.util.concurrent.TimeoutException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandler;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
-import com.google.common.base.Stopwatch;
-import com.google.common.io.Files;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-
 import brooklyn.entity.rebind.dto.BrooklynMementoImpl;
 import brooklyn.entity.rebind.dto.BrooklynMementoManifestImpl;
 import brooklyn.mementos.BrooklynMemento;
@@ -36,6 +30,13 @@ import brooklyn.util.time.Duration;
 import brooklyn.util.time.Time;
 import brooklyn.util.xstream.XmlUtil;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Charsets;
+import com.google.common.base.Stopwatch;
+import com.google.common.io.Files;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
 /**
  * @deprecated since 0.7.0 use {@link BrooklynMementoPersisterToObjectStore} instead;
  * it has a multi-file filesystem backend for equivalent functionality, but is pluggable
@@ -286,7 +287,7 @@ public class BrooklynMementoPersisterToMultiFile implements BrooklynMementoPersi
     }
     
     @Override
-    public void checkpoint(BrooklynMemento newMemento) {
+    public void checkpoint(BrooklynMemento newMemento, PersistenceExceptionHandler exceptionHandler) {
         if (!running) {
             if (LOG.isDebugEnabled()) LOG.debug("Ignoring checkpointing entire memento, because not running");
             return;
@@ -308,7 +309,7 @@ public class BrooklynMementoPersisterToMultiFile implements BrooklynMementoPersi
     }
     
     @Override
-    public void delta(Delta delta) {
+    public void delta(Delta delta, PersistenceExceptionHandler exceptionHandler) {
         if (!running) {
             if (LOG.isDebugEnabled()) LOG.debug("Ignoring checkpointed delta of memento, because not running");
             return;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index dec2bf7..34346ba 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -12,6 +12,7 @@ import java.util.concurrent.TimeoutException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandler;
 import brooklyn.entity.rebind.dto.BrooklynMementoImpl;
 import brooklyn.entity.rebind.dto.BrooklynMementoManifestImpl;
@@ -48,11 +49,13 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
 
     private volatile boolean running = true;
 
+
+    // FIXME Delete
     public BrooklynMementoPersisterToObjectStore(PersistenceObjectStore objectStore, ClassLoader classLoader) {
         this.objectStore = checkNotNull(objectStore, "objectStore");
         MementoSerializer<Object> rawSerializer = new XmlMementoSerializer<Object>(classLoader);
         this.serializer = new RetryingMementoSerializer<Object>(rawSerializer, MAX_SERIALIZATION_ATTEMPTS);
-
+        
         // TODO it's 95% the same code for each of these, throughout, so refactor to avoid repetition
         objectStore.createSubPath("entities");
         objectStore.createSubPath("locations");
@@ -261,7 +264,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
     }
     
     @Override
-    public void checkpoint(BrooklynMemento newMemento) {
+    public void checkpoint(BrooklynMemento newMemento, PersistenceExceptionHandler exceptionHandler) {
         if (!running) {
             if (LOG.isDebugEnabled()) LOG.debug("Ignoring checkpointing entire memento, because not running");
             return;
@@ -270,21 +273,21 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
         objectStore.prepareForMasterUse();
         
         for (EntityMemento entity : newMemento.getEntityMementos().values()) {
-            persist("entities", entity);
+            persist("entities", entity, exceptionHandler);
         }
         for (LocationMemento location : newMemento.getLocationMementos().values()) {
-            persist("locations", location);
+            persist("locations", location, exceptionHandler);
         }
         for (PolicyMemento policy : newMemento.getPolicyMementos().values()) {
-            persist("policies", policy);
+            persist("policies", policy, exceptionHandler);
         }
         for (EnricherMemento enricher : newMemento.getEnricherMementos().values()) {
-            persist("enrichers", enricher);
+            persist("enrichers", enricher, exceptionHandler);
         }
     }
     
     @Override
-    public void delta(Delta delta) {
+    public void delta(Delta delta, PersistenceExceptionHandler exceptionHandler) {
         if (!running) {
             if (LOG.isDebugEnabled()) LOG.debug("Ignoring checkpointed delta of memento, because not running");
             return;
@@ -296,29 +299,29 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
         objectStore.prepareForMasterUse();
         
         for (EntityMemento entity : delta.entities()) {
-            persist("entities", entity);
+            persist("entities", entity, exceptionHandler);
         }
         for (LocationMemento location : delta.locations()) {
-            persist("locations", location);
+            persist("locations", location, exceptionHandler);
         }
         for (PolicyMemento policy : delta.policies()) {
-            persist("policies", policy);
+            persist("policies", policy, exceptionHandler);
         }
         for (EnricherMemento enricher : delta.enrichers()) {
-            persist("enrichers", enricher);
+            persist("enrichers", enricher, exceptionHandler);
         }
         
         for (String id : delta.removedEntityIds()) {
-            delete("entities", id);
+            delete("entities", id, exceptionHandler);
         }
         for (String id : delta.removedLocationIds()) {
-            delete("locations", id);
+            delete("locations", id, exceptionHandler);
         }
         for (String id : delta.removedPolicyIds()) {
-            delete("policies", id);
+            delete("policies", id, exceptionHandler);
         }
         for (String id : delta.removedEnricherIds()) {
-            delete("enrichers", id);
+            delete("enrichers", id, exceptionHandler);
         }
     }
 
@@ -333,15 +336,23 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
             writer.waitForCurrentWrites(timeout);
     }
 
-    private void persist(String subPath, Memento entity) {
-        getWriter(getPath(subPath, entity.getId())).put(serializer.toString(entity));
+    private void persist(String subPath, Memento memento, PersistenceExceptionHandler exceptionHandler) {
+        try {
+            getWriter(getPath(subPath, memento.getId())).put(serializer.toString(memento));
+        } catch (Exception e) {
+            exceptionHandler.onPersistMementoFailed(memento, e);
+        }
     }
 
-    private void delete(String subPath, String id) {
-        StoreObjectAccessorWithLock w = getWriter(getPath(subPath, id));
-        w.delete();
-        synchronized (writers) {
-            writers.remove(id);
+    private void delete(String subPath, String id, PersistenceExceptionHandler exceptionHandler) {
+        try {
+            StoreObjectAccessorWithLock w = getWriter(getPath(subPath, id));
+            w.delete();
+            synchronized (writers) {
+                writers.remove(id);
+            }
+        } catch (Exception e) {
+            exceptionHandler.onDeleteMementoFailed(id, e);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
index 8b6d8d7..5516f84 100644
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
@@ -25,6 +25,7 @@ import brooklyn.entity.proxying.InternalEntityFactory;
 import brooklyn.entity.proxying.InternalLocationFactory;
 import brooklyn.entity.proxying.InternalPolicyFactory;
 import brooklyn.entity.rebind.ChangeListener;
+import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandler;
 import brooklyn.entity.rebind.RebindManager;
 import brooklyn.internal.storage.BrooklynStorage;
@@ -384,6 +385,11 @@ public class NonDeploymentManagementContext implements ManagementContextInternal
         }
 
         @Override
+        public void setPersister(BrooklynMementoPersister persister, PersistenceExceptionHandler exceptionHandler) {
+            throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+        }
+
+        @Override
         public BrooklynMementoPersister getPersister() {
             throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
index e648bf9..4d5c5bf 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
@@ -12,6 +12,8 @@ import java.util.Set;
 import org.testng.annotations.Test;
 
 import brooklyn.config.ConfigKey;
+import brooklyn.config.ConfigMap;
+import brooklyn.enricher.basic.AbstractEnricher;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.ConfigKeys;
 import brooklyn.entity.basic.EntityFunctions;
@@ -23,11 +25,17 @@ import brooklyn.entity.rebind.RebindManager.RebindFailureMode;
 import brooklyn.event.AttributeSensor;
 import brooklyn.management.EntityManager;
 import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.policy.Enricher;
+import brooklyn.policy.EnricherSpec;
+import brooklyn.policy.Policy;
+import brooklyn.policy.PolicySpec;
+import brooklyn.policy.basic.AbstractPolicy;
 import brooklyn.util.flags.SetFromFlag;
 import brooklyn.util.os.Os;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
+import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.io.Files;
@@ -155,10 +163,80 @@ public class RebindFailuresTest extends RebindTestFixtureWithApp {
         assertEquals(exceptionHandler.loadMementoFailures.size(), 2, "exceptions="+exceptionHandler.loadMementoFailures);
     }
 
+    @Test
+    public void testRebindWithFailingPolicyContinuesWithoutPolicy() throws Exception {
+        origApp.addPolicy(PolicySpec.create(MyPolicyFailingImpl.class)
+                .configure(MyPolicyFailingImpl.FAIL_ON_REBIND, true));
+        
+        newApp = rebind(false);
+        
+        Optional<Policy> newPolicy = Iterables.tryFind(newApp.getPolicies(), Predicates.instanceOf(MyPolicyFailingImpl.class));
+        assertFalse(newPolicy.isPresent(), "policy="+newPolicy);
+    }
+
+    @Test
+    public void testRebindWithFailingEnricherContinuesWithoutEnricher() throws Exception {
+        origApp.addEnricher(EnricherSpec.create(MyEnricherFailingImpl.class)
+                .configure(MyEnricherFailingImpl.FAIL_ON_REBIND, true));
+        
+        newApp = rebind(false);
+        
+        Optional<Enricher> newEnricher = Iterables.tryFind(newApp.getEnrichers(), Predicates.instanceOf(MyEnricherFailingImpl.class));
+        assertFalse(newEnricher.isPresent(), "enricher="+newEnricher);
+    }
+
     private Set<String> toEntityIds(Iterable<? extends Entity> entities) {
         return ImmutableSet.copyOf(Iterables.transform(entities, EntityFunctions.id()));
     }
     
+    public static class MyPolicyFailingImpl extends AbstractPolicy {
+        @SetFromFlag("failOnGenerateMemento")
+        public static final ConfigKey<Boolean> FAIL_ON_GENERATE_MEMENTO = ConfigKeys.newBooleanConfigKey("failOnGenerateMemento", "Whether to throw exception when generating memento", false);
+        
+        @SetFromFlag("failOnRebind")
+        public static final ConfigKey<Boolean> FAIL_ON_REBIND = ConfigKeys.newBooleanConfigKey("failOnRebind", "Whether to throw exception when rebinding", false);
+        
+        @Override
+        public ConfigMap getConfigMap() {
+            if (Boolean.TRUE.equals(getConfig(FAIL_ON_GENERATE_MEMENTO))) {
+                throw new RuntimeException("Simulating failure in "+this+", which will cause memento-generation to fail");
+            } else {
+                return super.getConfigMap();
+            }
+        }
+        
+        @Override
+        public void rebind() {
+            if (Boolean.TRUE.equals(getConfig(FAIL_ON_REBIND))) {
+                throw new RuntimeException("Simulating failure in "+this+", which will cause rebind to fail");
+            }
+        }
+    }
+
+    public static class MyEnricherFailingImpl extends AbstractEnricher {
+        @SetFromFlag("failOnGenerateMemento")
+        public static final ConfigKey<Boolean> FAIL_ON_GENERATE_MEMENTO = ConfigKeys.newBooleanConfigKey("failOnGenerateMemento", "Whether to throw exception when generating memento", false);
+        
+        @SetFromFlag("failOnRebind")
+        public static final ConfigKey<Boolean> FAIL_ON_REBIND = ConfigKeys.newBooleanConfigKey("failOnRebind", "Whether to throw exception when rebinding", false);
+        
+        @Override
+        public ConfigMap getConfigMap() {
+            if (Boolean.TRUE.equals(getConfig(FAIL_ON_GENERATE_MEMENTO))) {
+                throw new RuntimeException("Simulating failure in "+this+", which will cause memento-generation to fail");
+            } else {
+                return super.getConfigMap();
+            }
+        }
+        
+        @Override
+        public void rebind() {
+            if (Boolean.TRUE.equals(getConfig(FAIL_ON_REBIND))) {
+                throw new RuntimeException("Simulating failure in "+this+", which will cause rebind to fail");
+            }
+        }
+    }
+
     public static class MyEntityFailingImpl extends MyEntityImpl implements MyEntity {
         @SetFromFlag("failOnGenerateMemento")
         public static final ConfigKey<Boolean> FAIL_ON_GENERATE_MEMENTO = ConfigKeys.newBooleanConfigKey("failOnGenerateMemento", "Whether to throw exception when generating memento", false);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java b/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
index ffdff16..e1be542 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
@@ -13,8 +13,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.collections.Maps;
 
-import com.google.common.collect.Iterables;
-
 import brooklyn.config.BrooklynProperties;
 import brooklyn.entity.Application;
 import brooklyn.entity.Entity;
@@ -35,6 +33,8 @@ import brooklyn.util.javalang.Serializers;
 import brooklyn.util.javalang.Serializers.ObjectReplacer;
 import brooklyn.util.time.Duration;
 
+import com.google.common.collect.Iterables;
+
 public class RebindTestUtils {
 
     private static final Logger LOG = LoggerFactory.getLogger(RebindTestUtils.class);
@@ -158,7 +158,7 @@ public class RebindTestUtils {
             objectStore.prepareForSharedUse(PersistMode.AUTO, HighAvailabilityMode.DISABLED);
             BrooklynMementoPersisterToObjectStore newPersister = new BrooklynMementoPersisterToObjectStore(objectStore, classLoader);
             ((RebindManagerImpl) unstarted.getRebindManager()).setPeriodicPersistPeriod(persistPeriod);
-            unstarted.getRebindManager().setPersister(newPersister);
+            unstarted.getRebindManager().setPersister(newPersister, PersistenceExceptionHandlerImpl.builder().build());
             return unstarted;
         }
 
@@ -222,7 +222,7 @@ public class RebindTestUtils {
         LOG.info("Rebinding app, using directory "+mementoDir);
 
         BrooklynMementoPersisterToObjectStore newPersister = new BrooklynMementoPersisterToObjectStore(objectStore, classLoader);
-        newManagementContext.getRebindManager().setPersister(newPersister);
+        newManagementContext.getRebindManager().setPersister(newPersister, PersistenceExceptionHandlerImpl.builder().build());
         List<Application> newApps;
         if (exceptionHandler == null) {
             newApps = newManagementContext.getRebindManager().rebind(classLoader);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/test/java/brooklyn/entity/rebind/RecordingRebindExceptionHandler.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RecordingRebindExceptionHandler.java b/core/src/test/java/brooklyn/entity/rebind/RecordingRebindExceptionHandler.java
index 1cca83a..382e001 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RecordingRebindExceptionHandler.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RecordingRebindExceptionHandler.java
@@ -27,7 +27,7 @@ public class RecordingRebindExceptionHandler extends RebindExceptionHandlerImpl
     protected Exception failed;
     
     public RecordingRebindExceptionHandler(RebindManager.RebindFailureMode danglingRefFailureMode, RebindManager.RebindFailureMode rebindFailureMode) {
-        super(danglingRefFailureMode, rebindFailureMode);
+        super(builder().danglingRefFailureMode(danglingRefFailureMode).rebindFailureMode(rebindFailureMode));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterTestFixture.java b/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterTestFixture.java
index 13793a8..1946f75 100644
--- a/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterTestFixture.java
+++ b/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterTestFixture.java
@@ -85,7 +85,7 @@ public abstract class BrooklynMementoPersisterTestFixture {
         RebindTestUtils.waitForPersisted(localManagementContext);
         
         RecordingRebindExceptionHandler failFast = new RecordingRebindExceptionHandler(RebindFailureMode.FAIL_FAST, RebindFailureMode.FAIL_FAST);
-        RebindContextImpl rebindContext = new RebindContextImpl(classLoader);
+        RebindContextImpl rebindContext = new RebindContextImpl(failFast, classLoader);
         RebindContextLookupContext lookupContext = new RebindContextLookupContext(localManagementContext, rebindContext, failFast);
         // here we force these two to be reegistered in order to resolve the enricher and policy
         // (normally rebind will do that after loading the manifests, but in this test we are just looking at persistence/manifest)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFileTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFileTest.java b/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFileTest.java
index 72840ae..483693c 100644
--- a/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFileTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFileTest.java
@@ -4,6 +4,7 @@ import java.io.File;
 
 import org.testng.annotations.AfterMethod;
 
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
 import brooklyn.entity.rebind.RebindManagerImpl;
 import brooklyn.management.internal.LocalManagementContext;
 import brooklyn.test.entity.LocalManagementContextForTests;
@@ -27,7 +28,7 @@ public class BrooklynMementoPersisterToMultiFileTest extends BrooklynMementoPers
         LocalManagementContext mgmt = new LocalManagementContextForTests();
         ((RebindManagerImpl) mgmt.getRebindManager()).setPeriodicPersistPeriod(Duration.millis(100));
         persister = new BrooklynMementoPersisterToMultiFile(mementoDir, BrooklynMementoPersisterToMultiFileTest.class.getClassLoader());
-        mgmt.getRebindManager().setPersister(persister);
+        mgmt.getRebindManager().setPersister(persister, PersistenceExceptionHandlerImpl.builder().build());
         mgmt.getHighAvailabilityManager().disabled();
         mgmt.getRebindManager().start();
         return mgmt;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerSplitBrainTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerSplitBrainTest.java b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerSplitBrainTest.java
index e9eb855..b3406a7 100644
--- a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerSplitBrainTest.java
+++ b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerSplitBrainTest.java
@@ -18,6 +18,7 @@ import org.testng.annotations.Test;
 import brooklyn.entity.basic.ApplicationBuilder;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
 import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
 import brooklyn.entity.rebind.persister.InMemoryObjectStore;
 import brooklyn.entity.rebind.persister.ListeningObjectStore;
@@ -80,7 +81,7 @@ public class HighAvailabilityManagerSplitBrainTest {
             persister = new ManagementPlaneSyncRecordPersisterToObjectStore(mgmt, objectStore, classLoader);
             ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).allowRemoteTimestampInMemento();
             BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, classLoader);
-            mgmt.getRebindManager().setPersister(persisterObj);
+            mgmt.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
             ha = new HighAvailabilityManagerImpl(mgmt)
                 .setPollPeriod(Duration.PRACTICALLY_FOREVER)
                 .setHeartbeatTimeout(Duration.THIRTY_SECONDS)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerTestFixture.java b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerTestFixture.java
index ce8dab5..b572a80 100644
--- a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerTestFixture.java
+++ b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerTestFixture.java
@@ -19,6 +19,7 @@ import brooklyn.BrooklynVersion;
 import brooklyn.config.BrooklynProperties;
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
 import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
 import brooklyn.entity.rebind.persister.PersistMode;
 import brooklyn.entity.rebind.persister.PersistenceObjectStore;
@@ -68,7 +69,7 @@ public abstract class HighAvailabilityManagerTestFixture {
         persister = new ManagementPlaneSyncRecordPersisterToObjectStore(managementContext, objectStore, classLoader);
         ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).allowRemoteTimestampInMemento();
         BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, classLoader);
-        managementContext.getRebindManager().setPersister(persisterObj);
+        managementContext.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
         manager = new HighAvailabilityManagerImpl(managementContext)
                 .setPollPeriod(getPollPeriod())
                 .setHeartbeatTimeout(Duration.THIRTY_SECONDS)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/software/webapp/src/test/java/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java b/software/webapp/src/test/java/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
index 3c61ab8..3acc864 100644
--- a/software/webapp/src/test/java/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
+++ b/software/webapp/src/test/java/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
@@ -31,6 +31,7 @@ import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.basic.EntityLocal;
 import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
 import brooklyn.entity.rebind.dto.MementosGenerators;
 import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToMultiFile;
 import brooklyn.entity.trait.Startable;
@@ -201,12 +202,12 @@ public abstract class AbstractWebAppFixtureIntegrationTest {
             BrooklynMemento brooklynMemento = MementosGenerators.newBrooklynMemento(managementContext);
             
             BrooklynMementoPersisterToMultiFile oldPersister = new BrooklynMementoPersisterToMultiFile(tempDir , getClass().getClassLoader());
-            oldPersister.checkpoint(brooklynMemento);
+            oldPersister.checkpoint(brooklynMemento, PersistenceExceptionHandlerImpl.builder().build());
             oldPersister.waitForWritesCompleted(30*1000, TimeUnit.MILLISECONDS);
 
             BrooklynMementoPersisterToMultiFile newPersister = new BrooklynMementoPersisterToMultiFile(tempDir , getClass().getClassLoader());
             newManagementContext = new LocalManagementContextForTests();
-            newManagementContext.getRebindManager().setPersister(newPersister);
+            newManagementContext.getRebindManager().setPersister(newPersister, PersistenceExceptionHandlerImpl.builder().build());
             newManagementContext.getRebindManager().rebind(getClass().getClassLoader());
             newManagementContext.getRebindManager().start();
             SoftwareProcess entity2 = (SoftwareProcess) newManagementContext.getEntityManager().getEntity(tokill.getId());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/391b3bb8/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
index 8fba37b..6cdcf04 100644
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
@@ -34,6 +34,8 @@ import brooklyn.entity.basic.BrooklynShutdownHooks;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.PersistenceExceptionHandler;
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
 import brooklyn.entity.rebind.RebindManager;
 import brooklyn.entity.rebind.RebindManagerImpl;
 import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
@@ -541,8 +543,9 @@ public class BrooklynLauncher {
 
             BrooklynMementoPersisterToObjectStore persister = new BrooklynMementoPersisterToObjectStore(objectStore,
                     managementContext.getCatalog().getRootClassLoader());
+            PersistenceExceptionHandler persistenceExceptionHandler = PersistenceExceptionHandlerImpl.builder().build();
             ((RebindManagerImpl) rebindManager).setPeriodicPersistPeriod(persistPeriod);
-            rebindManager.setPersister(persister);
+            rebindManager.setPersister(persister, persistenceExceptionHandler);
         }
         
         // Initialise the HA manager as required


[3/6] git commit: BROOKLYN-14: rebind policies in separate phase

Posted by he...@apache.org.
BROOKLYN-14: rebind policies in separate phase

- Only add policies+enrichers to entities after all entities have had
  their state set, and all relationships (parent-child, 
  group membership, locations) have been set up
- Also corrects spelling of “doReconsruct” in BasicPolicyRebindSupport
  etc
- Improves comments in RebindManagerImpl on rebind’s phases

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

Branch: refs/heads/master
Commit: 59ce9e8b04b4d226436edab96c9e8b4ec2539154
Parents: b8f1a04
Author: Aled Sage <al...@gmail.com>
Authored: Tue Jul 1 10:28:33 2014 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Jul 1 10:28:33 2014 +0100

----------------------------------------------------------------------
 .../brooklyn/entity/rebind/RebindSupport.java   |  8 ++-
 .../rebind/BasicEnricherRebindSupport.java      | 13 ++++-
 .../entity/rebind/BasicEntityRebindSupport.java | 52 +++++++++---------
 .../rebind/BasicLocationRebindSupport.java      | 14 ++++-
 .../entity/rebind/BasicPolicyRebindSupport.java | 14 ++++-
 .../entity/rebind/RebindManagerImpl.java        | 49 +++++++++++++++--
 .../entity/rebind/RebindLocationTest.java       |  4 +-
 .../entity/rebind/RebindPolicyTest.java         | 55 ++++++++++++++++++++
 8 files changed, 168 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/59ce9e8b/api/src/main/java/brooklyn/entity/rebind/RebindSupport.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/entity/rebind/RebindSupport.java b/api/src/main/java/brooklyn/entity/rebind/RebindSupport.java
index 9d3aaf4..6aa0cca 100644
--- a/api/src/main/java/brooklyn/entity/rebind/RebindSupport.java
+++ b/api/src/main/java/brooklyn/entity/rebind/RebindSupport.java
@@ -18,7 +18,7 @@ public interface RebindSupport<T extends Memento> {
     /**
      * Creates a memento representing this entity's current state. This is useful for when restarting brooklyn.
      */
-    public T getMemento();
+    T getMemento();
 
     /**
      * Reconstructs this entity, given a memento of its state. Sets the internal state 
@@ -29,5 +29,9 @@ public interface RebindSupport<T extends Memento> {
      * 
      * Called before rebind.
      */
-    public void reconstruct(RebindContext rebindContext, T memento);
+    void reconstruct(RebindContext rebindContext, T memento);
+
+    void addPolicies(RebindContext rebindContext, T Memento);
+    
+    void addEnrichers(RebindContext rebindContext, T Memento);
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/59ce9e8b/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
index 4a5747c..37aa249 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
@@ -40,15 +40,24 @@ public class BasicEnricherRebindSupport implements RebindSupport<EnricherMemento
         FlagUtils.setFieldsFromFlags(enricher, configBag);
         FlagUtils.setAllConfigKeys(enricher, configBag, false);
         
-        doReconsruct(rebindContext, memento);
+        doReconstruct(rebindContext, memento);
         ((AbstractEnricher)enricher).rebind();
     }
 
+    @Override
+    public void addPolicies(RebindContext rebindContext, EnricherMemento Memento) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void addEnrichers(RebindContext rebindContext, EnricherMemento Memento) {
+        throw new UnsupportedOperationException();
+    }
 
     /**
      * For overriding, to give custom reconsruct behaviour.
      */
-    protected void doReconsruct(RebindContext rebindContext, EnricherMemento memento) {
+    protected void doReconstruct(RebindContext rebindContext, EnricherMemento memento) {
         // default is no-op
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/59ce9e8b/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
index 9ab4a8b..50fc396 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
@@ -88,8 +88,6 @@ public class BasicEntityRebindSupport implements RebindSupport<EntityMemento> {
         
         setParent(rebindContext, memento);
         addChildren(rebindContext, memento);
-        addPolicies(rebindContext, memento);
-        addEnrichers(rebindContext, memento);
         addMembers(rebindContext, memento);
         addTags(rebindContext, memento);
         addLocations(rebindContext, memento);
@@ -98,6 +96,32 @@ public class BasicEntityRebindSupport implements RebindSupport<EntityMemento> {
         ((AbstractEntity)entity).rebind();
     }
     
+    @Override
+    public void addPolicies(RebindContext rebindContext, EntityMemento memento) {
+        for (String policyId : memento.getPolicies()) {
+            AbstractPolicy policy = (AbstractPolicy) rebindContext.getPolicy(policyId);
+            if (policy != null) {
+                entity.addPolicy(policy);
+            } else {
+                LOG.warn("Policy not found; discarding policy {} of entity {}({})",
+                        new Object[] {policyId, memento.getType(), memento.getId()});
+            }
+        }
+    }
+    
+    @Override
+    public void addEnrichers(RebindContext rebindContext, EntityMemento memento) {
+        for (String enricherId : memento.getEnrichers()) {
+            AbstractEnricher enricher = (AbstractEnricher) rebindContext.getEnricher(enricherId);
+            if (enricher != null) {
+                entity.addEnricher(enricher);
+            } else {
+                LOG.warn("Enricher not found; discarding enricher {} of entity {}({})",
+                        new Object[] {enricherId, memento.getType(), memento.getId()});
+            }
+        }
+    }
+    
     /**
      * For overriding, to reconstruct other fields.
      */
@@ -162,28 +186,4 @@ public class BasicEntityRebindSupport implements RebindSupport<EntityMemento> {
             }
         }
     }
-    
-    protected void addPolicies(RebindContext rebindContext, EntityMemento memento) {
-        for (String policyId : memento.getPolicies()) {
-            AbstractPolicy policy = (AbstractPolicy) rebindContext.getPolicy(policyId);
-            if (policy != null) {
-                entity.addPolicy(policy);
-            } else {
-                LOG.warn("Policy not found; discarding policy {} of entity {}({})",
-                        new Object[] {policyId, memento.getType(), memento.getId()});
-            }
-        }
-    }
-    
-    protected void addEnrichers(RebindContext rebindContext, EntityMemento memento) {
-        for (String enricherId : memento.getEnrichers()) {
-            AbstractEnricher enricher = (AbstractEnricher) rebindContext.getEnricher(enricherId);
-            if (enricher != null) {
-                entity.addEnricher(enricher);
-            } else {
-                LOG.warn("Enricher not found; discarding enricher {} of entity {}({})",
-                        new Object[] {enricherId, memento.getType(), memento.getId()});
-            }
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/59ce9e8b/core/src/main/java/brooklyn/entity/rebind/BasicLocationRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicLocationRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicLocationRebindSupport.java
index 5e5c6e6..07d840f 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicLocationRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicLocationRebindSupport.java
@@ -89,7 +89,17 @@ public class BasicLocationRebindSupport implements RebindSupport<LocationMemento
         location.init(); // TODO deprecated calling init; will be deleted
         location.rebind();
         
-        doReconsruct(rebindContext, memento);
+        doReconstruct(rebindContext, memento);
+    }
+
+    @Override
+    public void addPolicies(RebindContext rebindContext, LocationMemento Memento) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void addEnrichers(RebindContext rebindContext, LocationMemento Memento) {
+        throw new UnsupportedOperationException();
     }
 
     protected void addChildren(RebindContext rebindContext, LocationMemento memento) {
@@ -115,7 +125,7 @@ public class BasicLocationRebindSupport implements RebindSupport<LocationMemento
     /**
      * For overriding, to give custom reconsruct behaviour.
      */
-    protected void doReconsruct(RebindContext rebindContext, LocationMemento memento) {
+    protected void doReconstruct(RebindContext rebindContext, LocationMemento memento) {
         // default is no-op
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/59ce9e8b/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
index 39202cb..c952f83 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
@@ -40,14 +40,24 @@ public class BasicPolicyRebindSupport implements RebindSupport<PolicyMemento> {
         FlagUtils.setFieldsFromFlags(policy, configBag);
         FlagUtils.setAllConfigKeys(policy, configBag, false);
         
-        doReconsruct(rebindContext, memento);
+        doReconstruct(rebindContext, memento);
         ((AbstractPolicy)policy).rebind();
     }
 
+    @Override
+    public void addPolicies(RebindContext rebindContext, PolicyMemento Memento) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void addEnrichers(RebindContext rebindContext, PolicyMemento Memento) {
+        throw new UnsupportedOperationException();
+    }
+
     /**
      * For overriding, to give custom reconsruct behaviour.
      */
-    protected void doReconsruct(RebindContext rebindContext, PolicyMemento memento) {
+    protected void doReconstruct(RebindContext rebindContext, PolicyMemento memento) {
         // default is no-op
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/59ce9e8b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index b1c5465..d3928b7 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -243,16 +243,23 @@ public class RebindManagerImpl implements RebindManager {
             final RebindContextImpl rebindContext = new RebindContextImpl(classLoader);
             LookupContext realLookupContext = new RebindContextLookupContext(managementContext, rebindContext, exceptionHandler);
             
-            // Two-phase deserialization.
-            // First we deserialize just the "manifest" to find all instances (and their types).
-            // Then we deserialize so that inter-entity references can be set.
-            //
+            // Four-phase deserialization.
+            //  1. deserialize just the "manifest" to find all instances (and their types).
+            //  2. deserialize so that inter-entity references can be set (and entity config/state is set).
+            //  3. add policies+enrichers to all the entities.
+            //  4. manage the entities
+            
             // TODO if underlying data-store is changed between first and second phase (e.g. to add an
             // entity), then second phase might try to reconstitute an entity that has not been put in
             // the rebindContext. This should not affect normal production usage, because rebind is run
             // against a data-store that is not being written to by other brooklyn instance(s).
-            BrooklynMementoManifest mementoManifest = persister.loadMementoManifest(exceptionHandler);
             
+            //
+            // PHASE ONE
+            //
+            
+            BrooklynMementoManifest mementoManifest = persister.loadMementoManifest(exceptionHandler);
+
             // Instantiate locations
             LOG.debug("RebindManager instantiating locations: {}", mementoManifest.getLocationIdToType().keySet());
             for (Map.Entry<String, String> entry : mementoManifest.getLocationIdToType().entrySet()) {
@@ -319,6 +326,10 @@ public class RebindManagerImpl implements RebindManager {
                 LOG.debug("Not rebinding enrichers; feature disabled: {}", memento.getEnricherIds());
             } 
             
+            //
+            // PHASE TWO
+            //
+            
             // Reconstruct locations
             LOG.debug("RebindManager reconstructing locations");
             for (LocationMemento locMemento : sortParentFirst(memento.getLocationMementos()).values()) {
@@ -385,7 +396,35 @@ public class RebindManagerImpl implements RebindManager {
                     }
                 }
             }
+
+            //
+            // PHASE THREE
+            //
+            
+            // Associate policies+enrichers with entities
+            LOG.debug("RebindManager reconstructing entities");
+            for (EntityMemento entityMemento : sortParentFirst(memento.getEntityMementos()).values()) {
+                Entity entity = rebindContext.getEntity(entityMemento.getId());
+                if (LOG.isDebugEnabled()) LOG.debug("RebindManager reconstructing entity {}", entityMemento);
+    
+                if (entity == null) {
+                    // usually because of creation-failure, when not using fail-fast
+                    exceptionHandler.onEntityNotFound(entityMemento.getId());
+                } else {
+                    try {
+                        entityMemento.injectTypeClass(entity.getClass());
+                        ((EntityInternal)entity).getRebindSupport().addPolicies(rebindContext, entityMemento);
+                        ((EntityInternal)entity).getRebindSupport().addEnrichers(rebindContext, entityMemento);
+                    } catch (Exception e) {
+                        exceptionHandler.onRebindEntityFailed(entity, e);
+                    }
+                }
+            }
             
+            //
+            // PHASE FOUR
+            //
+
             LOG.debug("RebindManager managing locations");
             for (Location location: locations.values()) {
                 if (location.getParent()==null) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/59ce9e8b/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
index 23e6de2..741e522 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
@@ -344,8 +344,8 @@ public class RebindLocationTest extends RebindTestFixtureWithApp {
                     return getMementoWithProperties(MutableMap.<String,Object>of("myfield", myfield));
                 }
                 @Override
-                protected void doReconsruct(RebindContext rebindContext, LocationMemento memento) {
-                    super.doReconsruct(rebindContext, memento);
+                protected void doReconstruct(RebindContext rebindContext, LocationMemento memento) {
+                    super.doReconstruct(rebindContext, memento);
                     myfield = (String) memento.getCustomField("myfield");
                     rebound = true;
                 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/59ce9e8b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
index b136665..4b7767a 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
@@ -10,8 +10,12 @@ import java.util.Map;
 import org.testng.annotations.Test;
 
 import brooklyn.config.ConfigKey;
+import brooklyn.enricher.basic.AbstractEnricher;
+import brooklyn.entity.Group;
+import brooklyn.entity.basic.BasicGroup;
 import brooklyn.entity.basic.ConfigKeys;
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityLocal;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.RebindEnricherTest.MyEnricher;
 import brooklyn.location.Location;
@@ -25,6 +29,7 @@ import brooklyn.test.entity.TestEntity;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.flags.SetFromFlag;
 
+import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;
 
 public class RebindPolicyTest extends RebindTestFixtureWithApp {
@@ -163,6 +168,56 @@ public class RebindPolicyTest extends RebindTestFixtureWithApp {
         assertFalse(newPolicy.isRebinding());
     }
     
+    // Previously, policy+enricher was added to entity as part of entity.reconstitute, so other entities might not
+    // have been initialised and the relationships not set. If a policy immediately looked at entity's children or
+    // at another entity, then it might find those entities' state uninitialised.
+    //
+    // Longer term, we may want to force policies+enrichers to be inactive until the entity really is managed.
+    // However, currently some policies inject an onEvent message during their `setEntity` method (because 
+    // their subscription does not give them the current value - only changed values. Doing that sudo-onEvent is
+    // a bad idea because even on normal startup the entity might still be in its init method, so we shouldn't be
+    // kicking off actions at that point.
+    @Test
+    public void testPolicyAddedWhenEntityRelationshipsSet() throws Exception {
+        BasicGroup origGroup = origApp.createAndManageChild(EntitySpec.create(BasicGroup.class));
+        TestEntity origEntity = origApp.createAndManageChild(EntitySpec.create(TestEntity.class));
+        origGroup.addMember(origEntity);
+        
+        EnricherChecksEntityHierarchy origEnricher = origApp.addEnricher(EnricherSpec.create(EnricherChecksEntityHierarchy.class));
+        PolicyChecksEntityHierarchy origPolicy = origApp.addPolicy(PolicySpec.create(PolicyChecksEntityHierarchy.class));
+        assertTrue(origEnricher.success);
+        assertTrue(origPolicy.success);
+        
+        newApp = (TestApplication) rebind();
+        EnricherChecksEntityHierarchy newEnricher = (EnricherChecksEntityHierarchy) Iterables.getOnlyElement(newApp.getEnrichers());
+        PolicyChecksEntityHierarchy newPolicy = (PolicyChecksEntityHierarchy) Iterables.getOnlyElement(newApp.getPolicies());
+
+        assertTrue(newEnricher.success);
+        assertTrue(newPolicy.success);
+    }
+    public static class PolicyChecksEntityHierarchy extends AbstractPolicy {
+        transient volatile boolean success;
+        @Override
+        public void setEntity(EntityLocal entity) {
+            super.setEntity(entity);
+            assertTrue(entity instanceof TestApplication);
+            assertEquals(entity.getChildren().size(), 2);
+            assertEquals(((Group)Iterables.find(entity.getChildren(), Predicates.instanceOf(Group.class))).getMembers().size(), 1);
+            success = true;
+        }
+    }
+    public static class EnricherChecksEntityHierarchy extends AbstractEnricher {
+        transient volatile boolean success;
+        @Override
+        public void setEntity(EntityLocal entity) {
+            super.setEntity(entity);
+            assertTrue(entity instanceof TestApplication);
+            assertEquals(entity.getChildren().size(), 2);
+            assertEquals(((Group)Iterables.find(entity.getChildren(), Predicates.instanceOf(Group.class))).getMembers().size(), 1);
+            success = true;
+        }
+    }
+    
     public static class PolicyChecksIsRebinding extends AbstractPolicy {
         boolean isRebindingValWhenRebinding;
         


[6/6] git commit: add back error handling, and misc minor code review comments.

Posted by he...@apache.org.
add back error handling, and misc minor code review comments.

This closes #34. And this closes #35.


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

Branch: refs/heads/master
Commit: abf21bdc49088d2df8d1f4cd34735a983f2ac7c0
Parents: fdbacdf
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 10:18:05 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 10:41:43 2014 +0100

----------------------------------------------------------------------
 .../entity/rebind/BasicEntityRebindSupport.java | 12 ++++++--
 .../BrooklynMementoPersisterToObjectStore.java  |  1 -
 .../internal/BrooklynFeatureEnablement.java     |  6 ++--
 .../entity/rebind/RebindTestFixture.java        | 31 +++++++-------------
 4 files changed, 23 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/abf21bdc/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
index 50fc396..f154474 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
@@ -101,7 +101,11 @@ public class BasicEntityRebindSupport implements RebindSupport<EntityMemento> {
         for (String policyId : memento.getPolicies()) {
             AbstractPolicy policy = (AbstractPolicy) rebindContext.getPolicy(policyId);
             if (policy != null) {
-                entity.addPolicy(policy);
+                try {
+                    entity.addPolicy(policy);
+                } catch (Exception e) {
+                    rebindContext.getExceptionHandler().onAddPolicyFailed(entity, policy, e);
+                }
             } else {
                 LOG.warn("Policy not found; discarding policy {} of entity {}({})",
                         new Object[] {policyId, memento.getType(), memento.getId()});
@@ -114,7 +118,11 @@ public class BasicEntityRebindSupport implements RebindSupport<EntityMemento> {
         for (String enricherId : memento.getEnrichers()) {
             AbstractEnricher enricher = (AbstractEnricher) rebindContext.getEnricher(enricherId);
             if (enricher != null) {
-                entity.addEnricher(enricher);
+                try {
+                    entity.addEnricher(enricher);
+                } catch (Exception e) {
+                    rebindContext.getExceptionHandler().onAddEnricherFailed(entity, enricher, e);
+                }
             } else {
                 LOG.warn("Enricher not found; discarding enricher {} of entity {}({})",
                         new Object[] {enricherId, memento.getType(), memento.getId()});

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/abf21bdc/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index 8a2b549..8746cc0 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -50,7 +50,6 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
     private volatile boolean running = true;
 
 
-    // FIXME Delete
     public BrooklynMementoPersisterToObjectStore(PersistenceObjectStore objectStore, ClassLoader classLoader) {
         this.objectStore = checkNotNull(objectStore, "objectStore");
         MementoSerializer<Object> rawSerializer = new XmlMementoSerializer<Object>(classLoader);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/abf21bdc/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java b/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
index a0a520d..8838b46 100644
--- a/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
+++ b/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
@@ -24,9 +24,9 @@ public class BrooklynFeatureEnablement {
     
     static {
         // Idea is here one can put experimental features that are *enabled* by default, but 
-        // that can be turned off via system properties. One might want to do that because
-        // the feature is deemed risky!
-        //   e.g. setDefault(ENABLE_POLICY_PERSISTENCE_PROPERTY, true);
+        // that can be turned off via system properties, or vice versa.
+        // Typically this is useful where a feature is deemed risky!
+        
         setDefault(FEATURE_POLICY_PERSISTENCE_PROPERTY, true);
         setDefault(FEATURE_ENRICHER_PERSISTENCE_PROPERTY, true);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/abf21bdc/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
index 89ac7a1..3b1992d 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
@@ -35,14 +35,8 @@ public abstract class RebindTestFixture<T extends StartableApplication> {
     protected T newApp;
     protected ManagementContext newManagementContext;
 
-    private boolean origPolicyPersistenceEnabled;
-    private boolean origEnricherPersistenceEnabled;
-    
     @BeforeMethod(alwaysRun=true)
     public void setUp() throws Exception {
-        origPolicyPersistenceEnabled = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_POLICY_PERSISTENCE_PROPERTY);
-        origEnricherPersistenceEnabled = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_ENRICHER_PERSISTENCE_PROPERTY);
-        
         mementoDir = Os.newTempDir(getClass());
         origManagementContext = RebindTestUtils.newPersistingManagementContext(mementoDir, classLoader, getPersistPeriodMillis());
         origApp = createApp();
@@ -59,21 +53,16 @@ public abstract class RebindTestFixture<T extends StartableApplication> {
 
     @AfterMethod(alwaysRun=true)
     public void tearDown() throws Exception {
-        try {
-            if (origApp != null) Entities.destroyAll(origApp.getManagementContext());
-            if (newApp != null) Entities.destroyAll(newApp.getManagementContext());
-            if (newManagementContext != null) Entities.destroyAll(newManagementContext);
-            origApp = null;
-            newApp = null;
-            newManagementContext = null;
-    
-            if (origManagementContext != null) Entities.destroyAll(origManagementContext);
-            if (mementoDir != null) FileBasedObjectStore.deleteCompletely(mementoDir);
-            origManagementContext = null;
-        } finally {
-            BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_POLICY_PERSISTENCE_PROPERTY, origPolicyPersistenceEnabled);
-            BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_ENRICHER_PERSISTENCE_PROPERTY, origEnricherPersistenceEnabled);
-        }
+        if (origApp != null) Entities.destroyAll(origApp.getManagementContext());
+        if (newApp != null) Entities.destroyAll(newApp.getManagementContext());
+        if (newManagementContext != null) Entities.destroyAll(newManagementContext);
+        origApp = null;
+        newApp = null;
+        newManagementContext = null;
+
+        if (origManagementContext != null) Entities.destroyAll(origManagementContext);
+        if (mementoDir != null) FileBasedObjectStore.deleteCompletely(mementoDir);
+        origManagementContext = null;
     }
 
     /** rebinds, and sets newApp */


[4/6] git commit: Merge remote-tracking branch 'aledsage/feature/PersistenceExceptionHandler'

Posted by he...@apache.org.
Merge remote-tracking branch 'aledsage/feature/PersistenceExceptionHandler'


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

Branch: refs/heads/master
Commit: 311aed1569d426e0f7188a6237673deb693bebcb
Parents: 7ddca72 648eb8f
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 10:16:42 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 10:16:42 2014 +0100

----------------------------------------------------------------------
 .../rebind/PersistenceExceptionHandler.java     |  32 +++
 .../brooklyn/entity/rebind/RebindContext.java   |   3 +-
 .../entity/rebind/RebindExceptionHandler.java   |  15 ++
 .../brooklyn/entity/rebind/RebindManager.java   |   2 +
 .../mementos/BrooklynMementoPersister.java      |   7 +-
 .../entity/rebind/BasicEntityRebindSupport.java |  18 +-
 .../rebind/ImmediateDeltaChangeListener.java    |  22 ++-
 .../rebind/PeriodicDeltaChangeListener.java     |  24 +--
 .../rebind/PersistenceExceptionHandlerImpl.java | 102 ++++++++++
 .../entity/rebind/RebindContextImpl.java        |  21 +-
 .../rebind/RebindExceptionHandlerImpl.java      | 196 +++++++++++++++++--
 .../entity/rebind/RebindManagerImpl.java        |  54 ++++-
 .../AbstractBrooklynMementoPersister.java       |   5 +-
 .../BrooklynMementoPersisterInMemory.java       |  22 ++-
 .../BrooklynMementoPersisterToFile.java         |   9 +-
 .../BrooklynMementoPersisterToMultiFile.java    |  19 +-
 .../BrooklynMementoPersisterToObjectStore.java  |  55 +++---
 .../internal/BrooklynFeatureEnablement.java     |   2 +
 .../NonDeploymentManagementContext.java         |   6 +
 .../entity/rebind/RebindFailuresTest.java       |  78 ++++++++
 .../brooklyn/entity/rebind/RebindTestUtils.java |   8 +-
 .../rebind/RecordingRebindExceptionHandler.java |   2 +-
 .../BrooklynMementoPersisterTestFixture.java    |   2 +-
 ...BrooklynMementoPersisterToMultiFileTest.java |   3 +-
 .../HighAvailabilityManagerSplitBrainTest.java  |   3 +-
 .../ha/HighAvailabilityManagerTestFixture.java  |   3 +-
 .../AbstractWebAppFixtureIntegrationTest.java   |   5 +-
 .../brooklyn/launcher/BrooklynLauncher.java     |   5 +-
 28 files changed, 610 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/311aed15/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/311aed15/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --cc core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index 54f4943,34346ba..8a2b549
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@@ -266,24 -269,21 +269,24 @@@ public class BrooklynMementoPersisterTo
              if (LOG.isDebugEnabled()) LOG.debug("Ignoring checkpointing entire memento, because not running");
              return;
          }
 -        if (LOG.isDebugEnabled()) LOG.debug("Checkpointing entire memento");
          objectStore.prepareForMasterUse();
          
 +        Stopwatch stopwatch = Stopwatch.createStarted();
 +
          for (EntityMemento entity : newMemento.getEntityMementos().values()) {
-             persist("entities", entity);
+             persist("entities", entity, exceptionHandler);
          }
          for (LocationMemento location : newMemento.getLocationMementos().values()) {
-             persist("locations", location);
+             persist("locations", location, exceptionHandler);
          }
          for (PolicyMemento policy : newMemento.getPolicyMementos().values()) {
-             persist("policies", policy);
+             persist("policies", policy, exceptionHandler);
          }
          for (EnricherMemento enricher : newMemento.getEnricherMementos().values()) {
-             persist("enrichers", enricher);
+             persist("enrichers", enricher, exceptionHandler);
          }
 +        
 +        if (LOG.isDebugEnabled()) LOG.debug("Checkpointed entire memento in {}", Time.makeTimeStringRounded(stopwatch));
      }
      
      @Override
@@@ -292,40 -292,37 +295,40 @@@
              if (LOG.isDebugEnabled()) LOG.debug("Ignoring checkpointed delta of memento, because not running");
              return;
          }
 -        if (LOG.isDebugEnabled()) LOG.debug("Checkpointed delta of memento; updating {} entities, {} locations and {} policies; " +
 -        		"removing {} entities, {} locations and {} policies", 
 -                new Object[] {delta.entities(), delta.locations(), delta.policies(),
 -                delta.removedEntityIds(), delta.removedLocationIds(), delta.removedPolicyIds()});
          objectStore.prepareForMasterUse();
          
 +        Stopwatch stopwatch = Stopwatch.createStarted();
 +        
          for (EntityMemento entity : delta.entities()) {
-             persist("entities", entity);
+             persist("entities", entity, exceptionHandler);
          }
          for (LocationMemento location : delta.locations()) {
-             persist("locations", location);
+             persist("locations", location, exceptionHandler);
          }
          for (PolicyMemento policy : delta.policies()) {
-             persist("policies", policy);
+             persist("policies", policy, exceptionHandler);
          }
          for (EnricherMemento enricher : delta.enrichers()) {
-             persist("enrichers", enricher);
+             persist("enrichers", enricher, exceptionHandler);
          }
          
          for (String id : delta.removedEntityIds()) {
-             delete("entities", id);
+             delete("entities", id, exceptionHandler);
          }
          for (String id : delta.removedLocationIds()) {
-             delete("locations", id);
+             delete("locations", id, exceptionHandler);
          }
          for (String id : delta.removedPolicyIds()) {
-             delete("policies", id);
+             delete("policies", id, exceptionHandler);
          }
          for (String id : delta.removedEnricherIds()) {
-             delete("enrichers", id);
+             delete("enrichers", id, exceptionHandler);
          }
 +        
 +        if (LOG.isDebugEnabled()) LOG.debug("Checkpointed delta of memento in {}; updated {} entities, {} locations and {} policies; " +
 +                "removing {} entities, {} locations and {} policies", 
 +                new Object[] {Time.makeTimeStringRounded(stopwatch), delta.entities(), delta.locations(), delta.policies(),
 +                delta.removedEntityIds(), delta.removedLocationIds(), delta.removedPolicyIds()});
      }
  
      @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/311aed15/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/311aed15/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerSplitBrainTest.java
----------------------------------------------------------------------


[5/6] git commit: Merge remote-tracking branch 'aledsage/fix/rebind-addPolicyInSeparatePhase'

Posted by he...@apache.org.
Merge remote-tracking branch 'aledsage/fix/rebind-addPolicyInSeparatePhase'

Conflicts:
	core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
        missing error catching in add{Enrichers,Policies} from #34, whereas those methods moved here.  will add back handler in next commit.


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

Branch: refs/heads/master
Commit: fdbacdfc15fe3ebe03e51e1c1dabcf70bb5d0d43
Parents: 311aed1 59ce9e8
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 10:17:21 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 10:17:21 2014 +0100

----------------------------------------------------------------------
 .../brooklyn/entity/rebind/RebindSupport.java   |  8 ++-
 .../rebind/BasicEnricherRebindSupport.java      | 13 ++++-
 .../entity/rebind/BasicEntityRebindSupport.java | 58 +++++++++-----------
 .../rebind/BasicLocationRebindSupport.java      | 14 ++++-
 .../entity/rebind/BasicPolicyRebindSupport.java | 14 ++++-
 .../entity/rebind/RebindManagerImpl.java        | 49 +++++++++++++++--
 .../entity/rebind/RebindLocationTest.java       |  4 +-
 .../entity/rebind/RebindPolicyTest.java         | 55 +++++++++++++++++++
 8 files changed, 168 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/fdbacdfc/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --cc core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 81c4f7b,d3928b7..f105efe
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@@ -262,13 -240,15 +262,15 @@@ public class RebindManagerImpl implemen
              Map<String,Policy> policies = Maps.newLinkedHashMap();
              Map<String,Enricher> enrichers = Maps.newLinkedHashMap();
              
 -            final RebindContextImpl rebindContext = new RebindContextImpl(classLoader);
 +            final RebindContextImpl rebindContext = new RebindContextImpl(exceptionHandler, classLoader);
              LookupContext realLookupContext = new RebindContextLookupContext(managementContext, rebindContext, exceptionHandler);
              
-             // Two-phase deserialization.
-             // First we deserialize just the "manifest" to find all instances (and their types).
-             // Then we deserialize so that inter-entity references can be set.
-             //
+             // Four-phase deserialization.
+             //  1. deserialize just the "manifest" to find all instances (and their types).
+             //  2. deserialize so that inter-entity references can be set (and entity config/state is set).
+             //  3. add policies+enrichers to all the entities.
+             //  4. manage the entities
+             
              // TODO if underlying data-store is changed between first and second phase (e.g. to add an
              // entity), then second phase might try to reconstitute an entity that has not been put in
              // the rebindContext. This should not affect normal production usage, because rebind is run


[2/6] git commit: BROOKLYN-14: policy+enricher persistence/rebind enabled

Posted by he...@apache.org.
BROOKLYN-14: policy+enricher persistence/rebind enabled


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

Branch: refs/heads/master
Commit: 648eb8fb7ea66cdef01950bfd0c9d65b056d6d25
Parents: 391b3bb
Author: Aled Sage <al...@gmail.com>
Authored: Mon Jun 30 22:51:47 2014 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Mon Jun 30 22:53:04 2014 +0100

----------------------------------------------------------------------
 .../src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/648eb8fb/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java b/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
index 7c2a9ba..a0a520d 100644
--- a/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
+++ b/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
@@ -27,6 +27,8 @@ public class BrooklynFeatureEnablement {
         // that can be turned off via system properties. One might want to do that because
         // the feature is deemed risky!
         //   e.g. setDefault(ENABLE_POLICY_PERSISTENCE_PROPERTY, true);
+        setDefault(FEATURE_POLICY_PERSISTENCE_PROPERTY, true);
+        setDefault(FEATURE_ENRICHER_PERSISTENCE_PROPERTY, true);
     }
     
     public static boolean isEnabled(String property) {