brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rich...@apache.org
Subject [5/8] git commit: AbstractMembershipTrackingPolicy usages not anonymous classes
Date Tue, 27 May 2014 21:35:17 GMT
AbstractMembershipTrackingPolicy usages not anonymous classes

- sub-class AbstractMembershipTrackingPolicy so that persist/rebind
  could re-create the policy; i.e. not anonymous inner classes.


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

Branch: refs/heads/master
Commit: e1b08d5a557b0e557aac6cff9111ef4ae3610c9d
Parents: 0238066
Author: Aled Sage <aled.sage@gmail.com>
Authored: Mon May 26 12:09:12 2014 +0100
Committer: Aled Sage <aled.sage@gmail.com>
Committed: Tue May 27 20:50:56 2014 +0100

----------------------------------------------------------------------
 .../monitoring/zabbix/ZabbixServerImpl.java     | 31 ++++++----
 .../entity/zookeeper/ZooKeeperEnsembleImpl.java | 55 +++++++++--------
 .../entity/network/bind/BindDnsServerImpl.java  | 40 +++++++-----
 .../cassandra/CassandraDatacenterImpl.java      | 55 ++++++++---------
 .../nosql/cassandra/CassandraFabricImpl.java    | 45 +++++++-------
 .../nosql/couchbase/CouchbaseClusterImpl.java   | 37 +++++------
 .../nosql/mongodb/MongoDBReplicaSetImpl.java    | 64 +++++++++++---------
 .../sharding/MongoDBRouterClusterImpl.java      | 30 ++++-----
 .../sharding/MongoDBShardedDeploymentImpl.java  | 30 +++++----
 .../entity/nosql/riak/RiakClusterImpl.java      | 34 ++++-------
 .../entity/dns/AbstractGeoDnsServiceImpl.java   | 22 ++++---
 .../AbstractNonProvisionedControllerImpl.java   | 55 +++++++++++------
 .../entity/proxy/LoadBalancerClusterImpl.java   | 14 +++--
 13 files changed, 275 insertions(+), 237 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
b/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
index 1df3fbc..6a9c73d 100644
--- a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
+++ b/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
@@ -16,7 +16,7 @@ import brooklyn.event.feed.http.HttpPollConfig;
 import brooklyn.event.feed.http.HttpValueFunctions;
 import brooklyn.location.Location;
 import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.collections.MutableMap;
+import brooklyn.policy.PolicySpec;
 
 import com.google.common.base.Functions;
 import com.google.common.base.Optional;
@@ -34,10 +34,9 @@ public class ZabbixServerImpl extends AbstractEntity implements ZabbixServer
{
 
     private Object[] mutex = new Object[0];
     private DynamicGroup monitoredEntities;
-    private AbstractMembershipTrackingPolicy policy;
+    private AgentTrackingPolicy policy;
     private Multimap<Location, Entity> entityLocations = HashMultimap.create();
 
-
     private transient HttpFeed login;
 
     @Override
@@ -66,16 +65,9 @@ public class ZabbixServerImpl extends AbstractEntity implements ZabbixServer
{
                         .onSuccess(HttpValueFunctions.jsonContents("result", String.class)))
                 .build();
 
-        policy = new AbstractMembershipTrackingPolicy(MutableMap.of("name", "Zabbix Agent
Tracker")) {
-            @Override
-            protected void onEntityChange(Entity member) { added(member); }
-            @Override
-            protected void onEntityAdded(Entity member) { } // Ignore
-            @Override
-            protected void onEntityRemoved(Entity member) { removed(member); }
-        };
-        addPolicy(policy);
-        policy.setGroup(monitoredEntities);
+        policy = addPolicy(PolicySpec.create(AgentTrackingPolicy.class)
+                .displayName("Zabbix Agent Tracker")
+                .configure("group", monitoredEntities));
 
         for (Entity each : monitoredEntities.getMembers()) {
             added(each);
@@ -84,6 +76,19 @@ public class ZabbixServerImpl extends AbstractEntity implements ZabbixServer
{
         setAttribute(Startable.SERVICE_UP, true);
     }
 
+    public static class AgentTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override
+        protected void onEntityChange(Entity member) {
+            ((ZabbixServerImpl)entity).added(member); }
+        @Override
+        protected void onEntityAdded(Entity member) {
+        } // Ignore
+        @Override
+        protected void onEntityRemoved(Entity member) {
+            ((ZabbixServerImpl)entity).removed(member);
+        }
+    }
+    
     public void added(Entity member) {
         synchronized (mutex) {
             Optional<Location> location = Iterables.tryFind(member.getLocations(),
Predicates.instanceOf(SshMachineLocation.class));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperEnsembleImpl.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperEnsembleImpl.java
b/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperEnsembleImpl.java
index 5427089..6d405d9 100644
--- a/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperEnsembleImpl.java
+++ b/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperEnsembleImpl.java
@@ -1,5 +1,12 @@
 package brooklyn.entity.zookeeper;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.Attributes;
 import brooklyn.entity.basic.EntityInternal;
@@ -8,19 +15,16 @@ import brooklyn.entity.group.DynamicClusterImpl;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.trait.Startable;
 import brooklyn.location.Location;
-import brooklyn.util.collections.MutableMap;
-import com.google.common.collect.Lists;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import brooklyn.policy.PolicySpec;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
+import com.google.common.collect.Lists;
 
 public class ZooKeeperEnsembleImpl extends DynamicClusterImpl implements ZooKeeperEnsemble
{
 
     private static final Logger log = LoggerFactory.getLogger(ZooKeeperEnsembleImpl.class);
     private static final AtomicInteger myId = new AtomicInteger();
+    
+    private MemberTrackingPolicy policy;
 
     public ZooKeeperEnsembleImpl() {}
 
@@ -42,28 +46,29 @@ public class ZooKeeperEnsembleImpl extends DynamicClusterImpl implements
ZooKeep
         log.info("Initializing the ZooKeeper Ensemble");
         super.init();
 
-        AbstractMembershipTrackingPolicy policy = new AbstractMembershipTrackingPolicy(MutableMap.of("name",
"Members tracker")) {
-            @Override
-            protected void onEntityChange(Entity member) {
-            }
+        policy = addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                .displayName("Members tracker")
+                .configure("group", this));
+    }
 
-            @Override
-            protected void onEntityAdded(Entity member) {
-                if (member.getAttribute(ZooKeeperNode.MY_ID) == null) {
-                    ((EntityInternal) member).setAttribute(ZooKeeperNode.MY_ID, myId.incrementAndGet());
-                }
-                setAttribute(SERVICE_UP, calculateServiceUp());
-            }
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override
+        protected void onEntityChange(Entity member) {
+        }
 
-            @Override
-            protected void onEntityRemoved(Entity member) {
-                setAttribute(SERVICE_UP, calculateServiceUp());
+        @Override
+        protected void onEntityAdded(Entity member) {
+            if (member.getAttribute(ZooKeeperNode.MY_ID) == null) {
+                ((EntityInternal) member).setAttribute(ZooKeeperNode.MY_ID, myId.incrementAndGet());
             }
-        };
-        addPolicy(policy);
-        policy.setGroup(this);
+            entity.setAttribute(SERVICE_UP, ((ZooKeeperEnsembleImpl)entity).calculateServiceUp());
+        }
 
-    }
+        @Override
+        protected void onEntityRemoved(Entity member) {
+            entity.setAttribute(SERVICE_UP, ((ZooKeeperEnsembleImpl)entity).calculateServiceUp());
+        }
+    };
 
     @Override
     public synchronized boolean addMember(Entity member) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/network/src/main/java/brooklyn/entity/network/bind/BindDnsServerImpl.java
----------------------------------------------------------------------
diff --git a/software/network/src/main/java/brooklyn/entity/network/bind/BindDnsServerImpl.java
b/software/network/src/main/java/brooklyn/entity/network/bind/BindDnsServerImpl.java
index 313c231..3df6a9a 100644
--- a/software/network/src/main/java/brooklyn/entity/network/bind/BindDnsServerImpl.java
+++ b/software/network/src/main/java/brooklyn/entity/network/bind/BindDnsServerImpl.java
@@ -32,6 +32,7 @@ import brooklyn.entity.trait.Startable;
 import brooklyn.location.Location;
 import brooklyn.location.MachineLocation;
 import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.policy.PolicySpec;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.net.Cidr;
 import brooklyn.util.ssh.BashCommands;
@@ -61,7 +62,7 @@ public class BindDnsServerImpl extends SoftwareProcessImpl implements BindDnsSer
     private AtomicLong serial = new AtomicLong(System.currentTimeMillis());
     private Object[] mutex = new Object[0];
     private DynamicGroup entities;
-    private AbstractMembershipTrackingPolicy policy;
+    private MemberTrackingPolicy policy;
     private Multimap<Location, Entity> entityLocations = HashMultimap.create();
     private ConcurrentMap<String, String> addressMappings = Maps.newConcurrentMap();
     private ConcurrentMap<String, String> reverseMappings = Maps.newConcurrentMap();
@@ -139,29 +140,36 @@ public class BindDnsServerImpl extends SoftwareProcessImpl implements
BindDnsSer
         setAttribute(REVERSE_LOOKUP_DOMAIN, reverseLookupDomain);
 
         Map<?, ?> flags = MutableMap.builder()
-                .put("name", "Address tracker")
-                .put("sensorsToTrack", ImmutableSet.of(getConfig(HOSTNAME_SENSOR)))
                 .build();
-        policy = new AbstractMembershipTrackingPolicy(flags) {
-            @Override
-            protected void onEntityChange(Entity member) { added(member); }
-            @Override
-            protected void onEntityAdded(Entity member) {
-                if (Strings.isNonBlank(member.getAttribute(getConfig(HOSTNAME_SENSOR))))
added(member); // Ignore, unless hostname set
-            }
-            @Override
-            protected void onEntityRemoved(Entity member) { removed(member); }
-        };
+        policy = addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                .displayName("Address tracker")
+                .configure("sensorsToTrack", ImmutableSet.of(getConfig(HOSTNAME_SENSOR)))
+                .configure("group", entities));
 
         // For any entities that have already come up
         for (Entity member : entities.getMembers()) {
             if (Strings.isNonBlank(member.getAttribute(getConfig(HOSTNAME_SENSOR)))) added(member);
// Ignore, unless hostname set
         }
-
-        addPolicy(policy);
-        policy.setGroup(entities);
     }
 
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override
+        protected void onEntityChange(Entity member) {
+            // TODO Should we guard to only call if service_up and if hostname set?
+            ((BindDnsServerImpl)entity).added(member);
+        }
+        @Override
+        protected void onEntityAdded(Entity member) {
+            if (Strings.isNonBlank(member.getAttribute(getConfig(HOSTNAME_SENSOR)))) {
+                ((BindDnsServerImpl)entity).added(member); // Ignore, unless hostname set
+            }
+        }
+        @Override
+        protected void onEntityRemoved(Entity member) {
+            ((BindDnsServerImpl)entity).removed(member);
+        }
+    };
+
     @Override
     public void postStart() {
         update();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
b/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
index 34cddf6..00171d9 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
@@ -26,20 +26,18 @@ import brooklyn.entity.basic.Lifecycle;
 import brooklyn.entity.effector.EffectorBody;
 import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
 import brooklyn.entity.group.DynamicClusterImpl;
-import brooklyn.entity.group.StopFailedRuntimeException;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.event.AttributeSensor;
 import brooklyn.event.SensorEvent;
 import brooklyn.event.SensorEventListener;
-import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
 import brooklyn.location.Location;
 import brooklyn.location.basic.Machines;
+import brooklyn.policy.PolicySpec;
 import brooklyn.util.ResourceUtils;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.collections.MutableSet;
 import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.text.Strings;
 import brooklyn.util.time.Time;
 
@@ -48,7 +46,6 @@ import com.google.common.base.Optional;
 import com.google.common.base.Supplier;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.LinkedHashMultimap;
@@ -133,7 +130,7 @@ public class CassandraDatacenterImpl extends DynamicClusterImpl implements
Cassa
     
     protected SeedTracker seedTracker = new SeedTracker();
     protected TokenGenerator tokenGenerator = null;
-    private AbstractMembershipTrackingPolicy policy;
+    private MemberTrackingPolicy policy;
 
     public CassandraDatacenterImpl() {
     }
@@ -326,32 +323,30 @@ public class CassandraDatacenterImpl extends DynamicClusterImpl implements
Cassa
     protected void connectSensors() {
         connectEnrichers();
         
-        // track members
-        Map<String, Object> flags = MutableMap.<String, Object>builder()
-                .put("name", "Cassandra Cluster Tracker")
-                .put("sensorsToTrack", ImmutableSet.of(Attributes.SERVICE_UP, Attributes.HOSTNAME,
CassandraNode.THRIFT_PORT))
-                .build();
-        policy = new AbstractMembershipTrackingPolicy(flags) {
-            @Override
-            protected void onEntityChange(Entity member) {
-                if (log.isDebugEnabled()) log.debug("Node {} updated in Cluster {}", member,
this);
-                update();
-            }
-            @Override
-            protected void onEntityAdded(Entity member) {
-                if (log.isDebugEnabled()) log.debug("Node {} added to Cluster {}", member,
this);
-                update();
-            }
-            @Override
-            protected void onEntityRemoved(Entity member) {
-                if (log.isDebugEnabled()) log.debug("Node {} removed from Cluster {}", member,
this);
-                update();
-            }
-        };
-        addPolicy(policy);
-        policy.setGroup(this);
+        policy = addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                .displayName("Cassandra Cluster Tracker")
+                .configure("sensorsToTrack", ImmutableSet.of(Attributes.SERVICE_UP, Attributes.HOSTNAME,
CassandraNode.THRIFT_PORT))
+                .configure("group", this));
     }
-    
+
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override
+        protected void onEntityChange(Entity member) {
+            if (log.isDebugEnabled()) log.debug("Node {} updated in Cluster {}", member,
this);
+            ((CassandraDatacenterImpl)entity).update();
+        }
+        @Override
+        protected void onEntityAdded(Entity member) {
+            if (log.isDebugEnabled()) log.debug("Node {} added to Cluster {}", member, this);
+            ((CassandraDatacenterImpl)entity).update();
+        }
+        @Override
+        protected void onEntityRemoved(Entity member) {
+            if (log.isDebugEnabled()) log.debug("Node {} removed from Cluster {}", member,
this);
+            ((CassandraDatacenterImpl)entity).update();
+        }
+    };
+
     @SuppressWarnings("unchecked")
     protected void connectEnrichers() {
         List<? extends List<? extends AttributeSensor<? extends Number>>>
summingEnricherSetup = ImmutableList.of(

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraFabricImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraFabricImpl.java
b/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraFabricImpl.java
index 9814aa5..36c3015 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraFabricImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraFabricImpl.java
@@ -23,6 +23,7 @@ import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.event.SensorEvent;
 import brooklyn.event.SensorEventListener;
 import brooklyn.location.Location;
+import brooklyn.policy.PolicySpec;
 import brooklyn.util.collections.CollectionFunctionals;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.collections.MutableSet;
@@ -56,7 +57,7 @@ public class CassandraFabricImpl extends DynamicFabricImpl implements CassandraF
     // Mutex for synchronizing during re-size operations
     private final Object mutex = new Object[0];
 
-    private AbstractMembershipTrackingPolicy policy;
+    private MemberTrackingPolicy policy;
 
     private final Supplier<Set<Entity>> defaultSeedSupplier = new Supplier<Set<Entity>>()
{
         @Override public Set<Entity> get() {
@@ -192,25 +193,9 @@ public class CassandraFabricImpl extends DynamicFabricImpl implements
CassandraF
             setConfig(CassandraDatacenter.SEED_SUPPLIER, getSeedSupplier());
         
         // track members
-        policy = new AbstractMembershipTrackingPolicy(MutableMap.of("name", "Cassandra Fabric
Tracker")) {
-            @Override
-            protected void onEntityChange(Entity member) {
-                if (log.isDebugEnabled()) log.debug("Location {} updated in Fabric {}", member,
CassandraFabricImpl.this);
-                update();
-            }
-            @Override
-            protected void onEntityAdded(Entity member) {
-                if (log.isDebugEnabled()) log.debug("Location {} added to Fabric {}", member,
CassandraFabricImpl.this);
-                update();
-            }
-            @Override
-            protected void onEntityRemoved(Entity member) {
-                if (log.isDebugEnabled()) log.debug("Location {} removed from Fabric {}",
member, CassandraFabricImpl.this);
-                update();
-            }
-        };
-        addPolicy(policy);
-        policy.setGroup(this);
+        policy = addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                .displayName("Cassandra Fabric Tracker")
+                .configure("group", this));
 
         // Track first node's startup
         subscribeToMembers(this, CassandraDatacenter.FIRST_NODE_STARTED_TIME_UTC, new SensorEventListener<Long>()
{
@@ -244,7 +229,25 @@ public class CassandraFabricImpl extends DynamicFabricImpl implements
CassandraF
             }
         });
     }
-    
+
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override
+        protected void onEntityChange(Entity member) {
+            if (log.isDebugEnabled()) log.debug("Location {} updated in Fabric {}", member,
entity);
+            ((CassandraFabricImpl)entity).update();
+        }
+        @Override
+        protected void onEntityAdded(Entity member) {
+            if (log.isDebugEnabled()) log.debug("Location {} added to Fabric {}", member,
entity);
+            ((CassandraFabricImpl)entity).update();
+        }
+        @Override
+        protected void onEntityRemoved(Entity member) {
+            if (log.isDebugEnabled()) log.debug("Location {} removed from Fabric {}", member,
entity);
+            ((CassandraFabricImpl)entity).update();
+        }
+    };
+
     protected int getSeedQuorumSize() {
         Integer quorumSize = getConfig(INITIAL_QUORUM_SIZE);
         if (quorumSize!=null && quorumSize>0)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
index f532a4f..148b445 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
@@ -3,7 +3,6 @@ package brooklyn.entity.nosql.couchbase;
 import static brooklyn.util.JavaGroovyEquivalents.groovyTruth;
 
 import java.util.Collection;
-import java.util.Map;
 import java.util.Set;
 
 import org.slf4j.Logger;
@@ -21,7 +20,7 @@ import brooklyn.entity.trait.Startable;
 import brooklyn.event.SensorEvent;
 import brooklyn.event.SensorEventListener;
 import brooklyn.location.Location;
-import brooklyn.util.collections.MutableMap;
+import brooklyn.policy.PolicySpec;
 import brooklyn.util.collections.MutableSet;
 import brooklyn.util.time.Time;
 
@@ -94,28 +93,24 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements
Couchbas
     }
 
     protected void connectSensors() {
-        Map<String, Object> flags = MutableMap.<String, Object>builder()
-                .put("name", "Controller targets tracker")
-                .build();
-
-        AbstractMembershipTrackingPolicy serverPoolMemberTrackerPolicy = new AbstractMembershipTrackingPolicy(flags)
{
-            protected void onEntityChange(Entity member) {
-                onServerPoolMemberChanged(member);
-            }
-
-            protected void onEntityAdded(Entity member) {
-                onServerPoolMemberChanged(member);
-            }
+        addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                .displayName("Controller targets tracker")
+                .configure("group", this));
+    }
 
-            protected void onEntityRemoved(Entity member) {
-                onServerPoolMemberChanged(member);
-            }
-        };
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override protected void onEntityChange(Entity member) {
+            ((CouchbaseClusterImpl)entity).onServerPoolMemberChanged(member);
+        }
 
-        addPolicy(serverPoolMemberTrackerPolicy);
-        serverPoolMemberTrackerPolicy.setGroup(this);
+        @Override protected void onEntityAdded(Entity member) {
+            ((CouchbaseClusterImpl)entity).onServerPoolMemberChanged(member);
+        }
 
-    }
+        @Override protected void onEntityRemoved(Entity member) {
+            ((CouchbaseClusterImpl)entity).onServerPoolMemberChanged(member);
+        }
+    };
 
     protected synchronized void onServerPoolMemberChanged(Entity member) {
         if (log.isTraceEnabled()) log.trace("For {}, considering membership of {} which is
in locations {}",

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
b/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
index f999f5e..7c668e7 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
@@ -2,6 +2,23 @@ package brooklyn.entity.nosql.mongodb;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import brooklyn.enricher.Enrichers;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.Lifecycle;
@@ -13,30 +30,17 @@ import brooklyn.event.AttributeSensor;
 import brooklyn.event.SensorEvent;
 import brooklyn.event.SensorEventListener;
 import brooklyn.location.Location;
+import brooklyn.policy.PolicySpec;
 import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
 import brooklyn.util.collections.MutableSet;
 import brooklyn.util.text.Strings;
+
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import javax.annotation.Nullable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Implementation of {@link MongoDBReplicaSet}.
@@ -52,7 +56,7 @@ public class MongoDBReplicaSetImpl extends DynamicClusterImpl implements
MongoDB
     // Provides IDs for replica set members. The first member will have ID 0.
     private final AtomicInteger nextMemberId = new AtomicInteger(0);
 
-    private AbstractMembershipTrackingPolicy policy;
+    private MemberTrackingPolicy policy;
     private final AtomicBoolean mustInitialise = new AtomicBoolean(true);
 
     @SuppressWarnings("unchecked")
@@ -261,20 +265,9 @@ public class MongoDBReplicaSetImpl extends DynamicClusterImpl implements
MongoDB
     public void start(Collection<? extends Location> locations) {
         // Promises that all the cluster's members have SERVICE_UP true on returning.
         super.start(locations);
-        policy = new AbstractMembershipTrackingPolicy(MutableMap.of("name", getName() + "
membership tracker")) {
-            @Override protected void onEntityChange(Entity member) {
-                // Ignored
-            }
-            @Override protected void onEntityAdded(Entity member) {
-                serverAdded((MongoDBServer) member);
-            }
-            @Override protected void onEntityRemoved(Entity member) {
-                serverRemoved((MongoDBServer) member);
-            }
-        };
-
-        addPolicy(policy);
-        policy.setGroup(this);
+        policy = addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                .displayName(getName() + " membership tracker")
+                .configure("group", this));
 
         for (AttributeSensor<Long> sensor: SENSORS_TO_SUM)
             addEnricher(Enrichers.builder()
@@ -346,4 +339,15 @@ public class MongoDBReplicaSetImpl extends DynamicClusterImpl implements
MongoDB
         setAttribute(Startable.SERVICE_UP, false);
     }
 
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override protected void onEntityChange(Entity member) {
+            // Ignored
+        }
+        @Override protected void onEntityAdded(Entity member) {
+            ((MongoDBReplicaSetImpl)entity).serverAdded((MongoDBServer) member);
+        }
+        @Override protected void onEntityRemoved(Entity member) {
+            ((MongoDBReplicaSetImpl)entity).serverRemoved((MongoDBServer) member);
+        }
+    };
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterClusterImpl.java
b/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterClusterImpl.java
index cf13c82..1f92799 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterClusterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterClusterImpl.java
@@ -11,7 +11,7 @@ import brooklyn.entity.trait.Startable;
 import brooklyn.event.SensorEvent;
 import brooklyn.event.SensorEventListener;
 import brooklyn.location.Location;
-import brooklyn.util.collections.MutableMap;
+import brooklyn.policy.PolicySpec;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
@@ -31,19 +31,21 @@ public class MongoDBRouterClusterImpl extends DynamicClusterImpl implements
Mong
     @Override
     public void start(Collection<? extends Location> locations) {
         super.start(locations);
-        AbstractMembershipTrackingPolicy policy = new AbstractMembershipTrackingPolicy(MutableMap.of("name",
"Router cluster membership tracker")) {
-            @Override protected void onEntityAdded(Entity member) {
-                setAnyRouter();
-            }
-            @Override protected void onEntityRemoved(Entity member) {
-                setAnyRouter();
-            }
-            @Override protected void onEntityChange(Entity member) {
-                setAnyRouter();
-            }
-        };
-        addPolicy(policy);
-        policy.setGroup(this);
+        addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                .displayName("Router cluster membership tracker")
+                .configure("group", this));
+    }
+    
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override protected void onEntityEvent(EventType type, Entity entity) {
+            ((MongoDBRouterClusterImpl)entity).setAnyRouter();
+        }
+        @Override protected void onEntityRemoved(Entity member) {
+            ((MongoDBRouterClusterImpl)entity).setAnyRouter();
+        }
+        @Override protected void onEntityChange(Entity member) {
+            ((MongoDBRouterClusterImpl)entity).setAnyRouter();
+        }
     }
     
     protected void setAnyRouter() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
b/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
index 704150c..5b5e462 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
@@ -20,7 +20,7 @@ import brooklyn.entity.group.DynamicCluster;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.trait.Startable;
 import brooklyn.location.Location;
-import brooklyn.util.collections.MutableMap;
+import brooklyn.policy.PolicySpec;
 import brooklyn.util.exceptions.Exceptions;
 
 import com.google.common.collect.ImmutableList;
@@ -57,16 +57,9 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements
Mong
                 .get();
 
             if (getConfigRaw(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP, true).isPresent())
{
-                AbstractMembershipTrackingPolicy policy = new AbstractMembershipTrackingPolicy(MutableMap.of("name",
"Co-located router tracker")) {
-                    protected void onEntityAdded(Entity member) {
-                        routers.addMember(member.getAttribute(CoLocatedMongoDBRouter.ROUTER));
-                    }
-                    protected void onEntityRemoved(Entity member) {
-                        routers.removeMember(member.getAttribute(CoLocatedMongoDBRouter.ROUTER));
-                    }
-                };
-                addPolicy(policy);
-                policy.setGroup((Group)getConfig(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP));
+                addPolicy(PolicySpec.create(ColocatedRouterTrackingPolicy.class)
+                        .displayName("Co-located router tracker")
+                        .configure("group", (Group)getConfig(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP)));
             }
             setAttribute(SERVICE_UP, true);
             setAttribute(Attributes.SERVICE_STATE, Lifecycle.RUNNING);
@@ -76,7 +69,20 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements
Mong
             throw Exceptions.propagate(e);
         }
     }
-    
+
+    public static class ColocatedRouterTrackingPolicy extends AbstractMembershipTrackingPolicy
{
+        @Override
+        protected void onEntityAdded(Entity member) {
+            MongoDBRouterCluster cluster = entity.getAttribute(ROUTER_CLUSTER);
+            cluster.addMember(member.getAttribute(CoLocatedMongoDBRouter.ROUTER));
+        }
+        @Override
+        protected void onEntityRemoved(Entity member) {
+            MongoDBRouterCluster cluster = entity.getAttribute(ROUTER_CLUSTER);
+            cluster.removeMember(member.getAttribute(CoLocatedMongoDBRouter.ROUTER));
+        }
+    };
+
     @Override
     public void stop() {
         setAttribute(Attributes.SERVICE_STATE, Lifecycle.STOPPING);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/nosql/src/main/java/brooklyn/entity/nosql/riak/RiakClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/riak/RiakClusterImpl.java
b/software/nosql/src/main/java/brooklyn/entity/nosql/riak/RiakClusterImpl.java
index 5508d5e..37ce1f4 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/riak/RiakClusterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/riak/RiakClusterImpl.java
@@ -19,7 +19,7 @@ import brooklyn.entity.group.DynamicClusterImpl;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.trait.Startable;
 import brooklyn.location.Location;
-import brooklyn.util.collections.MutableMap;
+import brooklyn.policy.PolicySpec;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
@@ -50,30 +50,18 @@ public class RiakClusterImpl extends DynamicClusterImpl implements RiakCluster
{
     }
     
     protected void connectSensors() {
-
-        Map<String, Object> flags = MutableMap.<String, Object>builder()
-                .put("name", "Controller targets tracker")
-                .put("sensorsToTrack", ImmutableSet.of(RiakNode.SERVICE_UP))
-                .build();
-
-        AbstractMembershipTrackingPolicy serverPoolMemberTrackerPolicy = new AbstractMembershipTrackingPolicy(flags)
{
-            protected void onEntityChange(Entity member) {
-                onServerPoolMemberChanged(member);
-            }
-
-            protected void onEntityAdded(Entity member) {
-                onServerPoolMemberChanged(member);
-            }
-
-            protected void onEntityRemoved(Entity member) {
-                onServerPoolMemberChanged(member);
-            }
-        };
-
-        addPolicy(serverPoolMemberTrackerPolicy);
-        serverPoolMemberTrackerPolicy.setGroup(this);
+        addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                .displayName("Controller targets tracker")
+                .configure("sensorsToTrack", ImmutableSet.of(RiakNode.SERVICE_UP))
+                .configure("group", this));
     }
 
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override protected void onEntityEvent(EventType type, Entity entity) {
+            ((RiakClusterImpl)super.entity).onServerPoolMemberChanged(entity);
+        }
+    };
+
     protected synchronized void onServerPoolMemberChanged(Entity member) {
         if (log.isTraceEnabled()) log.trace("For {}, considering membership of {} which is
in locations {}",
                 new Object[]{this, member, member.getLocations()});

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
b/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
index 54f6982..e920076 100644
--- a/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
@@ -26,7 +26,7 @@ import brooklyn.entity.basic.Lifecycle;
 import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
 import brooklyn.entity.webapp.WebAppService;
 import brooklyn.location.geo.HostGeoInfo;
-import brooklyn.util.collections.MutableMap;
+import brooklyn.policy.PolicySpec;
 import brooklyn.util.collections.MutableSet;
 import brooklyn.util.flags.SetFromFlag;
 import brooklyn.util.net.Networking;
@@ -106,22 +106,26 @@ public abstract class AbstractGeoDnsServiceImpl extends AbstractEntity
implement
         }
         endTracker();
         log.debug("Initializing tracker for "+this+", following "+targetEntityProvider);
-        tracker = new AbstractMembershipTrackingPolicy(MutableMap.of(
-                "name", "GeoDNS targets tracker",
-                "sensorsToTrack", ImmutableSet.of(HOSTNAME, ADDRESS, WebAppService.ROOT_URL))
) {
-            @Override
-            protected void onEntityEvent(EventType type, Entity entity) { refreshGroupMembership();
}
-        };
-        addPolicy(tracker);
-        tracker.setGroup(targetEntityProvider);
+        tracker = addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                .displayName("GeoDNS targets tracker")
+                .configure("sensorsToTrack", ImmutableSet.of(HOSTNAME, ADDRESS, WebAppService.ROOT_URL))
+                .configure("group", targetEntityProvider));
         refreshGroupMembership();
     }
+    
     protected synchronized void endTracker() {
         if (tracker == null || targetEntityProvider==null) return;
         removePolicy(tracker);
         tracker = null;
     }
     
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override
+        protected void onEntityEvent(EventType type, Entity entity) {
+            ((AbstractGeoDnsServiceImpl)super.entity).refreshGroupMembership();
+        }
+    }
+
     @Override
     public abstract String getHostname();
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java
b/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java
index 280d423..841d85a 100644
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java
@@ -19,6 +19,7 @@ import brooklyn.entity.trait.Startable;
 import brooklyn.event.AttributeSensor;
 import brooklyn.event.feed.ConfigToAttributes;
 import brooklyn.location.Location;
+import brooklyn.policy.PolicySpec;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.guava.Maybe;
 
@@ -52,13 +53,14 @@ public abstract class AbstractNonProvisionedControllerImpl extends AbstractEntit
         this(MutableMap.of(), parent, cluster);
     }
     public AbstractNonProvisionedControllerImpl(Map properties, Entity parent, Cluster cluster)
{
-        serverPoolMemberTrackerPolicy = new AbstractMembershipTrackingPolicy(MutableMap.of("name",
"Controller targets tracker")) {
-            protected void onEntityChange(Entity member) { onServerPoolMemberChanged(member);
}
-            protected void onEntityAdded(Entity member) { onServerPoolMemberChanged(member);
}
-            protected void onEntityRemoved(Entity member) { onServerPoolMemberChanged(member);
}
-        };
     }
-    
+
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override protected void onEntityEvent(EventType type, Entity member) {
+            ((AbstractNonProvisionedControllerImpl)super.entity).onServerPoolMemberChanged(member);
+        }
+    }
+
     /**
      * Opportunity to do late-binding of the cluster that is being controlled. Must be called
before start().
      * Can pass in the 'serverPool'.
@@ -80,6 +82,11 @@ public abstract class AbstractNonProvisionedControllerImpl extends AbstractEntit
         preStart();
     }
 
+    @Override
+    public void stop() {
+        preStop();
+    }
+    
     protected void preStart() {
         AttributeSensor<?> hostAndPortSensor = getConfig(HOST_AND_PORT_SENSOR);
         Maybe<Object> hostnameSensor = getConfigRaw(HOSTNAME_SENSOR, true);
@@ -90,18 +97,25 @@ public abstract class AbstractNonProvisionedControllerImpl extends AbstractEntit
         }
         
         ConfigToAttributes.apply(this);
-        LOG.info("Adding policy {} to {}, during start", serverPoolMemberTrackerPolicy, this);
-        addPolicy(serverPoolMemberTrackerPolicy);
-        resetServerPoolMemberTrackerPolicy();
+        addServerPoolMemberTrackerPolicy();
     }
     
-    protected synchronized void resetServerPoolMemberTrackerPolicy() {
-        serverPoolMemberTrackerPolicy.reset();
-        serverPoolAddresses.clear();
-        serverPoolTargets.clear();
-        if (groovyTruth(getServerPool())) {
-            serverPoolMemberTrackerPolicy.setGroup(getServerPool());
+    protected void preStop() {
+        removeServerPoolMemberTrackerPolicy();
+    }
+        
+    protected void addServerPoolMemberTrackerPolicy() {
+        Group serverPool = getServerPool();
+        if (serverPool != null) {
+            serverPoolMemberTrackerPolicy = addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                    .displayName("Controller targets tracker")
+                    .configure("group", serverPool));
             
+            LOG.info("Added policy {} to {}, during start", serverPoolMemberTrackerPolicy,
this);
+            
+            serverPoolAddresses.clear();
+            serverPoolTargets.clear();
+                
             // Initialize ourselves immediately with the latest set of members; don't wait
for
             // listener notifications because then will be out-of-date for short period (causing

             // problems for rebind)
@@ -116,10 +130,15 @@ public abstract class AbstractNonProvisionedControllerImpl extends AbstractEntit
                 }
             }
             
-            LOG.info("Resetting {}, members {} with address {}", new Object[] {this, serverPoolTargets,
serverPoolAddresses});
+            LOG.info("Resetting {}, members {} with addresses {}", new Object[] {this, serverPoolTargets,
serverPoolAddresses});
+            setAttribute(SERVER_POOL_TARGETS, serverPoolTargets);
+        }
+    }
+    
+    protected void removeServerPoolMemberTrackerPolicy() {
+        if (serverPoolMemberTrackerPolicy != null) {
+            removePolicy(serverPoolMemberTrackerPolicy);
         }
-        
-        setAttribute(SERVER_POOL_TARGETS, serverPoolTargets);
     }
     
     /** 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1b08d5a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerClusterImpl.java
b/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerClusterImpl.java
index 4d71caf..2c29756 100644
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerClusterImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancerClusterImpl.java
@@ -7,6 +7,7 @@ import brooklyn.entity.Entity;
 import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
 import brooklyn.entity.group.DynamicClusterImpl;
 import brooklyn.location.Location;
+import brooklyn.policy.PolicySpec;
 
 /**
  * A cluster of load balancers, where configuring the cluster (through the LoadBalancer interface)
@@ -37,11 +38,14 @@ public class LoadBalancerClusterImpl extends DynamicClusterImpl implements
LoadB
         // TODO Is there a race here, where (dispite super.stop() calling policy.suspend),
         // this could still be executing setAttribute(true) and hence incorrectly leave
         // the cluster in a service_up==true state after stop() returns?
-        AbstractMembershipTrackingPolicy policy = new AbstractMembershipTrackingPolicy()
{
-            @Override protected void onEntityEvent(EventType type, Entity entity) { setAttribute(SERVICE_UP,
calculateServiceUp()); }
-        };
-        addPolicy(policy);
-        policy.setGroup(this);
+        addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+                .configure("group", this));
+    }
+
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override protected void onEntityEvent(EventType type, Entity member) {
+            entity.setAttribute(SERVICE_UP, ((LoadBalancerClusterImpl)entity).calculateServiceUp());
+        }
     }
 
     /**


Mime
View raw message