diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/yoml/BrooklynDslInYomlStringPlanTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/yoml/BrooklynDslInYomlStringPlanTest.java index cb96ee7597e..281d363e95c 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/yoml/BrooklynDslInYomlStringPlanTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/yoml/BrooklynDslInYomlStringPlanTest.java @@ -22,9 +22,16 @@ import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind; import org.apache.brooklyn.api.typereg.RegisteredType; import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest; +import org.apache.brooklyn.camp.yoml.types.YomlInitializers; import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.entity.EntityAsserts; +import org.apache.brooklyn.core.entity.EntityInternal; import org.apache.brooklyn.core.sensor.Sensors; import org.apache.brooklyn.core.typereg.BasicBrooklynTypeRegistry; +import org.apache.brooklyn.test.Asserts; +import org.apache.brooklyn.util.guava.Maybe; +import org.apache.brooklyn.util.time.Duration; +import org.apache.brooklyn.util.time.Time; import org.apache.brooklyn.util.yoml.annotations.YomlAllFieldsTopLevel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +39,7 @@ import org.testng.annotations.Test; import com.google.api.client.repackaged.com.google.common.base.Joiner; +import com.google.common.base.Supplier; import com.google.common.collect.Iterables; public class BrooklynDslInYomlStringPlanTest extends AbstractYamlTest { @@ -73,14 +81,43 @@ public void testYomlParserRespectsDsl() throws Exception { "- type: org.apache.brooklyn.core.test.entity.TestEntity", " brooklyn.config:", " test.obj:", + // with this, the yoml is resolved at retrieval time " $brooklyn:object-yoml: item-w-dsl"); Entity app = createStartWaitAndLogApplication(yaml); Entity entity = Iterables.getOnlyElement( app.getChildren() ); entity.sensors().set(Sensors.newStringSensor("test.sensor"), "bob"); + Maybe raw = ((EntityInternal)entity).config().getRaw(ConfigKeys.newConfigKey(Object.class, "test.obj")); + Asserts.assertPresent(raw); + Asserts.assertInstanceOf(raw.get(), Supplier.class); Object obj = entity.config().get(ConfigKeys.newConfigKey(Object.class, "test.obj")); Assert.assertEquals(((ItemA)obj).name, "bob"); } + @Test + public void testYomlDefersDslEvaluationForConfig() throws Exception { + add(SAMPLE_TYPE_BASE); + add(SAMPLE_TYPE_TEST); + YomlInitializers.install(mgmt()); + + String yaml = Joiner.on("\n").join( + "services:", + "- type: org.apache.brooklyn.core.test.entity.TestEntity", + " brooklyn.initializers:", + " a-sensor:", + " type: static-sensor", + " value: '$brooklyn:self().attributeWhenReady(\"test.sensor\")'", + " period: 100ms"); + + Entity app = createStartWaitAndLogApplication(yaml); + Entity entity = Iterables.getOnlyElement( app.getChildren() ); + + entity.sensors().set(Sensors.newStringSensor("test.sensor"), "bob"); +// EntityAsserts.assertAttributeEqualsEventually(entity, attribute, expected); + System.out.println(entity.getAttribute(Sensors.newStringSensor("a-sensor"))); + Time.sleep(Duration.ONE_SECOND); + System.out.println(entity.getAttribute(Sensors.newStringSensor("a-sensor"))); + } + } diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/yoml/serializers/ConfigInMapUnderConfigSerializer.java b/utils/common/src/main/java/org/apache/brooklyn/util/yoml/serializers/ConfigInMapUnderConfigSerializer.java index aba4898211c..e10a3f9d7d9 100644 --- a/utils/common/src/main/java/org/apache/brooklyn/util/yoml/serializers/ConfigInMapUnderConfigSerializer.java +++ b/utils/common/src/main/java/org/apache/brooklyn/util/yoml/serializers/ConfigInMapUnderConfigSerializer.java @@ -78,7 +78,8 @@ protected boolean setKeyValueForJavaObjectOnRead(String key, Object value, Strin Object v2; try { - v2 = converter.read( ((YomlContextForRead)context).subpath("/"+key, value, optionalType) ); + if (isDeferredValue(value)) v2 = value; + else v2 = converter.read( ((YomlContextForRead)context).subpath("/"+key, value, optionalType) ); } catch (Exception e) { // for config we try with the optional type, but don't insist Exceptions.propagateIfFatal(e); diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/yoml/serializers/FieldsInMapUnderFields.java b/utils/common/src/main/java/org/apache/brooklyn/util/yoml/serializers/FieldsInMapUnderFields.java index e76f582659f..9a5ce805bc9 100644 --- a/utils/common/src/main/java/org/apache/brooklyn/util/yoml/serializers/FieldsInMapUnderFields.java +++ b/utils/common/src/main/java/org/apache/brooklyn/util/yoml/serializers/FieldsInMapUnderFields.java @@ -72,6 +72,16 @@ protected boolean setKeyValueForJavaObjectOnRead(String key, Object value, Strin String fieldType = getFieldTypeName(ff, optionalTypeConstraint); Object v2 = converter.read( ((YomlContextForRead)context).subpath("/"+key, value, fieldType) ); + if (isDeferredValue(v2)) { + Maybe coerced = config.getCoercer().tryCoerce(v2, ff.getType()); + if (coerced.isAbsent()) { + // couldn't coerce or resolve, and this is needed for fields of course + throw new YomlException("Cannot interpret or coerce '"+v2+"' as "+fieldType+" for field "+ff.getName(), + Maybe.getException(coerced)); + } + v2 = coerced.get(); + } + ff.setAccessible(true); ff.set(getJavaObject(), v2); return true;