http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EnrichersYamlTest.java
----------------------------------------------------------------------
diff --git 
a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EnrichersYamlTest.java
 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EnrichersYamlTest.java
new file mode 100644
index 0000000..16bd3e5
--- /dev/null
+++ 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EnrichersYamlTest.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.enricher.basic.Propagator;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityAdjuncts;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.policy.Enricher;
+import brooklyn.test.Asserts;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.test.policy.TestEnricher;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+@Test
+public class EnrichersYamlTest extends AbstractYamlTest {
+    private static final Logger log = 
LoggerFactory.getLogger(EnrichersYamlTest.class);
+
+    @Test
+    public void testWithAppEnricher() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-app-with-enricher.yaml"));
+        waitForApplicationTasks(app);
+        Assert.assertEquals(app.getDisplayName(), "test-app-with-enricher");
+        
+        log.info("App started:");
+        Entities.dumpInfo(app);
+        
+        Assert.assertEquals(EntityAdjuncts.getNonSystemEnrichers(app).size(), 
1);
+        final Enricher enricher = 
EntityAdjuncts.getNonSystemEnrichers(app).iterator().next();
+        Assert.assertTrue(enricher instanceof TestEnricher, 
"enricher="+enricher);
+        Assert.assertEquals(enricher.getConfig(TestEnricher.CONF_NAME), "Name 
from YAML");
+        
Assert.assertEquals(enricher.getConfig(TestEnricher.CONF_FROM_FUNCTION), 
"$brooklyn: is a fun place");
+        
+        Entity target = 
((EntityInternal)app).getExecutionContext().submit(MutableMap.of(), new 
Callable<Entity>() {
+            public Entity call() {
+                return enricher.getConfig(TestEnricher.TARGET_ENTITY);
+            }}).get();
+        Assert.assertNotNull(target);
+        Assert.assertEquals(target.getDisplayName(), "testentity");
+        Assert.assertEquals(target, app.getChildren().iterator().next());
+        Entity targetFromFlag = 
((EntityInternal)app).getExecutionContext().submit(MutableMap.of(), new 
Callable<Entity>() {
+            public Entity call() {
+                return 
enricher.getConfig(TestEnricher.TARGET_ENTITY_FROM_FLAG);
+            }}).get();
+        Assert.assertEquals(targetFromFlag, target);
+        Map<?, ?> leftoverProperties = ((TestEnricher) 
enricher).getLeftoverProperties();
+        Assert.assertEquals(leftoverProperties.get("enricherLiteralValue1"), 
"Hello");
+        Assert.assertEquals(leftoverProperties.get("enricherLiteralValue2"), 
"World");
+        Assert.assertEquals(leftoverProperties.size(), 2);
+    }
+    
+    @Test
+    public void testWithEntityEnricher() throws Exception {
+        final Entity app = 
createAndStartApplication(loadYaml("test-entity-with-enricher.yaml"));
+        waitForApplicationTasks(app);
+        Assert.assertEquals(app.getDisplayName(), "test-entity-with-enricher");
+
+        log.info("App started:");
+        Entities.dumpInfo(app);
+
+        Assert.assertEquals(EntityAdjuncts.getNonSystemEnrichers(app).size(), 
0);
+        Assert.assertEquals(app.getChildren().size(), 1);
+        final Entity child = app.getChildren().iterator().next();
+        Asserts.eventually(new Supplier<Integer>() {
+            @Override
+            public Integer get() {
+                return EntityAdjuncts.getNonSystemEnrichers(child).size();
+            }
+        }, Predicates.<Integer> equalTo(1));        
+        final Enricher enricher = 
EntityAdjuncts.getNonSystemEnrichers(child).iterator().next();
+        Assert.assertNotNull(enricher);
+        Assert.assertTrue(enricher instanceof TestEnricher, "enricher=" + 
enricher + "; type=" + enricher.getClass());
+        Assert.assertEquals(enricher.getConfig(TestEnricher.CONF_NAME), "Name 
from YAML");
+        
Assert.assertEquals(enricher.getConfig(TestEnricher.CONF_FROM_FUNCTION), 
"$brooklyn: is a fun place");
+        
+        Assert.assertEquals(((TestEnricher) enricher).getLeftoverProperties(),
+                ImmutableMap.of("enricherLiteralValue1", "Hello", 
"enricherLiteralValue2", "World"));
+    }
+    
+    @Test
+    public void testPropagatingEnricher() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-propagating-enricher.yaml"));
+        waitForApplicationTasks(app);
+        Assert.assertEquals(app.getDisplayName(), "test-propagating-enricher");
+
+        log.info("App started:");
+        Entities.dumpInfo(app);
+        TestEntity entity = (TestEntity)app.getChildren().iterator().next();
+        entity.setAttribute(TestEntity.NAME, "New Name");
+        Asserts.eventually(Entities.attributeSupplier(app, TestEntity.NAME), 
Predicates.<String>equalTo("New Name"));
+    }
+    
+    @Test
+    public void testPropogateChildSensor() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml",
+                    "  brooklyn.config:",
+                    "    test.confName: parent entity",
+                    "  id: parentId",
+                    "  brooklyn.enrichers:",
+                    "  - enricherType: brooklyn.enricher.basic.Propagator",
+                    "    brooklyn.config:",
+                    "      enricher.producer: 
$brooklyn:component(\"childId\")",
+                    "      enricher.propagating.propagatingAll: true",
+                    "  brooklyn.children:",
+                    "  - serviceType: brooklyn.test.entity.TestEntity",
+                    "    id: childId",
+                    "    brooklyn.config:",
+                    "      test.confName: Child Name"));
+        waitForApplicationTasks(app);
+        
+        log.info("App started:");
+        Entities.dumpInfo(app);
+        Assert.assertEquals(app.getChildren().size(), 1);
+        final Entity parentEntity = app.getChildren().iterator().next();
+        Assert.assertTrue(parentEntity instanceof TestEntity, "Expected parent 
entity to be TestEntity, found:" + parentEntity);
+        Assert.assertEquals(parentEntity.getChildren().size(), 1);
+        Entity childEntity = parentEntity.getChildren().iterator().next();
+        Assert.assertTrue(childEntity instanceof TestEntity, "Expected child 
entity to be TestEntity, found:" + childEntity);
+        Asserts.eventually(new Supplier<Integer>() {
+            @Override
+            public Integer get() {
+                return 
EntityAdjuncts.getNonSystemEnrichers(parentEntity).size();
+            }
+        }, Predicates.<Integer>equalTo(1));
+        Enricher enricher = 
EntityAdjuncts.getNonSystemEnrichers(parentEntity).iterator().next();
+        Asserts.assertTrue(enricher instanceof Propagator, "Expected enricher 
to be Propagator, found:" + enricher);
+        final Propagator propagator = (Propagator)enricher;
+        Entity producer = 
((EntityInternal)parentEntity).getExecutionContext().submit(MutableMap.of(), 
new Callable<Entity>() {
+            public Entity call() {
+                return propagator.getConfig(Propagator.PRODUCER);
+            }}).get();
+        Assert.assertEquals(producer, childEntity);
+        
Asserts.assertTrue(Boolean.valueOf(propagator.getConfig(Propagator.PROPAGATING_ALL)),
 "Expected Propagator.PROPAGATING_ALL to be true");
+        ((TestEntity)childEntity).setAttribute(TestEntity.NAME, "New Name");
+        Asserts.eventually(Entities.attributeSupplier(parentEntity, 
TestEntity.NAME), Predicates.<String>equalTo("New Name"));
+    }
+    
+    @Test
+    public void testMultipleEnricherReferences() throws Exception {
+        final Entity app = 
createAndStartApplication(loadYaml("test-referencing-enrichers.yaml"));
+        waitForApplicationTasks(app);
+        
+        Entity entity1 = null, entity2 = null, child1 = null, child2 = null, 
grandchild1 = null, grandchild2 = null;
+        
+        Assert.assertEquals(app.getChildren().size(), 2);
+        for (Entity child : app.getChildren()) {
+            if (child.getDisplayName().equals("entity 1"))
+                entity1 = child;
+            if (child.getDisplayName().equals("entity 2"))
+                entity2 = child;
+        }
+        Assert.assertNotNull(entity1);
+        Assert.assertNotNull(entity2);
+        
+        Assert.assertEquals(entity1.getChildren().size(), 2);
+        for (Entity child : entity1.getChildren()) {
+            if (child.getDisplayName().equals("child 1"))
+                child1 = child;
+            if (child.getDisplayName().equals("child 2"))
+                child2 = child;
+        }
+        Assert.assertNotNull(child1);
+        Assert.assertNotNull(child2);
+        
+        Assert.assertEquals(child1.getChildren().size(), 2);
+        for (Entity child : child1.getChildren()) {
+            if (child.getDisplayName().equals("grandchild 1"))
+               grandchild1 = child;
+            if (child.getDisplayName().equals("grandchild 2"))
+                grandchild2 = child;
+        }
+        Assert.assertNotNull(grandchild1);
+        Assert.assertNotNull(grandchild2);
+        
+        ImmutableSet<Enricher> enrichers = new ImmutableSet.Builder<Enricher>()
+                .add(getEnricher(app))
+                .add(getEnricher(entity1))
+                .add(getEnricher(entity2))
+                .add(getEnricher(child1))
+                .add(getEnricher(child2))
+                .add(getEnricher(grandchild1))
+                .add(getEnricher(grandchild2))
+                .build();
+        
+        Map<ConfigKey<Entity>, Entity> keyToEntity = new 
ImmutableMap.Builder<ConfigKey<Entity>, Entity>()
+                .put(TestReferencingEnricher.TEST_APPLICATION, app)
+                .put(TestReferencingEnricher.TEST_ENTITY_1, entity1)
+                .put(TestReferencingEnricher.TEST_ENTITY_2, entity2)
+                .put(TestReferencingEnricher.TEST_CHILD_1, child1)
+                .put(TestReferencingEnricher.TEST_CHILD_2, child2)
+                .put(TestReferencingEnricher.TEST_GRANDCHILD_1, grandchild1)
+                .put(TestReferencingEnricher.TEST_GRANDCHILD_2, grandchild2)
+                .build();
+        
+        for (Enricher enricher : enrichers)
+            checkReferences(enricher, keyToEntity);
+    }
+    
+    private void checkReferences(final Enricher enricher, 
Map<ConfigKey<Entity>, Entity> keyToEntity) throws Exception {
+        for (final ConfigKey<Entity> key : keyToEntity.keySet()) {
+            final Entity entity = keyToEntity.get(key); // Grab an entity 
whose execution context we can use
+            Entity fromConfig = 
((EntityInternal)entity).getExecutionContext().submit(MutableMap.of(), new 
Callable<Entity>() {
+                @Override
+                public Entity call() throws Exception {
+                    return (Entity) enricher.getConfig(key);
+                }
+            }).get();
+            Assert.assertEquals(fromConfig, keyToEntity.get(key));
+        }
+    }
+    
+    private Enricher getEnricher(Entity entity) {
+        List<Enricher> enrichers = 
EntityAdjuncts.getNonSystemEnrichers(entity);
+        Assert.assertEquals(enrichers.size(), 1, "Wrong number of enrichers: 
"+enrichers);
+        Enricher enricher = enrichers.iterator().next();
+        Assert.assertTrue(enricher instanceof TestReferencingEnricher, "Wrong 
enricher: "+enricher);
+        return enricher;
+    }
+    
+    @Override
+    protected Logger getLogger() {
+        return log;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlIntegrationTest.java
 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlIntegrationTest.java
new file mode 100644
index 0000000..4933e5d
--- /dev/null
+++ 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlIntegrationTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn;
+
+import static org.testng.Assert.*;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Iterables;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.group.DynamicCluster;
+import brooklyn.entity.proxy.nginx.NginxController;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.webapp.ControlledDynamicWebAppCluster;
+import brooklyn.entity.webapp.tomcat.TomcatServer;
+
+public class EntitiesYamlIntegrationTest extends AbstractYamlTest {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(EntitiesYamlIntegrationTest.class);
+
+    @Test(groups = "Integration")
+    public void testStartTomcatCluster() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-tomcat-cluster.yaml"));
+        waitForApplicationTasks(app);
+
+        assertNotNull(app);
+        assertEquals(app.getChildren().size(), 1);
+        final Entity entity = Iterables.getOnlyElement(app.getChildren());
+        assertTrue(entity instanceof ControlledDynamicWebAppCluster, 
"entity="+entity);
+        ControlledDynamicWebAppCluster cluster = 
(ControlledDynamicWebAppCluster) entity;
+
+        assertTrue(cluster.getController() instanceof NginxController, 
"controller="+cluster.getController());
+        Iterable<TomcatServer> tomcats = 
FluentIterable.from(cluster.getCluster().getMembers()).filter(TomcatServer.class);
+        assertEquals(Iterables.size(tomcats), 2);
+        for (TomcatServer tomcat : tomcats) {
+            assertTrue(tomcat.getAttribute(TomcatServer.SERVICE_UP), 
"serviceup");
+        }
+
+        EntitySpec<?> spec = entity.getConfig(DynamicCluster.MEMBER_SPEC);
+        assertNotNull(spec);
+        assertEquals(spec.getType(), TomcatServer.class);
+        
assertEquals(spec.getConfig().get(DynamicCluster.QUARANTINE_FAILED_ENTITIES), 
Boolean.FALSE);
+        assertEquals(spec.getConfig().get(DynamicCluster.INITIAL_QUORUM_SIZE), 
2);
+    }
+
+
+    @Override
+    protected Logger getLogger() {
+        return LOG;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
----------------------------------------------------------------------
diff --git 
a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
new file mode 100644
index 0000000..e873ffa
--- /dev/null
+++ 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
@@ -0,0 +1,919 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.io.StringReader;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.collections.Lists;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Application;
+import brooklyn.entity.Effector;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.BasicApplication;
+import brooklyn.entity.basic.BasicEntity;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityFunctions;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.basic.EntityPredicates;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.SameServerEntity;
+import brooklyn.entity.effector.Effectors;
+import brooklyn.entity.group.DynamicCluster;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.Sensors;
+import brooklyn.location.Location;
+import brooklyn.management.Task;
+import brooklyn.management.internal.EntityManagementUtils;
+import brooklyn.management.internal.EntityManagerInternal;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.test.entity.TestEntityImpl;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Functionals;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+@Test
+public class EntitiesYamlTest extends AbstractYamlTest {
+    private static final Logger log = 
LoggerFactory.getLogger(EntitiesYamlTest.class);
+
+    protected Entity setupAndCheckTestEntityInBasicYamlWith(String ...extras) 
throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml", extras));
+        waitForApplicationTasks(app);
+
+        Assert.assertEquals(app.getDisplayName(), 
"test-entity-basic-template");
+
+        log.info("App started:");
+        Entities.dumpInfo(app);
+        
+        Assert.assertTrue(app.getChildren().iterator().hasNext(), "Expected 
app to have child entity");
+        Entity entity = app.getChildren().iterator().next();
+        Assert.assertTrue(entity instanceof TestEntity, "Expected TestEntity, 
found " + entity.getClass());
+        
+        return (TestEntity)entity;
+    }
+    
+    @Test
+    public void testSingleEntity() throws Exception {
+        setupAndCheckTestEntityInBasicYamlWith();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testBrooklynConfig() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith( 
+            "  brooklyn.config:",
+            "    test.confName: Test Entity Name",
+            "    test.confMapPlain:",
+            "      foo: bar",
+            "      baz: qux",
+            "    test.confListPlain:",
+            "      - dogs",
+            "      - cats",
+            "      - badgers",
+            "    test.confSetThing: !!set",
+            "      ? square",
+            "      ? circle",
+            "      ? triangle",
+            "    test.confObject: 5");
+        
+        Assert.assertEquals(testEntity.getConfig(TestEntity.CONF_NAME), "Test 
Entity Name");
+        List<String> list = testEntity.getConfig(TestEntity.CONF_LIST_PLAIN);
+        Assert.assertEquals(list, ImmutableList.of("dogs", "cats", "badgers"));
+        Map<String, String> map = 
testEntity.getConfig(TestEntity.CONF_MAP_PLAIN);
+        Assert.assertEquals(map, ImmutableMap.of("foo", "bar", "baz", "qux"));
+        Set<String> set = 
(Set<String>)testEntity.getConfig(TestEntity.CONF_SET_THING);
+        Assert.assertEquals(set, ImmutableSet.of("square", "circle", 
"triangle"));
+        Object object = testEntity.getConfig(TestEntity.CONF_OBJECT);
+        Assert.assertEquals(object, 5);
+    }
+
+    @Test
+    public void testFlagInBrooklynConfig() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith( 
+            "  brooklyn.config:",
+            "    confName: Foo Bar");
+        Assert.assertEquals(testEntity.getConfig(TestEntity.CONF_NAME), "Foo 
Bar");
+    }
+
+    @Test
+    public void testUndeclaredItemInBrooklynConfig() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith( 
+            "  brooklyn.config:",
+            "    test.dynamic.confName: Foo Bar");
+        
Assert.assertEquals(testEntity.getConfig(ConfigKeys.newStringConfigKey("test.dynamic.confName")),
 "Foo Bar");
+    }
+
+    @Test
+    public void testFlagAtRoot() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith( 
+            "  confName: Foo Bar");
+        Assert.assertEquals(testEntity.getConfig(TestEntity.CONF_NAME), "Foo 
Bar");
+    }
+
+    @Test
+    public void testFlagAtRootEntityImpl() throws Exception {
+        Entity app = createAndStartApplication(
+                "services:",
+                "- serviceType: " + TestEntityImpl.class.getName(),
+                "  confName: Foo Bar");
+        Entity testEntity = Iterables.getOnlyElement(app.getChildren());
+        Assert.assertEquals(testEntity.getConfig(TestEntity.CONF_NAME), "Foo 
Bar");
+    }
+
+    @Test
+    public void testConfigKeyAtRoot() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith( 
+            "  test.confName: Foo Bar");
+        Assert.assertEquals(testEntity.getConfig(TestEntity.CONF_NAME), "Foo 
Bar");
+    }
+
+    @Test
+    public void testUndeclaredItemAtRootIgnored() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith( 
+            "  test.dynamic.confName: Foo Bar");
+        // should NOT be set (and there should be a warning in the log)
+        String dynamicConfNameValue = 
testEntity.getConfig(ConfigKeys.newStringConfigKey("test.dynamic.confName"));
+        Assert.assertNull(dynamicConfNameValue);
+    }
+
+    @Test
+    public void testExplicitFlags() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith( 
+            "  brooklyn.flags:",
+            "    confName: Foo Bar");
+        Assert.assertEquals(testEntity.getConfig(TestEntity.CONF_NAME), "Foo 
Bar");
+    }
+
+    @Test
+    public void testExplicitFlagsEntityImpl() throws Exception {
+        Entity app = createAndStartApplication(
+                "services:",
+                "- serviceType: " + TestEntityImpl.class.getName(),
+                "  brooklyn.flags:",
+                "    confName: Foo Bar");
+        Entity testEntity = Iterables.getOnlyElement(app.getChildren());
+        Assert.assertEquals(testEntity.getConfig(TestEntity.CONF_NAME), "Foo 
Bar");
+    }
+
+    @Test
+    public void testUndeclaredExplicitFlagsIgnored() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith( 
+            "  brooklyn.flags:",
+            "    test.dynamic.confName: Foo Bar");
+        String dynamicConfNameValue = 
testEntity.getConfig(ConfigKeys.newStringConfigKey("test.dynamic.confName"));
+        Assert.assertNull(dynamicConfNameValue);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testEmptyConfig() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml",
+            "  brooklyn.config:",
+            "    test.confName: \"\"",
+            "    test.confListPlain: !!seq []",
+            "    test.confMapPlain: !!map {}",
+            "    test.confSetPlain: !!set {}",
+            "    test.confObject: \"\""));
+        waitForApplicationTasks(app);
+
+        Assert.assertEquals(app.getDisplayName(), 
"test-entity-basic-template");
+
+        log.info("App started:");
+        Entities.dumpInfo(app);
+
+        Entity entity = app.getChildren().iterator().next();
+        Assert.assertNotNull(entity, "Expected app to have child entity");
+        Assert.assertTrue(entity instanceof TestEntity, "Expected TestEntity, 
found " + entity.getClass());
+        TestEntity testEntity = (TestEntity) entity;
+        Assert.assertEquals(testEntity.getConfig(TestEntity.CONF_NAME), "");
+        List<String> list = testEntity.getConfig(TestEntity.CONF_LIST_PLAIN);
+        Assert.assertEquals(list, ImmutableList.of());
+        Map<String, String> map = 
testEntity.getConfig(TestEntity.CONF_MAP_PLAIN);
+        Assert.assertEquals(map, ImmutableMap.of());
+        // TODO: CONF_SET_PLAIN is being set to an empty ArrayList - may be a 
snakeyaml issue?
+        //        Set<String> plainSet = 
(Set<String>)testEntity.getConfig(TestEntity.CONF_SET_PLAIN);
+        //        Assert.assertEquals(plainSet, ImmutableSet.of());
+        Object object = testEntity.getConfig(TestEntity.CONF_OBJECT);
+        Assert.assertEquals(object, "");
+    }
+    
+    @SuppressWarnings("unchecked")
+    public void testEmptyStructuredConfig() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml",
+            "  brooklyn.config:",
+            "    test.confName: \"\"",
+            "    test.confListThing: !!seq []",
+            "    test.confSetThing: !!set {}",
+            "    test.confMapThing: !!map {}"));
+        waitForApplicationTasks(app);
+
+        Assert.assertEquals(app.getDisplayName(), 
"test-entity-basic-template");
+
+        log.info("App started:");
+        Entities.dumpInfo(app);
+
+        Entity entity = app.getChildren().iterator().next();
+        Assert.assertNotNull(entity, "Expected app to have child entity");
+        Assert.assertTrue(entity instanceof TestEntity, "Expected TestEntity, 
found " + entity.getClass());
+        TestEntity testEntity = (TestEntity) entity;
+        List<String> thingList = 
(List<String>)testEntity.getConfig(TestEntity.CONF_LIST_THING);
+        Set<String> thingSet = 
(Set<String>)testEntity.getConfig(TestEntity.CONF_SET_THING);
+        Map<String, String> thingMap = (Map<String, 
String>)testEntity.getConfig(TestEntity.CONF_MAP_THING);
+        Assert.assertEquals(thingList, Lists.newArrayList());
+        Assert.assertEquals(thingSet, ImmutableSet.of());
+        Assert.assertEquals(thingMap, ImmutableMap.of());
+    }
+
+    @Test
+    public void testSensor() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml", 
+            "  brooklyn.config:",
+            "    test.confObject: 
$brooklyn:sensor(\"brooklyn.test.entity.TestEntity\", \"test.sequence\")"));
+        waitForApplicationTasks(app);
+
+        Assert.assertEquals(app.getDisplayName(), 
"test-entity-basic-template");
+
+        log.info("App started:");
+        Entities.dumpInfo(app);
+
+        Entity entity = app.getChildren().iterator().next();
+        Assert.assertNotNull(entity, "Expected app to have child entity");
+        Assert.assertTrue(entity instanceof TestEntity, "Expected TestEntity, 
found " + entity.getClass());
+        TestEntity testEntity = (TestEntity) entity;
+        Object object = testEntity.getConfig(TestEntity.CONF_OBJECT);
+        Assert.assertNotNull(object);
+        Assert.assertTrue(object instanceof AttributeSensor, 
"attributeSensor="+object);
+        Assert.assertEquals(object, TestEntity.SEQUENCE);
+    }
+
+    @Test
+    public void testSensorOnArbitraryClass() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml", 
+            "  brooklyn.config:",
+            "    test.confObject: 
$brooklyn:sensor(\""+EntitiesYamlTest.class.getName()+"$ArbitraryClassWithSensor\",
 \"mysensor\")"));
+        waitForApplicationTasks(app);
+
+        log.info("App started:");
+        Entities.dumpInfo(app);
+
+        TestEntity entity = (TestEntity) app.getChildren().iterator().next();
+        Object object = entity.getConfig(TestEntity.CONF_OBJECT);
+        Assert.assertEquals(object, ArbitraryClassWithSensor.MY_SENSOR);
+    }
+    public static class ArbitraryClassWithSensor {
+        public static final AttributeSensor<String> MY_SENSOR = 
Sensors.newStringSensor("mysensor");
+    }
+    
+    @Test
+    public void testComponent() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml",
+            "  brooklyn.config:",
+            "    test.confName: first entity",
+            "  id: te1",
+            "- serviceType: brooklyn.test.entity.TestEntity",
+            "  name: second entity",
+            "  brooklyn.config:",
+            "    test.confObject: $brooklyn:component(\"te1\")"));
+        waitForApplicationTasks(app);
+        Entity firstEntity = null;
+        Entity secondEntity = null;
+        Assert.assertEquals(app.getChildren().size(), 2);
+        for (Entity entity : app.getChildren()) {
+            if (entity.getDisplayName().equals("testentity"))
+                firstEntity = entity;
+            else if (entity.getDisplayName().equals("second entity"))
+                secondEntity = entity;
+        }
+        final Entity[] entities = {firstEntity, secondEntity};
+        Assert.assertNotNull(entities[0], "Expected app to contain child named 
'testentity'");
+        Assert.assertNotNull(entities[1], "Expected app to contain child named 
'second entity'");
+        Object object = 
((EntityInternal)app).getExecutionContext().submit(MutableMap.of(), new 
Callable<Object>() {
+            public Object call() {
+                return entities[1].getConfig(TestEntity.CONF_OBJECT);
+            }}).get();
+        Assert.assertNotNull(object);
+        Assert.assertEquals(object, firstEntity, "Expected second entity's 
test.confObject to contain first entity");
+    }
+
+    @Test
+    public void testGrandchildEntities() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml", 
+            "  brooklyn.config:",
+            "    test.confName: first entity",
+            "  brooklyn.children:",
+            "  - serviceType: brooklyn.test.entity.TestEntity",
+            "    name: Child Entity",
+            "    brooklyn.config:",
+            "      test.confName: Name of the first Child",
+            "    brooklyn.children:",
+            "    - serviceType: brooklyn.test.entity.TestEntity",
+            "      name: Grandchild Entity",
+            "      brooklyn.config:",
+            "        test.confName: Name of the Grandchild",
+            "  - serviceType: brooklyn.test.entity.TestEntity",
+            "    name: Second Child",
+            "    brooklyn.config:",
+            "      test.confName: Name of the second Child"));
+        waitForApplicationTasks(app);
+        Assert.assertEquals(app.getChildren().size(), 1);
+        Entity firstEntity = app.getChildren().iterator().next();
+        Assert.assertEquals(firstEntity.getConfig(TestEntity.CONF_NAME), 
"first entity");
+        Assert.assertEquals(firstEntity.getChildren().size(), 2);
+        Entity firstChild = null;
+        Entity secondChild = null;
+        for (Entity entity : firstEntity.getChildren()) {
+            if (entity.getConfig(TestEntity.CONF_NAME).equals("Name of the 
first Child"))
+                firstChild = entity;
+            if (entity.getConfig(TestEntity.CONF_NAME).equals("Name of the 
second Child"))
+                secondChild = entity;
+        }
+        Assert.assertNotNull(firstChild, "Expected a child of 'first entity' 
with the name 'Name of the first Child'");
+        Assert.assertNotNull(secondChild, "Expected a child of 'first entity' 
with the name 'Name of the second Child'");
+        Assert.assertEquals(firstChild.getChildren().size(), 1);
+        Entity grandchild = firstChild.getChildren().iterator().next();
+        Assert.assertEquals(grandchild.getConfig(TestEntity.CONF_NAME), "Name 
of the Grandchild");
+        Assert.assertEquals(secondChild.getChildren().size(), 0);
+    }
+
+    @Test
+    public void testWithInitConfig() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-with-init-config.yaml"));
+        waitForApplicationTasks(app);
+        Assert.assertEquals(app.getDisplayName(), 
"test-entity-with-init-config");
+        TestEntityWithInitConfig testWithConfigInit = null;
+        TestEntity testEntity = null;
+        Assert.assertEquals(app.getChildren().size(), 2);
+        for (Entity entity : app.getChildren()) {
+            if (entity instanceof TestEntity)
+                testEntity = (TestEntity) entity;
+            if (entity instanceof TestEntityWithInitConfig)
+                testWithConfigInit = (TestEntityWithInitConfig) entity;
+        }
+        Assert.assertNotNull(testEntity, "Expected app to contain TestEntity 
child");
+        Assert.assertNotNull(testWithConfigInit, "Expected app to contain 
TestEntityWithInitConfig child");
+        Assert.assertEquals(testWithConfigInit.getEntityCachedOnInit(), 
testEntity);
+        log.info("App started:");
+        Entities.dumpInfo(app);
+    }
+
+    @Test
+    public void testMultipleReferencesJava() throws Exception {
+        final Entity app = 
createAndStartApplication(loadYaml("test-referencing-entities.yaml"));
+        waitForApplicationTasks(app);
+        
+        Entity c1 = Tasks.resolving(new DslComponent("c1").newTask(), 
Entity.class).context( ((EntityInternal)app).getExecutionContext() 
).embedResolutionInTask(true).get();
+        Assert.assertEquals(c1, Entities.descendants(app, 
EntityPredicates.displayNameEqualTo("child 1")).iterator().next());
+        
+        Entity e1 = Tasks.resolving(new DslComponent(Scope.PARENT, 
"xxx").newTask(), Entity.class).context( 
((EntityInternal)c1).getExecutionContext() ).embedResolutionInTask(true).get();
+        Assert.assertEquals(e1, Entities.descendants(app, 
EntityPredicates.displayNameEqualTo("entity 1")).iterator().next());
+        
+        Entity c1a = 
Tasks.resolving(BrooklynDslCommon.descendant("c1").newTask(), 
Entity.class).context( ((EntityInternal)e1).getExecutionContext() 
).embedResolutionInTask(true).get();
+        Assert.assertEquals(c1a, c1);
+        Entity e1a = 
Tasks.resolving(BrooklynDslCommon.ancestor("e1").newTask(), 
Entity.class).context( ((EntityInternal)c1).getExecutionContext() 
).embedResolutionInTask(true).get();
+        Assert.assertEquals(e1a, e1);
+        try {
+            Tasks.resolving(BrooklynDslCommon.ancestor("c1").newTask(), 
Entity.class).context( ((EntityInternal)e1).getExecutionContext() 
).embedResolutionInTask(true).get();
+            Assert.fail("Should not have found c1 as ancestor of e1");
+        } catch (Exception e) { /* expected */ }
+    }
+    
+    @Test
+    public void testMultipleReferences() throws Exception {
+        final Entity app = 
createAndStartApplication(loadYaml("test-referencing-entities.yaml"));
+        waitForApplicationTasks(app);
+        
+        Entities.dumpInfo(app);
+        
+        Assert.assertEquals(app.getDisplayName(), "test-referencing-entities");
+
+        Entity entity1 = null, entity2 = null, child1 = null, child2 = null, 
grandchild1 = null, grandchild2 = null;
+
+        Assert.assertEquals(app.getChildren().size(), 2);
+        for (Entity child : app.getChildren()) {
+            if (child.getDisplayName().equals("entity 1"))
+                entity1 = child;
+            if (child.getDisplayName().equals("entity 2"))
+                entity2 = child;
+        }
+        Assert.assertNotNull(entity1);
+        Assert.assertNotNull(entity2);
+
+        Assert.assertEquals(entity1.getChildren().size(), 2);
+        for (Entity child : entity1.getChildren()) {
+            if (child.getDisplayName().equals("child 1"))
+                child1 = child;
+            if (child.getDisplayName().equals("child 2"))
+                child2 = child;
+        }
+        Assert.assertNotNull(child1);
+        Assert.assertNotNull(child2);
+
+        Assert.assertEquals(child1.getChildren().size(), 2);
+        for (Entity child : child1.getChildren()) {
+            if (child.getDisplayName().equals("grandchild 1"))
+                grandchild1 = child;
+            if (child.getDisplayName().equals("grandchild 2"))
+                grandchild2 = child;
+        }
+        Assert.assertNotNull(grandchild1);
+        Assert.assertNotNull(grandchild2);
+
+        Map<ConfigKey<Entity>, Entity> keyToEntity = new 
ImmutableMap.Builder<ConfigKey<Entity>, Entity>()
+            .put(ReferencingYamlTestEntity.TEST_REFERENCE_APP, app)
+            .put(ReferencingYamlTestEntity.TEST_REFERENCE_ENTITY1, entity1)
+            .put(ReferencingYamlTestEntity.TEST_REFERENCE_ENTITY1_ALT, entity1)
+            .put(ReferencingYamlTestEntity.TEST_REFERENCE_ENTITY2, entity2)
+            .put(ReferencingYamlTestEntity.TEST_REFERENCE_CHILD1, child1)
+            .put(ReferencingYamlTestEntity.TEST_REFERENCE_CHILD2, child2)
+            .put(ReferencingYamlTestEntity.TEST_REFERENCE_GRANDCHILD1, 
grandchild1)
+            .put(ReferencingYamlTestEntity.TEST_REFERENCE_GRANDCHILD2, 
grandchild2)
+            .build();
+
+        Iterable<Entity> entitiesInApp = 
((EntityInternal)app).getExecutionContext().submit(MutableMap.of(), new 
Callable<Iterable<Entity>>() {
+            @Override
+            public Iterable<Entity> call() throws Exception {
+                return 
((EntityManagerInternal)((EntityInternal)app).getManagementContext().getEntityManager()).getAllEntitiesInApplication((Application)app);
+            }
+        }).get();
+
+        for (Entity entityInApp : entitiesInApp) {
+            checkReferences(entityInApp, keyToEntity);
+            try {
+                getResolvedConfigInTask(entityInApp, 
ReferencingYamlTestEntity.TEST_REFERENCE_BOGUS);
+                Assert.fail("Should not have resolved 
"+ReferencingYamlTestEntity.TEST_REFERENCE_BOGUS+" at "+entityInApp);
+            } catch (Exception e) {
+                /* expected */
+            }
+        }
+    }
+
+    private void checkReferences(final Entity entity, Map<ConfigKey<Entity>, 
Entity> keyToEntity) throws Exception {
+        for (final ConfigKey<Entity> key : keyToEntity.keySet()) {
+            try {
+                Assert.assertEquals(getResolvedConfigInTask(entity, 
key).get(), keyToEntity.get(key));
+            } catch (Throwable t) {
+                Exceptions.propagateIfFatal(t);
+                Assert.fail("Wrong value for "+entity+":"+key+", 
"+((EntityInternal)entity).config().getLocalRaw(key)+": "+t, t);
+            }
+        }
+    }
+
+    private Maybe<Entity> getResolvedConfigInTask(final Entity entity, final 
ConfigKey<Entity> key) {
+        return Tasks.resolving(Tasks.<Entity>builder().body(
+            
Functionals.callable(Suppliers.compose(EntityFunctions.config(key), 
Suppliers.ofInstance(entity))) ).build())
+            .as(Entity.class)
+            .context( ((EntityInternal)entity).getExecutionContext() 
).embedResolutionInTask(true)
+            .getMaybe();
+    }
+
+    public void testWithAppLocation() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml",  
+            "location: localhost:(name=yaml name)"));
+        waitForApplicationTasks(app);
+        Assert.assertEquals(app.getLocations().size(), 1);
+        Location location = app.getLocations().iterator().next();
+        Assert.assertNotNull(location);
+        Assert.assertEquals(location.getDisplayName(), "yaml name");
+        Assert.assertEquals(app.getChildren().size(), 1);
+        Entity entity = app.getChildren().iterator().next();
+        Assert.assertNotNull(entity);
+        Assert.assertEquals(entity.getLocations().size(), 1);
+    }
+
+    @Test
+    public void testWithEntityLocation() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml",  
+            "  location: localhost:(name=yaml name)\n"));
+        waitForApplicationTasks(app);
+        Assert.assertEquals(app.getLocations().size(), 0);
+        Assert.assertEquals(app.getChildren().size(), 1);
+        Entity entity = app.getChildren().iterator().next();
+        Assert.assertEquals(entity.getLocations().size(), 1);
+        Location location = entity.getLocations().iterator().next();
+        Assert.assertNotNull(location);
+        Assert.assertEquals(location.getDisplayName(), "yaml name");
+        Assert.assertNotNull(entity);
+    }
+
+    @Test
+    public void testWith2AppLocations() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml",  
+            "locations:",
+            "- localhost:(name=localhost name)",
+            "- byon:(hosts=\"1.1.1.1\", name=byon name)"));
+        waitForApplicationTasks(app);
+
+        Assert.assertEquals(app.getLocations().size(), 2);
+        Location localhostLocation = null, byonLocation = null; 
+        for (Location location : app.getLocations()) {
+            if (location.getDisplayName().equals("localhost name"))
+                localhostLocation = location;
+            else if (location.getDisplayName().equals("byon name"))
+                byonLocation = location;
+        }
+        Assert.assertNotNull(localhostLocation);
+        Assert.assertNotNull(byonLocation);
+        Assert.assertEquals(app.getChildren().size(), 1);
+        Entity entity = app.getChildren().iterator().next();
+        Assert.assertNotNull(entity);
+        Assert.assertEquals(entity.getLocations().size(), 2);
+    }
+
+    @Test
+    public void testWith2EntityLocations() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml",  
+            "  locations:",
+            "  - localhost:(name=localhost name)",
+            "  - byon:(hosts=\"1.1.1.1\", name=byon name)"));
+        waitForApplicationTasks(app);
+        Assert.assertEquals(app.getLocations().size(), 0);
+        Assert.assertEquals(app.getChildren().size(), 1);
+        Entity entity = app.getChildren().iterator().next();
+        Assert.assertEquals(entity.getLocations().size(), 2);
+        Location localhostLocation = null, byonLocation = null; 
+        for (Location location : entity.getLocations()) {
+            if (location.getDisplayName().equals("localhost name"))
+                localhostLocation = location;
+            else if (location.getDisplayName().equals("byon name"))
+                byonLocation = location;
+        }
+        Assert.assertNotNull(localhostLocation);
+        Assert.assertNotNull(byonLocation);
+    }
+
+    @Test
+    public void testWithAppAndEntityLocations() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-entity-basic-template.yaml",  
+            "  location: localhost:(name=localhost name)",
+            "location: byon:(hosts=\"1.1.1.1\", name=byon name)"));
+        waitForApplicationTasks(app);
+        Assert.assertEquals(app.getLocations().size(), 1);
+        Assert.assertEquals(app.getChildren().size(), 1);
+        Entity entity = app.getChildren().iterator().next();
+        
+        Assert.assertEquals(entity.getLocations().size(), 2);
+        Iterator<Location> entityLocationIterator = 
entity.getLocations().iterator();
+        Assert.assertEquals(entityLocationIterator.next().getDisplayName(), 
"localhost name");
+        Assert.assertEquals(entityLocationIterator.next().getDisplayName(), 
"byon name");
+        
+        Location appLocation = app.getLocations().iterator().next();
+        Assert.assertEquals(appLocation.getDisplayName(), "byon name");
+    }
+
+    @Test
+    public void testCreateClusterWithMemberSpec() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("test-cluster-with-member-spec.yaml"));
+        waitForApplicationTasks(app);
+        assertEquals(app.getChildren().size(), 1);
+
+        Entity clusterEntity = Iterables.getOnlyElement(app.getChildren());
+        assertTrue(clusterEntity instanceof DynamicCluster, 
"cluster="+clusterEntity);
+
+        DynamicCluster cluster = DynamicCluster.class.cast(clusterEntity);
+        assertEquals(cluster.getMembers().size(), 2, 
"members="+cluster.getMembers());
+
+        for (Entity member : cluster.getMembers()) {
+            assertTrue(member instanceof TestEntity, "member="+member);
+            assertEquals(member.getConfig(TestEntity.CONF_NAME), "yamlTest");
+        }
+    }
+
+    @Test
+    public void testEntitySpecConfig() throws Exception {
+        String yaml =
+                "services:\n"+
+                "- serviceType: brooklyn.test.entity.TestEntity\n"+
+                "  brooklyn.config:\n"+
+                "   test.childSpec:\n"+
+                "     $brooklyn:entitySpec:\n"+
+                "       type: brooklyn.test.entity.TestEntity\n"+
+                "       brooklyn.config:\n"+
+                "         test.confName: inchildspec\n";
+        
+        Application app = (Application) createStartWaitAndLogApplication(new 
StringReader(yaml));
+        TestEntity entity = (TestEntity) 
Iterables.getOnlyElement(app.getChildren());
+        
+        TestEntity child = (TestEntity) 
entity.createAndManageChildFromConfig();
+        assertEquals(child.getConfig(TestEntity.CONF_NAME), "inchildspec");
+    }
+
+    @Test
+    public void testEntitySpecFlags() throws Exception {
+        String yaml =
+                "services:\n"+
+                "- serviceType: brooklyn.test.entity.TestEntity\n"+
+                "  confName: inParent\n"+
+                "  brooklyn.config:\n"+
+                "   test.childSpec:\n"+
+                "     $brooklyn:entitySpec:\n"+
+                "       type: brooklyn.test.entity.TestEntity\n"+
+                "       confName: inchildspec\n";
+        
+        Application app = (Application) createStartWaitAndLogApplication(new 
StringReader(yaml));
+        TestEntity entity = (TestEntity) 
Iterables.getOnlyElement(app.getChildren());
+        
+        TestEntity child = (TestEntity) 
entity.createAndManageChildFromConfig();
+        assertEquals(child.getConfig(TestEntity.CONF_NAME), "inchildspec");
+    }
+
+    @Test
+    public void testEntitySpecExplicitFlags() throws Exception {
+        String yaml =
+                "services:\n"+
+                "- serviceType: brooklyn.test.entity.TestEntity\n"+
+                "  brooklyn.flags:\n"+
+                "    confName: inParent\n"+
+                "  brooklyn.config:\n"+
+                "   test.childSpec:\n"+
+                "     $brooklyn:entitySpec:\n"+
+                "       type: brooklyn.test.entity.TestEntity\n"+
+                "       brooklyn.flags:\n"+
+                "         confName: inchildspec\n";
+        
+        Application app = (Application) createStartWaitAndLogApplication(new 
StringReader(yaml));
+        TestEntity entity = (TestEntity) 
Iterables.getOnlyElement(app.getChildren());
+        
+        TestEntity child = (TestEntity) 
entity.createAndManageChildFromConfig();
+        assertEquals(child.getConfig(TestEntity.CONF_NAME), "inchildspec");
+    }
+
+    @Test
+    public void testEntitySpecWithChildren() throws Exception {
+        String yaml =
+                "services:\n"+
+                "- serviceType: brooklyn.test.entity.TestEntity\n"+
+                "  brooklyn.config:\n"+
+                "   test.childSpec:\n"+
+                "     $brooklyn:entitySpec:\n"+
+                "       type: brooklyn.test.entity.TestEntity\n"+
+                "       brooklyn.config:\n"+
+                "         test.confName: child\n"+
+                "       brooklyn.children:\n"+
+                "       - type: brooklyn.test.entity.TestEntity\n" +
+                "         brooklyn.config:\n" +
+                "           test.confName: grandchild\n" +
+                "         brooklyn.children:\n"+
+                "         - type: brooklyn.test.entity.TestEntity\n" +
+                "           brooklyn.config:\n" +
+                "             test.confName: greatgrandchild\n";
+        
+        Application app = (Application) createStartWaitAndLogApplication(new 
StringReader(yaml));
+        TestEntity entity = (TestEntity) 
Iterables.getOnlyElement(app.getChildren());
+        
+        TestEntity child = (TestEntity) 
entity.createAndManageChildFromConfig();
+        assertEquals(child.getConfig(TestEntity.CONF_NAME), "child");
+        assertEquals(child.getChildren().size(), 1, "Child entity should have 
exactly one child of its own");
+
+        TestEntity grandchild = (TestEntity) 
Iterables.getOnlyElement(child.getChildren());
+        assertEquals(grandchild.getConfig(TestEntity.CONF_NAME), "grandchild");
+        assertEquals(grandchild.getChildren().size(), 1, "Grandchild entity 
should have exactly one child of its own");
+
+        TestEntity greatgrandchild = (TestEntity) 
Iterables.getOnlyElement(grandchild.getChildren());
+        assertEquals(greatgrandchild.getConfig(TestEntity.CONF_NAME), 
"greatgrandchild");
+    }
+    
+    @Test
+    public void testNestedEntitySpecConfigs() throws Exception {
+        String yaml =
+                "services:\n"+
+                "- serviceType: brooklyn.test.entity.TestEntity\n"+
+                "  brooklyn.config:\n"+
+                "   test.childSpec:\n"+
+                "     $brooklyn:entitySpec:\n"+
+                "       type: brooklyn.test.entity.TestEntity\n"+
+                "       brooklyn.config:\n"+
+                "         test.confName: inchildspec\n"+
+                "         test.childSpec:\n"+
+                "           $brooklyn:entitySpec:\n"+
+                "             type: brooklyn.test.entity.TestEntity\n"+
+                "             brooklyn.config:\n"+
+                "               test.confName: ingrandchildspec\n";
+        
+        Application app = (Application) createStartWaitAndLogApplication(new 
StringReader(yaml));
+        TestEntity entity = (TestEntity) 
Iterables.getOnlyElement(app.getChildren());
+        
+        TestEntity child = (TestEntity) 
entity.createAndManageChildFromConfig();
+        assertEquals(child.getConfig(TestEntity.CONF_NAME), "inchildspec");
+        
+        TestEntity grandchild = (TestEntity) 
child.createAndManageChildFromConfig();
+        assertEquals(grandchild.getConfig(TestEntity.CONF_NAME), 
"ingrandchildspec");
+    }
+    
+    @Test
+    public void testEntitySpecInUnmatchedConfig() throws Exception {
+        String yaml =
+                "services:\n"+
+                "- serviceType: brooklyn.test.entity.TestEntity\n"+
+                "  brooklyn.config:\n"+
+                "   key.does.not.match:\n"+
+                "     $brooklyn:entitySpec:\n"+
+                "       type: brooklyn.test.entity.TestEntity\n"+
+                "       brooklyn.config:\n"+
+                "         test.confName: inchildspec\n";
+        
+        Application app = (Application) createStartWaitAndLogApplication(new 
StringReader(yaml));
+        TestEntity entity = (TestEntity) 
Iterables.getOnlyElement(app.getChildren());
+        EntitySpec<?> entitySpec = (EntitySpec<?>) 
entity.config().getBag().getStringKey("key.does.not.match");
+        assertEquals(entitySpec.getType(), TestEntity.class);
+        assertEquals(entitySpec.getConfig(), 
ImmutableMap.of(TestEntity.CONF_NAME, "inchildspec"));
+    }
+
+    @Test
+    public void testAppWithSameServerEntityStarts() throws Exception {
+        Entity app = 
createAndStartApplication(loadYaml("same-server-entity-test.yaml"));
+        waitForApplicationTasks(app);
+        assertNotNull(app);
+        assertEquals(app.getAttribute(Attributes.SERVICE_STATE_ACTUAL), 
Lifecycle.RUNNING, "service state");
+        assertTrue(app.getAttribute(Attributes.SERVICE_UP), "service up");
+
+        assertEquals(app.getChildren().size(), 1);
+        Entity entity = Iterables.getOnlyElement(app.getChildren());
+        assertTrue(entity instanceof SameServerEntity, "entity="+entity);
+
+        SameServerEntity sse = (SameServerEntity) entity;
+        assertEquals(sse.getChildren().size(), 2);
+        for (Entity child : sse.getChildren()) {
+            assertTrue(child instanceof BasicEntity, "child="+child);
+        }
+    }
+    
+    @Test
+    public void testEntityImplExposesAllInterfacesIncludingStartable() throws 
Exception {
+        String yaml =
+                "services:\n"+
+                "- serviceType: brooklyn.test.entity.TestEntityImpl\n";
+        
+        Application app = (Application) createStartWaitAndLogApplication(new 
StringReader(yaml));
+        TestEntity entity = (TestEntity) 
Iterables.getOnlyElement(app.getChildren());
+        assertTrue(entity.getCallHistory().contains("start"), 
"history="+entity.getCallHistory());
+    }
+
+    @Test
+    public void testEntityWithInitializer() throws Exception {
+        String yaml =
+                "services:\n"+
+                "- type: "+TestEntity.class.getName()+"\n"+
+                "  brooklyn.initializers: [ { type: 
"+TestSensorAndEffectorInitializer.class.getName()+" } ]";
+        
+        Application app = (Application) createStartWaitAndLogApplication(new 
StringReader(yaml));
+        TestEntity entity = (TestEntity) 
Iterables.getOnlyElement(app.getChildren());
+        
+        Effector<?> hi = 
entity.getEffector(TestSensorAndEffectorInitializer.EFFECTOR_SAY_HELLO);
+        Assert.assertNotNull(hi);
+        
+        Assert.assertNotNull( 
entity.getEntityType().getSensor(TestSensorAndEffectorInitializer.SENSOR_HELLO_DEFINED)
 );
+        Assert.assertNotNull( 
entity.getEntityType().getSensor(TestSensorAndEffectorInitializer.SENSOR_HELLO_DEFINED_EMITTED)
 );
+        Assert.assertNull( 
entity.getEntityType().getSensor(TestSensorAndEffectorInitializer.SENSOR_LAST_HELLO)
 );
+        
+        Assert.assertNull( 
entity.getAttribute(Sensors.newStringSensor(TestSensorAndEffectorInitializer.SENSOR_LAST_HELLO))
 );
+        Assert.assertNull( 
entity.getAttribute(Sensors.newStringSensor(TestSensorAndEffectorInitializer.SENSOR_HELLO_DEFINED))
 );
+        Assert.assertEquals( 
entity.getAttribute(Sensors.newStringSensor(TestSensorAndEffectorInitializer.SENSOR_HELLO_DEFINED_EMITTED)),
+            "1");
+        
+        Task<String> saying = entity.invoke(Effectors.effector(String.class, 
TestSensorAndEffectorInitializer.EFFECTOR_SAY_HELLO).buildAbstract(), 
+            MutableMap.of("name", "Bob"));
+        Assert.assertEquals(saying.get(Duration.TEN_SECONDS), "Hello Bob");
+        Assert.assertEquals( 
entity.getAttribute(Sensors.newStringSensor(TestSensorAndEffectorInitializer.SENSOR_LAST_HELLO)),
+            "Bob");
+    }
+
+    @Test
+    public void testEntityWithConfigurableInitializerEmpty() throws Exception {
+        String yaml =
+                "services:\n"+
+                "- type: "+TestEntity.class.getName()+"\n"+
+                "  brooklyn.initializers: [ { type: 
"+TestSensorAndEffectorInitializer.TestConfigurableInitializer.class.getName()+"
 } ]";
+        
+        Application app = (Application) createStartWaitAndLogApplication(new 
StringReader(yaml));
+        TestEntity entity = (TestEntity) 
Iterables.getOnlyElement(app.getChildren());
+        
+        Task<String> saying = entity.invoke(Effectors.effector(String.class, 
TestSensorAndEffectorInitializer.EFFECTOR_SAY_HELLO).buildAbstract(), 
+            MutableMap.of("name", "Bob"));
+        Assert.assertEquals(saying.get(Duration.TEN_SECONDS), "Hello Bob");
+    }
+
+    @Test
+    public void testEntityWithConfigurableInitializerNonEmpty() throws 
Exception {
+        String yaml =
+                "services:\n"+
+                "- type: "+TestEntity.class.getName()+"\n"+
+                "  brooklyn.initializers: [ { "
+                  + "type: 
"+TestSensorAndEffectorInitializer.TestConfigurableInitializer.class.getName()+","
+                  + "brooklyn.config: { 
"+TestSensorAndEffectorInitializer.TestConfigurableInitializer.HELLO_WORD+": 
Hey }"
+                  + " } ]";
+        
+        Application app = (Application) createStartWaitAndLogApplication(new 
StringReader(yaml));
+        TestEntity entity = (TestEntity) 
Iterables.getOnlyElement(app.getChildren());
+        
+        Task<String> saying = entity.invoke(Effectors.effector(String.class, 
TestSensorAndEffectorInitializer.EFFECTOR_SAY_HELLO).buildAbstract(), 
+            MutableMap.of("name", "Bob"));
+        Assert.assertEquals(saying.get(Duration.TEN_SECONDS), "Hey Bob");
+    }
+
+    @Test
+    public void testEntityTypeAsImpl() throws Exception {
+        String yaml =
+                "services:"+"\n"+
+                "- type: "+CustomTestEntityImpl.class.getName()+"\n";
+
+        Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+
+        Entity testEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(testEntity.getEntityType().getName(), 
"CustomTestEntityImpl");
+    }
+    
+    public static class CustomTestEntityImpl extends TestEntityImpl {
+        public CustomTestEntityImpl() {
+            System.out.println("in CustomTestEntityImpl");
+        }
+        @Override
+        protected String getEntityTypeName() {
+            return "CustomTestEntityImpl";
+        }
+    }
+
+    @Test
+    public void testWrapperAppMarkerExists() throws Exception {
+        Entity entity = createAndStartApplication(
+                "services:",
+                "- type: " + BasicEntity.class.getName());
+        assertTrue(entity.getConfig(EntityManagementUtils.WRAPPER_APP_MARKER));
+    }
+
+    @Test
+    public void testWrapperAppMarkerDoesntExist() throws Exception {
+        Entity entity = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName());
+        assertNull(entity.getConfig(EntityManagementUtils.WRAPPER_APP_MARKER));
+    }
+
+    @Test
+    public void testWrapperAppMarkerForced() throws Exception {
+        Entity entity = createAndStartApplication(
+                "wrappedApp: true",
+                "services:",
+                "- type: " + BasicApplication.class.getName());
+        assertTrue(entity.getConfig(EntityManagementUtils.WRAPPER_APP_MARKER));
+    }
+
+    @Test
+    public void testWrapperAppMarkerUnforced() throws Exception {
+        Entity entity = createAndStartApplication(
+                "wrappedApp: false",
+                "services:",
+                "- type: " + BasicApplication.class.getName());
+        assertNull(entity.getConfig(EntityManagementUtils.WRAPPER_APP_MARKER));
+    }
+
+    @Override
+    protected Logger getLogger() {
+        return log;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
new file mode 100644
index 0000000..a83dba2
--- /dev/null
+++ 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn;
+
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+
+import java.io.File;
+import java.io.Reader;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Application;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.rebind.RebindTestUtils;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.Task;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.stream.Streams;
+
+import com.google.common.io.Files;
+
+@Test
+public class JavaWebAppWithDslYamlRebindIntegrationTest extends 
AbstractYamlTest {
+    
+    private static final Logger log = 
LoggerFactory.getLogger(JavaWebAppWithDslYamlRebindIntegrationTest.class);
+    
+    protected ClassLoader classLoader = getClass().getClassLoader();
+    protected File mementoDir;
+    protected Set<ManagementContext> mgmtContexts = MutableSet.of();
+
+    @Override
+    protected LocalManagementContext newTestManagementContext() {
+        if (mementoDir!=null) throw new IllegalStateException("already created 
mgmt context");
+        mementoDir = Files.createTempDir();
+        log.info("Test "+getClass()+" persisting to "+mementoDir);
+
+        LocalManagementContext mgmt =
+            RebindTestUtils.newPersistingManagementContext(mementoDir, 
classLoader, 1);
+        mgmtContexts.add(mgmt);
+        return mgmt;
+    }
+    
+    @AfterMethod(alwaysRun = true)
+    @Override
+    public void tearDown() {
+        for (ManagementContext mgmt: mgmtContexts) Entities.destroyAll(mgmt);
+        super.tearDown();
+        mementoDir = null;
+        mgmtContexts.clear();
+    }
+
+    @Override
+    protected Logger getLogger() {
+        return log;
+    }
+
+    public Application rebind(Application app) throws Exception {
+        RebindTestUtils.waitForPersisted(app);
+        // optionally for good measure can also check this:
+//        RebindTestUtils.checkCurrentMementoSerializable(app);
+        Application result = RebindTestUtils.rebind(mementoDir, 
getClass().getClassLoader());
+        mgmtContexts.add(result.getManagementContext());
+        return result;
+    }
+
+    /** as {@link JavaWebAppsIntegrationTest#testWithDbDeploy()} but with 
rebind */
+    @Test(groups="Integration")
+    public void testJavaWebAppDeployAndRebind() throws Exception {
+        Reader input = Streams.reader(new 
ResourceUtils(this).getResourceFromUrl("java-web-app-and-db-with-function.yaml"));
+        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
+
+        Assembly assembly = at.getInstantiator().newInstance().instantiate(at, 
platform);
+        final Application app = (Application) 
mgmt().getEntityManager().getEntity(assembly.getId());
+
+        Set<Task<?>> tasks = 
BrooklynTaskTags.getTasksInEntityContext(mgmt().getExecutionManager(), app);
+        for (Task<?> t: tasks) t.blockUntilEnded();
+        Entities.dumpInfo(app);
+
+        Application app2 = rebind(app);
+        Assert.assertEquals(app2.getChildren().size(), 2);
+    }
+
+    // test for https://github.com/brooklyncentral/brooklyn/issues/1422
+    @Test(groups="Integration")
+    public void testJavaWebWithMemberSpecRebind() throws Exception {
+        Reader input = Streams.reader(new 
ResourceUtils(this).getResourceFromUrl("test-java-web-app-spec-and-db-with-function.yaml"));
+        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
+
+        Assembly assembly = at.getInstantiator().newInstance().instantiate(at, 
platform);
+        final Application app = (Application) 
mgmt().getEntityManager().getEntity(assembly.getId());
+
+        Set<Task<?>> tasks = 
BrooklynTaskTags.getTasksInEntityContext(mgmt().getExecutionManager(), app);
+        for (Task<?> t: tasks) t.blockUntilEnded();
+        Entities.dumpInfo(app);
+        
+        Application app2 = rebind(app);
+        Assert.assertEquals(app2.getChildren().size(), 2);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
new file mode 100644
index 0000000..007c830
--- /dev/null
+++ 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
@@ -0,0 +1,275 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.PlatformComponent;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.collection.ResolvableLink;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.webapp.DynamicWebAppCluster;
+import brooklyn.entity.webapp.JavaWebAppService;
+import brooklyn.entity.webapp.WebAppService;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.Task;
+import brooklyn.policy.Policy;
+import brooklyn.policy.autoscaling.AutoScalerPolicy;
+import brooklyn.test.Asserts;
+import brooklyn.test.EntityTestUtils;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.net.Urls;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.time.Duration;
+
+import com.google.common.collect.Iterables;
+
+@Test(groups="Integration")
+public class JavaWebAppsIntegrationTest {
+
+    private static final Logger log = 
LoggerFactory.getLogger(JavaWebAppsIntegrationTest.class);
+    
+    private ManagementContext brooklynMgmt;
+    private BrooklynCampPlatform platform;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setup() {
+        BrooklynCampPlatformLauncherNoServer launcher = new 
BrooklynCampPlatformLauncherNoServer();
+        launcher.launch();
+        brooklynMgmt = launcher.getBrooklynMgmt();
+      
+        platform = new BrooklynCampPlatform(
+              PlatformRootSummary.builder().name("Brooklyn CAMP 
Platform").build(),
+              brooklynMgmt);
+    }
+    
+    @AfterMethod
+    public void teardown() {
+        if (brooklynMgmt!=null) Entities.destroyAll(brooklynMgmt);
+    }
+    
+    public void testSimpleYamlDeploy() throws IOException {
+        Reader input = Streams.reader(new 
ResourceUtils(this).getResourceFromUrl("java-web-app-simple.yaml"));
+        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
+
+        try {
+            Assembly assembly = 
at.getInstantiator().newInstance().instantiate(at, platform);
+            log.info("Test - created "+assembly);
+            
+            final Entity app = 
brooklynMgmt.getEntityManager().getEntity(assembly.getId());
+            log.info("App - "+app);
+            Assert.assertEquals(app.getDisplayName(), "sample-single-jboss");
+                        
+            // locations set on AT in this yaml
+            Assert.assertEquals(app.getLocations().size(), 1);
+
+            Set<Task<?>> tasks = 
BrooklynTaskTags.getTasksInEntityContext(brooklynMgmt.getExecutionManager(), 
app);
+            log.info("Waiting on "+tasks.size()+" task(s)");
+            for (Task<?> t: tasks) {
+                t.blockUntilEnded();
+            }
+
+            log.info("App started:");
+            Entities.dumpInfo(app);
+
+            Assert.assertEquals(app.getChildren().size(), 1);
+            
Assert.assertEquals(app.getChildren().iterator().next().getDisplayName(), 
"tomcat1");
+            
Assert.assertEquals(app.getChildren().iterator().next().getLocations().size(), 
1);
+            
+            final String url = 
Asserts.succeedsEventually(MutableMap.of("timeout", Duration.TEN_SECONDS), new 
Callable<String>() {
+                @Override public String call() throws Exception {
+                    String url = 
app.getChildren().iterator().next().getAttribute(JavaWebAppService.ROOT_URL);
+                    return checkNotNull(url, "url of %s", app);
+                }});
+        
+            String site = Asserts.succeedsEventually(MutableMap.of("timeout", 
Duration.TEN_SECONDS), new Callable<String>() {
+                    @Override public String call() throws Exception {
+                        return new 
ResourceUtils(this).getResourceAsString(url);
+                    }});
+            
+            log.info("App URL for "+app+": "+url);
+            Assert.assertTrue(url.contains("928"), "URL should be on port 
9280+ based on config set in yaml, url "+url+", app "+app);
+            Assert.assertTrue(site.toLowerCase().contains("hello"), site);
+            Assert.assertTrue(!platform.assemblies().isEmpty());
+        } catch (Exception e) {
+            log.warn("Unable to instantiate "+at+" (rethrowing): "+e);
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    public void testWithDbDeploy() throws IOException {
+        Reader input = Streams.reader(new 
ResourceUtils(this).getResourceFromUrl("java-web-app-and-db-with-function.yaml"));
+        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
+
+        try {
+            Assembly assembly = 
at.getInstantiator().newInstance().instantiate(at, platform);
+            log.info("Test - created "+assembly);
+            
+            final Entity app = 
brooklynMgmt.getEntityManager().getEntity(assembly.getId());
+            log.info("App - "+app);
+            
+            // locations set on individual services here
+            Assert.assertEquals(app.getLocations().size(), 0);
+            
+            Iterator<ResolvableLink<PlatformComponent>> pcs = 
assembly.getPlatformComponents().links().iterator();
+            PlatformComponent pc1 = pcs.next().resolve();
+            Entity cluster = 
brooklynMgmt.getEntityManager().getEntity(pc1.getId());
+            log.info("pc1 - "+pc1+" - "+cluster);
+            
+            PlatformComponent pc2 = pcs.next().resolve();
+            log.info("pc2 - "+pc2);
+            
+            Set<Task<?>> tasks = 
BrooklynTaskTags.getTasksInEntityContext(brooklynMgmt.getExecutionManager(), 
app);
+            log.info("Waiting on "+tasks.size()+" task(s)");
+            AtomicInteger i = new AtomicInteger(0);
+            for (Task<?> t: tasks) {
+                t.blockUntilEnded();
+                log.info("Completed task #" + i.incrementAndGet());
+            }
+
+            log.info("App started:");
+            Entities.dumpInfo(app);
+
+            EntityTestUtils.assertAttributeEqualsEventually(app, 
Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+            Assert.assertEquals(app.getAttribute(Attributes.SERVICE_UP), 
Boolean.TRUE);
+            
+            final String url = 
Asserts.succeedsEventually(MutableMap.of("timeout", Duration.TEN_SECONDS), new 
Callable<String>() {
+                    @Override public String call() throws Exception {
+                        Entity cluster = Iterables.getOnlyElement( 
Iterables.filter(app.getChildren(), WebAppService.class) );
+                        String url = 
cluster.getAttribute(JavaWebAppService.ROOT_URL);
+                        return checkNotNull(url, "url of %s", cluster);
+                    }});
+            
+            String site = Asserts.succeedsEventually(MutableMap.of("timeout", 
Duration.TEN_SECONDS), new Callable<String>() {
+                    @Override public String call() throws Exception {
+                        return new 
ResourceUtils(this).getResourceAsString(url);
+                    }});
+            
+            log.info("App URL for "+app+": "+url);
+            Assert.assertTrue(url.contains("921"), "URL should be on port 
9280+ based on config set in yaml, url "+url+", app "+app);
+            Assert.assertTrue(site.toLowerCase().contains("hello"), site);
+            Assert.assertTrue(!platform.assemblies().isEmpty());
+            
+            String dbPage = new 
ResourceUtils(this).getResourceAsString(Urls.mergePaths(url, "db.jsp"));
+            Assert.assertTrue(dbPage.contains("Isaac Asimov"), "db.jsp does 
not mention Isaac Asimov, probably the DB did not get initialised:\n"+dbPage);
+        } catch (Exception e) {
+            log.warn("Unable to instantiate "+at+" (rethrowing): "+e);
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    public void testWithPolicyDeploy() {
+        Reader input = Streams.reader(new 
ResourceUtils(this).getResourceFromUrl("java-web-app-and-db-with-policy.yaml"));
+        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
+
+        try {
+            Assembly assembly = 
at.getInstantiator().newInstance().instantiate(at, platform);
+            log.info("Test - created "+assembly);
+            
+            final Entity app = 
brooklynMgmt.getEntityManager().getEntity(assembly.getId());
+            log.info("App - "+app);
+            
+            // locations set on individual services here
+            Assert.assertEquals(app.getLocations().size(), 0);
+            
+            Set<Task<?>> tasks = 
BrooklynTaskTags.getTasksInEntityContext(brooklynMgmt.getExecutionManager(), 
app);
+            log.info("Waiting on "+tasks.size()+" task(s)");
+            for (Task<?> t: tasks) {
+                t.blockUntilEnded();
+            }
+            
+            log.info("App started:");
+            Entities.dumpInfo(app);
+            
+            Iterator<ResolvableLink<PlatformComponent>> pcs = 
assembly.getPlatformComponents().links().iterator();
+            PlatformComponent clusterComponent = null;
+            while (pcs.hasNext() && clusterComponent == null) {
+                PlatformComponent component = pcs.next().resolve();
+                if (component.getName().equals("My Web with Policy"))
+                    clusterComponent = component;
+            }
+            Assert.assertNotNull(clusterComponent, "Database PlatformComponent 
not found");
+            Entity cluster = 
brooklynMgmt.getEntityManager().getEntity(clusterComponent.getId());
+            log.info("pc1 - "+clusterComponent+" - "+cluster);
+            
+            Assert.assertEquals(cluster.getPolicies().size(), 1);
+            Policy policy = cluster.getPolicies().iterator().next();
+            Assert.assertNotNull(policy);
+            Assert.assertTrue(policy instanceof AutoScalerPolicy, 
"policy="+policy);
+            
Assert.assertEquals(policy.getConfig(AutoScalerPolicy.MAX_POOL_SIZE), 
(Integer)5);
+            
Assert.assertEquals(policy.getConfig(AutoScalerPolicy.MIN_POOL_SIZE), 
(Integer)1);
+            Assert.assertEquals(policy.getConfig(AutoScalerPolicy.METRIC), 
DynamicWebAppCluster.REQUESTS_PER_SECOND_IN_WINDOW_PER_NODE);
+            
Assert.assertEquals(policy.getConfig(AutoScalerPolicy.METRIC_LOWER_BOUND), 
(Integer)10);
+            
Assert.assertEquals(policy.getConfig(AutoScalerPolicy.METRIC_UPPER_BOUND), 
(Integer)100);
+            Assert.assertTrue(policy.isRunning());
+
+            EntityTestUtils.assertAttributeEqualsEventually(app, 
Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+            Assert.assertEquals(app.getAttribute(Attributes.SERVICE_UP), 
Boolean.TRUE);
+            
+            final String url = 
Asserts.succeedsEventually(MutableMap.of("timeout", Duration.TEN_SECONDS), new 
Callable<String>() {
+                    @Override public String call() throws Exception {
+                        Entity cluster = Iterables.getOnlyElement( 
Iterables.filter(app.getChildren(), WebAppService.class) );
+                        String url = 
cluster.getAttribute(JavaWebAppService.ROOT_URL);
+                        return checkNotNull(url, "url of %s", cluster);
+                    }});
+            
+            String site = Asserts.succeedsEventually(MutableMap.of("timeout", 
Duration.TEN_SECONDS), new Callable<String>() {
+                    @Override public String call() throws Exception {
+                        return new 
ResourceUtils(this).getResourceAsString(url);
+                    }});
+            
+            log.info("App URL for "+app+": "+url);
+            Assert.assertTrue(url.contains("921"), "URL should be on port 
9280+ based on config set in yaml, url "+url+", app "+app);
+            Assert.assertTrue(site.toLowerCase().contains("hello"), site);
+            Assert.assertTrue(!platform.assemblies().isEmpty());
+            
+            String dbPage = new 
ResourceUtils(this).getResourceAsString(Urls.mergePaths(url, "db.jsp"));
+            Assert.assertTrue(dbPage.contains("Isaac Asimov"), "db.jsp does 
not mention Isaac Asimov, probably the DB did not get initialised:\n"+dbPage);
+        } catch (Exception e) {
+            log.warn("Unable to instantiate "+at+" (rethrowing): "+e);
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsMatchingTest.java
----------------------------------------------------------------------
diff --git 
a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsMatchingTest.java
 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsMatchingTest.java
new file mode 100644
index 0000000..048b8f8
--- /dev/null
+++ 
b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsMatchingTest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn;
+
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.collection.ResolvableLink;
+import io.brooklyn.camp.spi.pdp.DeploymentPlan;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.management.ManagementContext;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.task.DeferredSupplier;
+
+@Test
+public class JavaWebAppsMatchingTest {
+
+    private static final Logger log = 
LoggerFactory.getLogger(JavaWebAppsMatchingTest.class);
+    
+    private ManagementContext brooklynMgmt;
+    private BrooklynCampPlatform platform;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setup() {
+        brooklynMgmt = new LocalManagementContextForTests();
+        platform = new BrooklynCampPlatform(
+              PlatformRootSummary.builder().name("Brooklyn CAMP 
Platform").build(),
+              brooklynMgmt);
+    }
+    
+    // FIXME all commented-out lines require camp server
+    
+    @AfterMethod(alwaysRun=true)
+    public void teardown() {
+        if (brooklynMgmt!=null) Entities.destroyAll(brooklynMgmt);
+    }
+    
+    public void testSimpleYamlParse() throws IOException {
+        Reader input = Streams.reader(new 
ResourceUtils(this).getResourceFromUrl("java-web-app-simple.yaml"));
+        DeploymentPlan plan = platform.pdp().parseDeploymentPlan(input);
+        log.info("DP is:\n"+plan.toString());
+        Assert.assertEquals(plan.getServices().size(), 1);
+        Assert.assertEquals(plan.getName(), "sample-single-jboss");
+    }
+    
+    public void testSimpleYamlMatch() throws IOException {
+        Reader input = Streams.reader(new 
ResourceUtils(this).getResourceFromUrl("java-web-app-simple.yaml"));
+        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
+        
+        Assert.assertEquals(at.getName(), "sample-single-jboss");
+    }
+
+    public void testExampleFunctionsYamlMatch() throws IOException {
+        Reader input = Streams.reader(new 
ResourceUtils(this).getResourceFromUrl("example-with-function.yaml"));
+        
+        DeploymentPlan plan = platform.pdp().parseDeploymentPlan(input);
+        log.info("DP is:\n"+plan.toString());
+        Map<?,?> cfg1 = (Map<?, ?>) 
plan.getServices().get(0).getCustomAttributes().get(BrooklynCampReservedKeys.BROOKLYN_CONFIG);
+        Map<?,?> cfg = MutableMap.copyOf(cfg1);
+        
+        Assert.assertEquals(cfg.remove("literalValue1"), "$brooklyn: is a fun 
place");
+        Assert.assertEquals(cfg.remove("literalValue2"), "$brooklyn: is a fun 
place");
+        Assert.assertEquals(cfg.remove("literalValue3"), "$brooklyn: is a fun 
place");
+        Assert.assertEquals(cfg.remove("literalValue4"), "$brooklyn: is a fun 
place");
+        Assert.assertEquals(cfg.remove("$brooklyn:1"), "key to the city");
+        Assert.assertTrue(cfg.isEmpty(), ""+cfg);
+
+        Assert.assertEquals(plan.getName(), "example-with-function");
+        Assert.assertEquals(plan.getCustomAttributes().get("location"), 
"localhost");
+        
+        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(plan);
+        
+        Assert.assertEquals(at.getName(), "example-with-function");
+        Assert.assertEquals(at.getCustomAttributes().get("location"), 
"localhost");
+        
+        PlatformComponentTemplate pct = 
at.getPlatformComponentTemplates().links().iterator().next().resolve();
+        Object cfg2 = 
pct.getCustomAttributes().get(BrooklynCampReservedKeys.BROOKLYN_CONFIG);
+        Assert.assertEquals(cfg2, cfg1);
+    }
+
+    public void testJavaAndDbWithFunctionYamlMatch() throws IOException {
+        Reader input = Streams.reader(new 
ResourceUtils(this).getResourceFromUrl("java-web-app-and-db-with-function.yaml"));
+        assertWebDbWithFunctionValid(input);
+    }
+    
+    public void testJavaAndDbWithFunctionYamlMatch2() throws IOException {
+        Reader input = Streams.reader(new 
ResourceUtils(this).getResourceFromUrl("java-web-app-and-db-with-function-2.yaml"));
+        assertWebDbWithFunctionValid(input);
+    }
+    
+    protected void assertWebDbWithFunctionValid(Reader input) { 
+        DeploymentPlan plan = platform.pdp().parseDeploymentPlan(input);
+        log.info("DP is:\n"+plan.toString());
+        
+        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(plan);
+        
+        Assert.assertEquals(at.getName(), "java-cluster-db-example");
+
+        Iterator<ResolvableLink<PlatformComponentTemplate>> pcti = 
at.getPlatformComponentTemplates().links().iterator();
+        PlatformComponentTemplate pct1 = pcti.next().resolve(); 
+
+        PlatformComponentTemplate pct2 = pcti.next().resolve(); 
+
+        Map<?,?> config = (Map<?, ?>) 
pct1.getCustomAttributes().get(BrooklynCampReservedKeys.BROOKLYN_CONFIG);
+        Map<?,?> javaSysProps = (Map<?, ?>) config.get("java.sysprops");
+        Object dbUrl = javaSysProps.get("brooklyn.example.db.url");
+        Assert.assertTrue(dbUrl instanceof DeferredSupplier<?>, "url is: 
"+dbUrl);
+        
+        Assert.assertEquals(pct2.getCustomAttributes().get("planId"), "db");
+    }
+
+}


Reply via email to