Merge pull request #1419 from aledsage/fix/policy-persistence-20140527
Fixes in policy persistence (against branch feature/policy-persistence)
diff --git a/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java b/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
index 4346be5..c80c9a7 100644
--- a/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
+++ b/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
@@ -27,7 +27,7 @@
super(flags);
enricherType = new EnricherTypeImpl(getAdjunctType());
- if (isLegacyConstruction()) {
+ if (isLegacyConstruction() && !isLegacyNoConstructionInit()) {
init();
}
}
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
index 6ab1e58..4a5747c 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
@@ -32,12 +32,16 @@
enricher.setName(memento.getDisplayName());
- // FIXME Will this set config keys that are not marked with `@SetFromFlag`?
- // Note that the flags may have been set in the constructor; but some have no-arg constructors
+ // TODO entity does config-lookup differently; the memento contains the config keys.
+ // BasicEntityMemento.postDeserialize uses the injectTypeClass to call EntityTypes.getDefinedConfigKeys(clazz)
+ //
+ // Note that the flags may have been set in the constructor; but some enrichers have no-arg constructors
ConfigBag configBag = ConfigBag.newInstance(memento.getConfig());
FlagUtils.setFieldsFromFlags(enricher, configBag);
+ FlagUtils.setAllConfigKeys(enricher, configBag, false);
doReconsruct(rebindContext, memento);
+ ((AbstractEnricher)enricher).rebind();
}
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
index 5f32f7f..39202cb 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
@@ -31,13 +31,17 @@
if (LOG.isTraceEnabled()) LOG.trace("Reconstructing policy: {}", memento.toVerboseString());
policy.setName(memento.getDisplayName());
-
- // FIXME Will this set config keys that are not marked with `@SetFromFlag`?
- // Note that the flags may have been set in the constructor; but some have no-arg constructors
+
+ // TODO entity does config-lookup differently; the memento contains the config keys.
+ // BasicEntityMemento.postDeserialize uses the injectTypeClass to call EntityTypes.getDefinedConfigKeys(clazz)
+ //
+ // Note that the flags may have been set in the constructor; but some policies have no-arg constructors
ConfigBag configBag = ConfigBag.newInstance(memento.getConfig());
FlagUtils.setFieldsFromFlags(policy, configBag);
+ FlagUtils.setAllConfigKeys(policy, configBag, false);
doReconsruct(rebindContext, memento);
+ ((AbstractPolicy)policy).rebind();
}
/**
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 1317bb2..f9e28f4 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -496,7 +496,10 @@
// There are several possibilities for the constructor; find one that works.
// Prefer passing in the flags because required for Application to set the management context
// TODO Feels very hacky!
- Map<String, Object> flags = MutableMap.<String, Object>of("id", id, "deferConstructionChecks", true);
+ Map<String, Object> flags = MutableMap.<String, Object>of(
+ "id", id,
+ "deferConstructionChecks", true,
+ "noConstructionInit", true);
flags.putAll(memento.getConfig());
return (Policy) invokeConstructor(reflections, policyClazz, new Object[] {flags});
@@ -525,7 +528,10 @@
// There are several possibilities for the constructor; find one that works.
// Prefer passing in the flags because required for Application to set the management context
// TODO Feels very hacky!
- Map<String, Object> flags = MutableMap.<String, Object>of("id", id, "deferConstructionChecks", true);
+ Map<String, Object> flags = MutableMap.<String, Object>of(
+ "id", id,
+ "deferConstructionChecks", true,
+ "noConstructionInit", true);
flags.putAll(memento.getConfig());
return (Enricher) invokeConstructor(reflections, enricherClazz, new Object[] {flags});
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BasicPolicyMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/BasicPolicyMemento.java
index 2b71ad3..795ea2e 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BasicPolicyMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BasicPolicyMemento.java
@@ -43,6 +43,7 @@
// Trusts the builder to not mess around with mutability after calling build()
protected BasicPolicyMemento(Builder builder) {
+ super(builder);
config = toPersistedMap(builder.config);
}
diff --git a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
index fd0dd02..8d3bc01 100644
--- a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
+++ b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
@@ -52,6 +52,7 @@
protected Map<String,Object> leftoverProperties = Maps.newLinkedHashMap();
private boolean _legacyConstruction;
+ private boolean _legacyNoConstructionInit;
// TODO not sure if we need this -- never read
@SuppressWarnings("unused")
@@ -87,6 +88,8 @@
public AbstractEntityAdjunct(@SuppressWarnings("rawtypes") Map flags) {
inConstruction = true;
_legacyConstruction = !InternalPolicyFactory.FactoryConstructionTracker.isConstructing();
+ _legacyNoConstructionInit = (flags != null) && Boolean.TRUE.equals(flags.get("noConstructionInit"));
+
if (!_legacyConstruction && flags!=null && !flags.isEmpty()) {
log.debug("Using direct construction for "+getClass().getName()+" because properties were specified ("+flags+")");
_legacyConstruction = true;
@@ -158,6 +161,15 @@
protected boolean isLegacyConstruction() {
return _legacyConstruction;
}
+
+ /**
+ * Used for legacy-style policies/enrichers on rebind, to indicate that init() should not be called.
+ * Will likely be deleted in a future release; should not be called apart from by framework code.
+ */
+ @Beta
+ protected boolean isLegacyNoConstructionInit() {
+ return _legacyNoConstructionInit;
+ }
public void setManagementContext(ManagementContext managementContext) {
this.managementContext = managementContext;
@@ -168,7 +180,7 @@
}
/**
- * Called by framework (in new-style policies where PolicySpec was used) after configuring, setting parent, etc,
+ * Called by framework (in new-style policies where PolicySpec was used) after configuring etc,
* but before a reference to this policy is shared.
*
* To preserve backwards compatibility for if the policy is constructed directly, one
@@ -186,6 +198,15 @@
// no-op
}
+ /**
+ * Called by framework (in new-style policies/enrichers where PolicySpec/EnricherSpec was used) on rebind,
+ * after configuring but before {@link #setEntity(EntityLocal)} and before a reference to this policy is shared.
+ * Note that {@link #init()} will not be called on rebind.
+ */
+ public void rebind() {
+ // no-op
+ }
+
public <T> T getConfig(ConfigKey<T> key) {
return configsInternal.getConfig(key);
}
diff --git a/core/src/main/java/brooklyn/policy/basic/AbstractPolicy.java b/core/src/main/java/brooklyn/policy/basic/AbstractPolicy.java
index 6be9544..c6b932c 100644
--- a/core/src/main/java/brooklyn/policy/basic/AbstractPolicy.java
+++ b/core/src/main/java/brooklyn/policy/basic/AbstractPolicy.java
@@ -40,7 +40,7 @@
super(flags);
policyType = new PolicyTypeImpl(getAdjunctType());
- if (isLegacyConstruction()) {
+ if (isLegacyConstruction() && !isLegacyNoConstructionInit()) {
init();
}
}
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindEnricherTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindEnricherTest.java
new file mode 100644
index 0000000..f48a114
--- /dev/null
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindEnricherTest.java
@@ -0,0 +1,186 @@
+package brooklyn.entity.rebind;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.enricher.Enrichers;
+import brooklyn.enricher.basic.AbstractEnricher;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.group.DynamicCluster;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.Sensors;
+import brooklyn.policy.EnricherSpec;
+import brooklyn.test.EntityTestUtils;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.util.flags.SetFromFlag;
+import brooklyn.util.text.StringFunctions;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+public class RebindEnricherTest extends RebindTestFixtureWithApp {
+
+ public static AttributeSensor<String> METRIC1 = Sensors.newStringSensor("RebindEnricherTest.metric1");
+ public static AttributeSensor<String> METRIC2 = Sensors.newStringSensor("RebindEnricherTest.metric2");
+
+ private DynamicCluster origCluster;
+ private TestEntity origEntity;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ origCluster = origApp.createAndManageChild(EntitySpec.create(DynamicCluster.class).configure("memberSpec", EntitySpec.create(TestEntity.class)));
+ origEntity = origApp.createAndManageChild(EntitySpec.create(TestEntity.class));
+ }
+
+ @Test
+ public void testPropagatingEnricher() throws Exception {
+ origApp.addEnricher(Enrichers.builder()
+ .propagating(METRIC1)
+ .from(origEntity)
+ .build());
+
+ TestApplication newApp = rebind();
+ TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class));
+
+ newEntity.setAttribute(METRIC1, "myval");
+ EntityTestUtils.assertAttributeEqualsEventually(newApp, METRIC1, "myval");
+ }
+
+ @Test
+ public void testPropagatingAllEnricher() throws Exception {
+ origApp.addEnricher(Enrichers.builder()
+ .propagatingAll()
+ .from(origEntity)
+ .build());
+
+ TestApplication newApp = rebind();
+ TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class));
+
+ newEntity.setAttribute(METRIC1, "myval");
+ EntityTestUtils.assertAttributeEqualsEventually(newApp, METRIC1, "myval");
+ }
+
+ @Test
+ public void testPropagatingAsEnricher() throws Exception {
+ origApp.addEnricher(Enrichers.builder()
+ .propagating(ImmutableMap.of(METRIC1, METRIC2))
+ .from(origEntity)
+ .build());
+
+ TestApplication newApp = rebind();
+ TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class));
+
+ newEntity.setAttribute(METRIC1, "myval");
+ EntityTestUtils.assertAttributeEqualsEventually(newApp, METRIC2, "myval");
+ }
+
+ @Test
+ public void testCombiningEnricher() throws Exception {
+ origApp.addEnricher(Enrichers.builder()
+ .combining(METRIC1, METRIC2)
+ .from(origEntity)
+ .computing(StringFunctions.joiner(","))
+ .publishing(METRIC2)
+ .build());
+
+ TestApplication newApp = rebind();
+ TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class));
+
+ newEntity.setAttribute(METRIC1, "myval");
+ newEntity.setAttribute(METRIC2, "myval2");
+ EntityTestUtils.assertAttributeEventually(newApp, METRIC2, Predicates.or(Predicates.equalTo("myval,myval2"), Predicates.equalTo("myval2,myval")));
+ }
+
+ @Test
+ public void testAggregatingMembersEnricher() throws Exception {
+ origCluster.resize(2);
+
+ origApp.addEnricher(Enrichers.builder()
+ .aggregating(METRIC1)
+ .from(origCluster)
+ .fromMembers()
+ .computing(StringFunctions.joiner(","))
+ .publishing(METRIC2)
+ .build());
+
+ TestApplication newApp = rebind();
+ DynamicCluster newCluster = (DynamicCluster) Iterables.find(newApp.getChildren(), Predicates.instanceOf(DynamicCluster.class));
+
+ int i = 0;
+ for (Entity member : newCluster.getMembers()) {
+ ((EntityInternal)member).setAttribute(METRIC1, "myval"+(i++));
+ }
+ EntityTestUtils.assertAttributeEventually(newApp, METRIC2, Predicates.or(Predicates.equalTo("myval1,myval2"), Predicates.equalTo("myval2,myval1")));
+ }
+
+ @Test
+ public void testRestoresConfig() throws Exception {
+ origApp.addEnricher(EnricherSpec.create(MyEnricher.class)
+ .configure(MyEnricher.MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME, "myVal for with setFromFlag noShortName")
+ .configure(MyEnricher.MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME, "myVal for setFromFlag withShortName")
+ .configure(MyEnricher.MY_CONFIG_WITHOUT_SETFROMFLAG, "myVal for witout setFromFlag"));
+
+ newApp = (TestApplication) rebind();
+ MyEnricher newEnricher = (MyEnricher) Iterables.getOnlyElement(newApp.getEnrichers());
+
+ assertEquals(newEnricher.getConfig(MyEnricher.MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME), "myVal for with setFromFlag noShortName");
+ assertEquals(newEnricher.getConfig(MyEnricher.MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME), "myVal for setFromFlag withShortName");
+ assertEquals(newEnricher.getConfig(MyEnricher.MY_CONFIG_WITHOUT_SETFROMFLAG), "myVal for witout setFromFlag");
+ }
+
+ public static class MyEnricher extends AbstractEnricher {
+ public static final ConfigKey<String> MY_CONFIG = ConfigKeys.newStringConfigKey("myconfigkey");
+
+ @SetFromFlag
+ public static final ConfigKey<String> MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME = ConfigKeys.newStringConfigKey("myconfig.withSetfromflag.noShortName");
+
+ @SetFromFlag("myConfigWithSetFromFlagWithShortName")
+ public static final ConfigKey<String> MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME = ConfigKeys.newStringConfigKey("myconfig.withSetfromflag.withShortName");
+
+ public static final ConfigKey<String> MY_CONFIG_WITHOUT_SETFROMFLAG = ConfigKeys.newStringConfigKey("myconfig.withoutSetfromflag");
+
+ @SetFromFlag
+ String myfield;
+
+ @SuppressWarnings("unused")
+ private final Object dummy = new Object(); // so not serializable
+
+ public volatile boolean initCalled;
+ public volatile boolean rebindCalled;
+
+ public MyEnricher() {
+ }
+
+ public MyEnricher(Map<?,?> flags) {
+ super(flags);
+ }
+
+ @Override
+ public void init() {
+ super.init();
+ initCalled = true;
+ }
+
+ // TODO When AbstractEnricher declares rebind; @Override
+ public void rebind() {
+ // TODO super.rebind();
+ rebindCalled = true;
+ }
+ }
+
+ public static class MyEnricherWithoutNoArgConstructor extends MyEnricher {
+ public MyEnricherWithoutNoArgConstructor(Map<?,?> flags) {
+ super(flags);
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
index 6de41c7..e731b33 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
@@ -108,28 +108,20 @@
assertEquals(newLoc.myAtomicLong.get(), 124L);
}
- @SetFromFlag
- public static final ConfigKey<String> MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME = ConfigKeys.newStringConfigKey("myconfig.withSetfromflag.noShortName");
-
- @SetFromFlag("myConfigWithSetFromFlagWithShortName")
- public static final ConfigKey<String> MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME = ConfigKeys.newStringConfigKey("myconfig.withSetfromflag.withShortName");
-
- public static final ConfigKey<String> MY_CONFIG_WITHOUT_SETFROMFLAG = ConfigKeys.newStringConfigKey("myconfig.withoutSetfromflag");
-
@Test
public void testRestoresConfig() throws Exception {
MyLocation origLoc = origManagementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class)
- .configure(MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME, "myVal for with setFromFlag noShortName")
- .configure(MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME, "myVal for setFromFlag withShortName")
- .configure(MY_CONFIG_WITHOUT_SETFROMFLAG, "myVal for witout setFromFlag"));
+ .configure(MyLocation.MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME, "myVal for with setFromFlag noShortName")
+ .configure(MyLocation.MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME, "myVal for setFromFlag withShortName")
+ .configure(MyLocation.MY_CONFIG_WITHOUT_SETFROMFLAG, "myVal for witout setFromFlag"));
origApp.start(ImmutableList.of(origLoc));
newApp = (TestApplication) rebind();
MyLocation newLoc = (MyLocation) Iterables.get(newApp.getLocations(), 0);
- assertEquals(newLoc.getConfig(MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME), "myVal for with setFromFlag noShortName");
- assertEquals(newLoc.getConfig(MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME), "myVal for setFromFlag withShortName");
- assertEquals(newLoc.getConfig(MY_CONFIG_WITHOUT_SETFROMFLAG), "myVal for witout setFromFlag");
+ assertEquals(newLoc.getConfig(MyLocation.MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME), "myVal for with setFromFlag noShortName");
+ assertEquals(newLoc.getConfig(MyLocation.MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME), "myVal for setFromFlag withShortName");
+ assertEquals(newLoc.getConfig(MyLocation.MY_CONFIG_WITHOUT_SETFROMFLAG), "myVal for witout setFromFlag");
}
@Test
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
index bf6e943..bacb4df 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
@@ -1,13 +1,16 @@
package brooklyn.entity.rebind;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
-import java.util.Collection;
import java.util.Map;
import org.testng.annotations.Test;
-import brooklyn.policy.Policy;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.policy.PolicySpec;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.test.entity.TestApplication;
import brooklyn.util.collections.MutableMap;
@@ -26,30 +29,103 @@
* See RebindManagerImpl.CheckpointingChangeListener.onChanged(Entity) and
* MementosGenerator.newEntityMementoBuilder()
*/
- @Test(enabled=false)
- public void testRestoresSimplePolicy() throws Exception {
- MyPolicy origPolicy = new MyPolicy(MutableMap.of("myfield", "myval"));
+
+ @Test
+ public void testRestoresSimplePolicyFromConstructor() throws Exception {
+ MyPolicy origPolicy = new MyPolicy(MutableMap.of("myfield", "myFieldVal", "myconfigkey", "myConfigVal"));
origApp.addPolicy(origPolicy);
+ runRestoresSimplePolicy();
+ }
+
+ @Test
+ public void testRestoresDeprecatedPolicyFromConstructorWithoutNoArgs() throws Exception {
+ MyPolicyWithoutNoArgConstructor origPolicy = new MyPolicyWithoutNoArgConstructor(MutableMap.of("myfield", "myFieldVal", "myconfigkey", "myConfigVal"));
+ origApp.addPolicy(origPolicy);
+ runRestoresSimplePolicy();
+ }
+
+ @Test
+ public void testRestoresSimplePolicyFromPolicySpec() throws Exception {
+ origApp.addPolicy(PolicySpec.create(MyPolicy.class)
+ .configure("myfield", "myFieldVal")
+ .configure(MyPolicy.MY_CONFIG, "myConfigVal"));
+ runRestoresSimplePolicy();
+ }
+
+ protected void runRestoresSimplePolicy() throws Exception {
+ MyPolicy origPolicy = (MyPolicy) Iterables.getOnlyElement(origApp.getPolicies());
+ assertTrue(origPolicy.isRunning());
+ assertTrue(origPolicy.initCalled);
+ assertFalse(origPolicy.rebindCalled);
TestApplication newApp = rebind();
- Collection<Policy> policies = newApp.getPolicies();
- MyPolicy newPolicy = (MyPolicy) Iterables.get(policies, 0);
+ MyPolicy newPolicy = (MyPolicy) Iterables.getOnlyElement(newApp.getPolicies());
- assertEquals(newPolicy.myfield, origPolicy.myfield);
+ assertEquals(newPolicy.myfield, "myFieldVal");
+ assertEquals(newPolicy.getConfig(MyPolicy.MY_CONFIG), "myConfigVal");
+ assertTrue(newPolicy.isRunning());
+ assertFalse(newPolicy.initCalled);
+ assertTrue(newPolicy.rebindCalled);
+ }
+
+ @Test
+ public void testRestoresConfig() throws Exception {
+ origApp.addPolicy(PolicySpec.create(MyPolicy.class)
+ .configure(MyPolicy.MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME, "myVal for with setFromFlag noShortName")
+ .configure(MyPolicy.MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME, "myVal for setFromFlag withShortName")
+ .configure(MyPolicy.MY_CONFIG_WITHOUT_SETFROMFLAG, "myVal for witout setFromFlag"));
+
+ newApp = (TestApplication) rebind();
+ MyPolicy newPolicy = (MyPolicy) Iterables.getOnlyElement(newApp.getPolicies());
+
+ assertEquals(newPolicy.getConfig(MyPolicy.MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME), "myVal for with setFromFlag noShortName");
+ assertEquals(newPolicy.getConfig(MyPolicy.MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME), "myVal for setFromFlag withShortName");
+ assertEquals(newPolicy.getConfig(MyPolicy.MY_CONFIG_WITHOUT_SETFROMFLAG), "myVal for witout setFromFlag");
}
public static class MyPolicy extends AbstractPolicy {
+ public static final ConfigKey<String> MY_CONFIG = ConfigKeys.newStringConfigKey("myconfigkey");
+
+ @SetFromFlag
+ public static final ConfigKey<String> MY_CONFIG_WITH_SETFROMFLAG_NO_SHORT_NAME = ConfigKeys.newStringConfigKey("myconfig.withSetfromflag.noShortName");
+
+ @SetFromFlag("myConfigWithSetFromFlagWithShortName")
+ public static final ConfigKey<String> MY_CONFIG_WITH_SETFROMFLAG_WITH_SHORT_NAME = ConfigKeys.newStringConfigKey("myconfig.withSetfromflag.withShortName");
+
+ public static final ConfigKey<String> MY_CONFIG_WITHOUT_SETFROMFLAG = ConfigKeys.newStringConfigKey("myconfig.withoutSetfromflag");
+
@SetFromFlag
String myfield;
@SuppressWarnings("unused")
private final Object dummy = new Object(); // so not serializable
+ public transient volatile boolean initCalled;
+ public transient volatile boolean rebindCalled;
+
public MyPolicy() {
}
public MyPolicy(Map<?,?> flags) {
super(flags);
}
+
+ @Override
+ public void init() {
+ super.init();
+ initCalled = true;
+ }
+
+ // TODO When AbstractPolicy declares rebind; @Override
+ public void rebind() {
+ // TODO super.rebind();
+ rebindCalled = true;
+ }
}
-}
+
+ public static class MyPolicyWithoutNoArgConstructor extends MyPolicy {
+ public MyPolicyWithoutNoArgConstructor(Map<?,?> flags) {
+ super(flags);
+ }
+ }
+}
\ No newline at end of file