Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master ddc3dd9ff -> f1d90c638


BROOKLYN-184: Entities auto-managed

- Deprecates Entities.manage
- Deprecates ApplicationBuilder
- Deprecates BrooklynLauncher.application(Application)
- BrooklynRestResourceUtils uses EntitySpec (with DslComponent for
  soleChild ref)


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

Branch: refs/heads/master
Commit: 5f2a296b572fd858766031a386682806ad8edead
Parents: 9402f85
Author: Aled Sage <[email protected]>
Authored: Thu Oct 15 16:34:09 2015 +0200
Committer: Aled Sage <[email protected]>
Committed: Thu Oct 15 21:19:34 2015 +0100

----------------------------------------------------------------------
 .../brooklyn/core/entity/AbstractEntity.java    |   7 +-
 .../apache/brooklyn/core/entity/Entities.java   |  41 ++-
 .../core/entity/factory/ApplicationBuilder.java |   6 +-
 .../core/mgmt/EntityManagementUtils.java        |   2 -
 .../core/mgmt/internal/LocalEntityManager.java  |   6 +-
 .../entity/group/AbstractGroupImpl.java         |   1 -
 .../entity/group/DynamicClusterImpl.java        |   5 +-
 .../entity/group/DynamicFabricImpl.java         |   4 +
 .../entity/group/DynamicMultiGroupImpl.java     |   1 -
 .../core/entity/EntityAutomanagedTest.java      | 329 +++++++++++++++++++
 .../BrooklynNodeUpgradeEffectorBody.java        |   2 +-
 .../messaging/activemq/ActiveMQBrokerImpl.java  |   2 -
 .../messaging/kafka/KafkaClusterImpl.java       |   2 -
 .../entity/messaging/qpid/QpidBrokerImpl.java   |   2 -
 .../messaging/rabbit/RabbitBrokerImpl.java      |   1 -
 .../ControlledDynamicWebAppClusterImpl.java     |   7 +-
 .../BrooklynAssemblyTemplateInstantiator.java   |   3 +-
 .../brooklyn/launcher/BrooklynLauncher.java     |   4 +
 .../rest/util/BrooklynRestResourceUtils.java    |  20 +-
 19 files changed, 411 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java 
b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index 49afc60..65ec72f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -662,13 +662,16 @@ public abstract class AbstractEntity extends 
AbstractBrooklynObject implements E
     @Override
     public <T extends Entity> T addChild(EntitySpec<T> spec) {
         if (spec.getParent()==null) {
-            spec = EntitySpec.create(spec).parent(this);
+            spec = EntitySpec.create(spec).parent(getProxyIfAvailable());
         }
         if (!this.equals(spec.getParent())) {
             throw new IllegalArgumentException("Attempt to create child of 
"+this+" with entity spec "+spec+
                 " failed because spec has different parent: 
"+spec.getParent());
         }
-        return addChild(getEntityManager().createEntity(spec));
+        
+        // The spec now includes this as the parent, so no need to call 
addChild; 
+        // that is done by InternalEntityFactory.
+        return getEntityManager().createEntity(spec);
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java 
b/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java
index a9616d8..0120fd7 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java
@@ -49,6 +49,7 @@ import org.apache.brooklyn.api.entity.drivers.EntityDriver;
 import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolver;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.mgmt.EntityManager;
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.mgmt.LocationManager;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
@@ -695,7 +696,7 @@ public class Entities {
      * (after the application is started) */
     public static void start(Entity e, Collection<? extends Location> 
locations) {
         if (!isManaged(e) && !manage(e)) {
-            log.warn("Using discouraged mechanism to start management -- 
Entities.start(Application, Locations) -- caller should create and use the 
preferred management context");
+            log.warn("Using deprecated discouraged mechanism to start 
management -- Entities.start(Application, Locations) -- caller should create 
and use the preferred management context");
             startManagement(e);
         }
         if (e instanceof Startable) Entities.invokeEffector((EntityLocal)e, e, 
Startable.START,
@@ -871,8 +872,18 @@ public class Entities {
      *
      * @throws IllegalStateException if {@literal e} is an {@link Application}.
      * @see #startManagement(Entity)
+     * 
+     * @deprecated since 0.9.0; entities are automatically managed when 
created via {@link Entity#addChild(EntitySpec)},
+     *             or with {@link EntityManager#createEntity(EntitySpec)} (it 
is strongly encouraged to include the parent
+     *             if using the latter for anything but a top-level app).
      */
+    @Deprecated
     public static boolean manage(Entity e) {
+        if (Entities.isManaged(e)) {
+            return true; // no-op
+        }
+        
+        log.warn("Deprecated use of Entities.manage(Entity), for unmanaged 
entity "+e);
         Entity o = e.getParent();
         Entity eum = e; // Highest unmanaged ancestor
         if (o==null) throw new IllegalArgumentException("Can't manage "+e+" 
because it is an orphan");
@@ -901,9 +912,15 @@ public class Entities {
      * <p>
      * <b>NOTE</b> This method may change, but is provided as a stop-gap to 
prevent ad-hoc things
      * being done in the code which are even more likely to break!
+     * 
+     * @deprecated since 0.9.0; entities are automatically managed when 
created via {@link Entity#addChild(EntitySpec)},
+     *             or with {@link EntityManager#createEntity(EntitySpec)}.
      */
+    @Deprecated
     @Beta
     public static ManagementContext startManagement(Entity e) {
+        log.warn("Deprecated use of Entities.startManagement(Entity), for 
entity "+e);
+        
         Entity o = e;
         Entity eum = e; // Highest unmanaged ancestor
         while (o.getParent()!=null) {
@@ -929,11 +946,24 @@ public class Entities {
      * Starts managing the given (unmanaged) app, using the given management 
context.
      *
      * @see #startManagement(Entity)
+     * 
+     * @deprecated since 0.9.0; entities are automatically managed when 
created with 
+     *             {@link EntityManager#createEntity(EntitySpec)}. For 
top-level apps, use code like
+     *             {@code 
managementContext.getEntityManager().createEntity(EntitySpec.create(...))}.
      */
+    @Deprecated
     public static ManagementContext startManagement(Application app, 
ManagementContext mgmt) {
+        log.warn("Deprecated use of Entities.startManagement(Application, 
ManagementContext), for app "+app);
+        
         if (isManaged(app)) {
-            throw new IllegalStateException("Application "+app+" is already 
managed, so can't set brooklyn properties");
+            if (app.getManagementContext() == mgmt) {
+                // no-op; app was presumably auto-managed
+                return mgmt;
+            } else {
+                throw new IllegalStateException("Application "+app+" is 
already managed by "+app.getManagementContext()+", so cannot be managed by 
"+mgmt);
+            }
         }
+
         mgmt.getEntityManager().manage(app);
         return mgmt;
     }
@@ -943,8 +973,15 @@ public class Entities {
      * management context.
      *
      * @see #startManagement(Entity)
+     * 
+     * @deprecated since 0.9.0; entities are automatically managed when 
created via {@link Entity#addChild(EntitySpec)},
+     *             or with {@link EntityManager#createEntity(EntitySpec)}. For 
top-level apps, use code like
+     *             {@code 
managementContext.getEntityManager().createEntity(EntitySpec.create(...))}.
      */
+    @Deprecated
     public static ManagementContext startManagement(Application app, 
BrooklynProperties props) {
+        log.warn("Deprecated use of Entities.startManagement(Application, 
BrooklynProperties), for app "+app);
+        
         if (isManaged(app)) {
             throw new IllegalStateException("Application "+app+" is already 
managed, so can't set brooklyn properties");
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/core/src/main/java/org/apache/brooklyn/core/entity/factory/ApplicationBuilder.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/entity/factory/ApplicationBuilder.java
 
b/core/src/main/java/org/apache/brooklyn/core/entity/factory/ApplicationBuilder.java
index 7e00305..2d3ee08 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/entity/factory/ApplicationBuilder.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/entity/factory/ApplicationBuilder.java
@@ -63,7 +63,11 @@ import com.google.common.annotations.Beta;
  * </pre>
  * 
  * @author aled
+ * 
+ * @deprecated since 0.9.0; use {@link EntitySpec} and {@link 
EntityManager#createEntity(EntitySpec)}, having 
+ *             added the children to the spec etc.
  */
+@Deprecated
 @Beta
 public abstract class ApplicationBuilder {
 
@@ -213,8 +217,8 @@ public abstract class ApplicationBuilder {
         }
         try {
             checkNotManaged();
-            this.app = 
managementContext.getEntityManager().createEntity(appSpec);
             this.managementContext = managementContext;
+            this.app = 
managementContext.getEntityManager().createEntity(appSpec);
             doBuild();
             Entities.startManagement(app, managementContext);
             managed = true;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
index 5536a1e..889f74f 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
@@ -79,7 +79,6 @@ public class EntityManagementUtils {
     /** creates an application from the given app spec, managed by the given 
management context */
     public static <T extends Application> T createUnstarted(ManagementContext 
mgmt, EntitySpec<T> spec) {
         T app = mgmt.getEntityManager().createEntity(spec);
-        Entities.startManagement(app, mgmt);
         return app;
     }
 
@@ -188,7 +187,6 @@ public class EntityManagementUtils {
         final List<Entity> children = MutableList.of();
         for (EntitySpec<?> spec: specs) {
             Entity child = (Entity)parent.addChild(spec);
-            Entities.manage(child);
             children.add(child);
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalEntityManager.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalEntityManager.java
 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalEntityManager.java
index 6c9022d..7d3b705 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalEntityManager.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalEntityManager.java
@@ -144,7 +144,11 @@ public class LocalEntityManager implements 
EntityManagerInternal {
         try {
             T entity = entityFactory.createEntity(spec);
             Entity proxy = ((AbstractEntity)entity).getProxy();
-            return (T) checkNotNull(proxy, "proxy for entity %s, spec %s", 
entity, spec);
+            checkNotNull(proxy, "proxy for entity %s, spec %s", entity, spec);
+            
+            manage(entity);
+            
+            return (T) proxy;
         } catch (Throwable e) {
             log.warn("Failed to create entity using spec "+spec+" 
(rethrowing)", e);
             throw Exceptions.propagate(e);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/core/src/main/java/org/apache/brooklyn/entity/group/AbstractGroupImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/entity/group/AbstractGroupImpl.java 
b/core/src/main/java/org/apache/brooklyn/entity/group/AbstractGroupImpl.java
index 7ece9bf..8108c9f 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/group/AbstractGroupImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/AbstractGroupImpl.java
@@ -152,7 +152,6 @@ public abstract class AbstractGroupImpl extends 
AbstractEntity implements Abstra
                         DelegateEntity child = 
addChild(EntitySpec.create(DelegateEntity.class)
                                 .configure(DelegateEntity.DELEGATE_ENTITY, 
member)
                                 .displayName(String.format(nameFormat, 
member.getDisplayName())));
-                        Entities.manage(child);
                     }
                 }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicClusterImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicClusterImpl.java 
b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicClusterImpl.java
index 3fcebdf..004a537 100644
--- 
a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicClusterImpl.java
+++ 
b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicClusterImpl.java
@@ -293,7 +293,6 @@ public class DynamicClusterImpl extends AbstractGroupImpl 
implements DynamicClus
             QuarantineGroup quarantineGroup = getAttribute(QUARANTINE_GROUP);
             if (quarantineGroup==null || !Entities.isManaged(quarantineGroup)) 
{
                 quarantineGroup = 
addChild(EntitySpec.create(QuarantineGroup.class).displayName("quarantine"));
-                Entities.manage(quarantineGroup);
                 sensors().set(QUARANTINE_GROUP, quarantineGroup);
             }
         }
@@ -770,12 +769,16 @@ public class DynamicClusterImpl extends AbstractGroupImpl 
implements DynamicClus
             LOG.debug("Creating and adding a node to cluster {}({}) with 
properties {}", new Object[] { this, getId(), createFlags });
         }
 
+        // TODO should refactor to have a createNodeSpec; and spec should 
support initial sensor values 
         Entity entity = createNode(loc, createFlags);
 
         entity.sensors().set(CLUSTER_MEMBER, true);
         entity.sensors().set(CLUSTER, this);
 
+        // Continue to call manage(), because some uses of NodeFactory (in 
tests) still instantiate the
+        // entity via its constructor
         Entities.manage(entity);
+        
         addMember(entity);
         return entity;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabricImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabricImpl.java 
b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabricImpl.java
index 23c05b5..67c4c79 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabricImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabricImpl.java
@@ -247,7 +247,11 @@ public class DynamicFabricImpl extends AbstractGroupImpl 
implements DynamicFabri
                 ((EntityLocal)entity).setDisplayName(entity.getDisplayName() 
+" ("+locationName+")");
         }
         if (entity.getParent()==null) entity.setParent(this);
+        
+        // Continue to call manage(), because some uses of NodeFactory (in 
tests) still instantiate the
+        // entity via its constructor
         Entities.manage(entity);
+        
         addMember(entity);
         
         return entity;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicMultiGroupImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicMultiGroupImpl.java
 
b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicMultiGroupImpl.java
index b6f5d55..5c507a3 100644
--- 
a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicMultiGroupImpl.java
+++ 
b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicMultiGroupImpl.java
@@ -181,7 +181,6 @@ public class DynamicMultiGroupImpl extends DynamicGroupImpl 
implements DynamicMu
                 BasicGroup bucket = buckets.get(name);
                 if (bucket == null) {
                     bucket = 
addChild(EntitySpec.create(bucketSpec).displayName(name));
-                    Entities.manage(bucket);
                     buckets.put(name, bucket);
                 }
                 bucket.setMembers(entityMapping.get(name));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/core/src/test/java/org/apache/brooklyn/core/entity/EntityAutomanagedTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/core/entity/EntityAutomanagedTest.java 
b/core/src/test/java/org/apache/brooklyn/core/entity/EntityAutomanagedTest.java
new file mode 100644
index 0000000..a940a11
--- /dev/null
+++ 
b/core/src/test/java/org/apache/brooklyn/core/entity/EntityAutomanagedTest.java
@@ -0,0 +1,329 @@
+/*
+ * 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.core.entity;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import 
org.apache.brooklyn.core.entity.EntityAutomanagedTest.RecordingCollectionChangeListener.ChangeEvent;
+import 
org.apache.brooklyn.core.entity.EntityAutomanagedTest.RecordingCollectionChangeListener.ChangeType;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.test.Asserts;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+public class EntityAutomanagedTest extends BrooklynAppUnitTestSupport {
+
+    // TODO Want to use a RecordingCollectionChangeListener to ensure on 
auto-manage
+    // we are notified of the entity being added etc, but compilation fails on 
command line,
+    // running `mvn clean install` (using 1.7.0_65, build 24.65-b04)!
+    //  - when written "properly", it complains about the @Override annotation 
on onItemAdded(Entity item)
+    //  - when that is removed, it complains about the call to 
mgmt.addEntitySetListener not being compatible
+    //  - when try stripping out generics, it complains that "cannot find 
symbol" for the declaration of this class
+    //
+    // In your IDE (at least in Eclipse), you can uncomment the bits beside 
the TODO and run it 
+    // with those insertions!
+    
+    protected RecordingCollectionChangeListener listener;
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        super.setUp();
+        listener = new RecordingCollectionChangeListener();
+        
+        // TODO Compiler problems - see comment at top of class
+        //mgmt.addEntitySetListener((CollectionChangeListener)listener);
+    }
+
+    
+    //////////////////////////////////////
+    // Variants of addChild(EntitySpec) //
+    //////////////////////////////////////
+    
+    @Test
+    public void testAddedChildSpec() throws Exception {
+        TestEntity e = app.addChild(EntitySpec.create(TestEntity.class));
+        assertTrue(Entities.isManaged(e));
+        listener.assertEventsEqualsEventually(ImmutableList.of(new 
ChangeEvent(ChangeType.ADDED, e)));
+    }
+
+    @Test
+    public void testAddedChildHierarchySpec() throws Exception {
+        TestEntity e = app.addChild(EntitySpec.create(TestEntity.class)
+                .child(EntitySpec.create(TestEntity.class)
+                        .child(EntitySpec.create(TestEntity.class))));
+        TestEntity e2 = (TestEntity) Iterables.getOnlyElement(e.getChildren());
+        TestEntity e3 = (TestEntity) 
Iterables.getOnlyElement(e2.getChildren());
+        
+        assertTrue(Entities.isManaged(e));
+        assertTrue(Entities.isManaged(e2));
+        assertTrue(Entities.isManaged(e3));
+        assertEquals(e.getParent(), app);
+        assertEquals(e2.getParent(), e);
+        assertEquals(e3.getParent(), e2);
+        listener.assertEventsEqualsEventually(ImmutableList.of(
+                new ChangeEvent(ChangeType.ADDED, e),
+                new ChangeEvent(ChangeType.ADDED, e2),
+                new ChangeEvent(ChangeType.ADDED, e3)));
+    }
+
+    @Test
+    public void testNewEntityWithParent() throws Exception {
+        TestEntity e = app.addChild(EntitySpec.create(TestEntity.class)
+                .parent(app));
+        assertTrue(Entities.isManaged(e));
+        assertEquals(e.getParent(), app);
+        listener.assertEventsEqualsEventually(ImmutableList.of(new 
ChangeEvent(ChangeType.ADDED, e)));
+    }
+
+    @Test
+    public void testNewEntityHierarchyWithParent() throws Exception {
+        TestEntity e = 
mgmt.getEntityManager().createEntity(EntitySpec.create(TestEntity.class)
+                .child(EntitySpec.create(TestEntity.class)
+                        .child(EntitySpec.create(TestEntity.class)))
+                .parent(app));
+        TestEntity e2 = (TestEntity) Iterables.getOnlyElement(e.getChildren());
+        TestEntity e3 = (TestEntity) 
Iterables.getOnlyElement(e2.getChildren());
+        
+        assertTrue(Entities.isManaged(e));
+        assertTrue(Entities.isManaged(e2));
+        assertTrue(Entities.isManaged(e3));
+        assertEquals(e.getParent(), app);
+        assertEquals(e2.getParent(), e);
+        assertEquals(e3.getParent(), e2);
+        listener.assertEventsEqualsEventually(ImmutableList.of(
+                new ChangeEvent(ChangeType.ADDED, e),
+                new ChangeEvent(ChangeType.ADDED, e2),
+                new ChangeEvent(ChangeType.ADDED, e3)));
+    }
+    
+    @Test
+    public void testAddingSameChildAgainIsNoop() throws Exception {
+        TestEntity e = app.addChild(EntitySpec.create(TestEntity.class)
+                .parent(app));
+        
+        app.addChild(e);
+        assertTrue(Entities.isManaged(e));
+        assertEquals(e.getParent(), app);
+        listener.assertEventsEqualsEventually(ImmutableList.of(new 
ChangeEvent(ChangeType.ADDED, e)));
+    }
+    
+    
+    //////////////////////////////////////
+    // Variants of createEntity for app //
+    //////////////////////////////////////
+
+    @Test
+    public void testNewApp() throws Exception {
+        TestApplication app2 = 
mgmt.getEntityManager().createEntity(EntitySpec.create(TestApplication.class));
+        assertTrue(Entities.isManaged(app2));
+        
+        assertTrue(mgmt.getApplications().contains(app2), "app="+app2+"; 
apps="+mgmt.getApplications());
+        app.addChild(app2);
+        assertTrue(Entities.isManaged(app2));
+        listener.assertEventsEqualsEventually(ImmutableList.of(new 
ChangeEvent(ChangeType.ADDED, app2)));
+    }
+    
+    
+    ////////////////////////////////////////////////////////////////
+    // Variants of Entities.startManagement and Entities.manage() //
+    ////////////////////////////////////////////////////////////////
+
+    @Test
+    public void testManageIsNoop() throws Exception {
+        TestEntity child = 
mgmt.getEntityManager().createEntity(EntitySpec.create(TestEntity.class)
+                .parent(app));
+        
+        Entities.manage(child);
+        assertTrue(Entities.isManaged(child));
+        listener.assertEventsEqualsEventually(ImmutableList.of(new 
ChangeEvent(ChangeType.ADDED, child)));
+    }
+    
+    @Test
+    public void testStartManagementIsNoop() throws Exception {
+        TestApplication app2 = 
mgmt.getEntityManager().createEntity(EntitySpec.create(TestApplication.class));
+        assertTrue(Entities.isManaged(app2));
+        
+        Entities.startManagement(app2, mgmt);
+        assertTrue(Entities.isManaged(app2));
+        listener.assertEventsEqualsEventually(ImmutableList.of(new 
ChangeEvent(ChangeType.ADDED, app2)));
+    }
+    
+    @Test
+    public void testStartManagementOfEntityIsNoop() throws Exception {
+        Entity app2 = 
mgmt.getEntityManager().createEntity(EntitySpec.create(TestApplication.class));
+        assertTrue(Entities.isManaged(app2));
+        
+        Entities.startManagement(app2);
+        assertTrue(Entities.isManaged(app2));
+        listener.assertEventsEqualsEventually(ImmutableList.of(new 
ChangeEvent(ChangeType.ADDED, app2)));
+    }
+    
+    @Test
+    public void testStartManagementFailsIfAppDeleted() throws Exception {
+        TestApplication app2 = 
mgmt.getEntityManager().createEntity(EntitySpec.create(TestApplication.class));
+        Entities.unmanage(app2);
+        
+        try {
+            Entities.startManagement(app2, mgmt);
+            fail("Managed deleted app "+app2+" in "+mgmt);
+        } catch (IllegalStateException e) {
+            if (!(e.toString().contains("No concrete entity known"))) throw e;
+        }
+    }
+
+    @Test
+    public void testManageFailsIfEntityDeleted() throws Exception {
+        TestEntity child = 
mgmt.getEntityManager().createEntity(EntitySpec.create(TestEntity.class)
+                .parent(app));
+        Entities.unmanage(child);
+        
+        try {
+            Entities.manage(child);
+            fail("Managed deleted entity "+child+" in "+mgmt);
+        } catch (IllegalStateException e) {
+            if (!(e.toString().contains("No concrete entity known"))) throw e;
+        }
+    }
+    
+
+    ///////////////////////////////////////////
+    // Variants of createEntity for non-apps //
+    ///////////////////////////////////////////
+
+    // TODO Controversial? Should it be based on reachability from parent? Can 
entities be (temporarily) top-level?
+    // But management model is simpler if it becomes managed immediately.
+    @Test
+    public void testNewOrphanedEntityIsManaged() throws Exception {
+        TestEntity e = 
mgmt.getEntityManager().createEntity(EntitySpec.create(TestEntity.class));
+        assertTrue(Entities.isManaged(e));
+        listener.assertEventsEqualsEventually(ImmutableList.of(new 
ChangeEvent(ChangeType.ADDED, e)));
+        
+        // Check that orphaned entity doesn't interfere with getApplications
+        Asserts.assertEqualsIgnoringOrder(mgmt.getApplications(), 
ImmutableList.of(app)); 
+    }
+
+    @Test
+    public void testOrphanedEntityHierarchyIsManaged() throws Exception {
+        TestEntity e = 
mgmt.getEntityManager().createEntity(EntitySpec.create(TestEntity.class)
+                .child(EntitySpec.create(TestEntity.class)
+                        .child(EntitySpec.create(TestEntity.class))));
+        TestEntity e2 = (TestEntity) Iterables.getOnlyElement(e.getChildren());
+        TestEntity e3 = (TestEntity) 
Iterables.getOnlyElement(e2.getChildren());
+        
+        assertTrue(Entities.isManaged(e));
+        assertTrue(Entities.isManaged(e2));
+        assertTrue(Entities.isManaged(e3));
+        assertEquals(e.getParent(), null);
+        assertEquals(e2.getParent(), e);
+        assertEquals(e3.getParent(), e2);
+        listener.assertEventsEqualsEventually(ImmutableList.of(
+                new ChangeEvent(ChangeType.ADDED, e),
+                new ChangeEvent(ChangeType.ADDED, e2),
+                new ChangeEvent(ChangeType.ADDED, e3)));
+    }
+    
+    @Test
+    public void testNewOrphanedEntityCanBeAddedToChild() throws Exception {
+        TestEntity e = 
mgmt.getEntityManager().createEntity(EntitySpec.create(TestEntity.class));
+        
+        app.addChild(e);
+        assertTrue(Entities.isManaged(e));
+        listener.assertEventsEqualsEventually(ImmutableList.of(new 
ChangeEvent(ChangeType.ADDED, e)));
+    }
+
+    // TODO Compiler problems - see comment at top of class
+    public static class RecordingCollectionChangeListener { // FIXME 
implements CollectionChangeListener<Entity> {
+        public enum ChangeType {
+            ADDED, REMOVED;
+        }
+        public static class ChangeEvent {
+            public final ChangeType type;
+            public final Entity entity;
+            
+            ChangeEvent(ChangeType type, Entity entity) {
+                this.type = checkNotNull(type, "type");
+                this.entity = checkNotNull(entity, "entity");
+            }
+            
+            @Override
+            public int hashCode() {
+                return Objects.hashCode(type, entity);
+            }
+            
+            @Override
+            public boolean equals(Object obj) {
+                if (!(obj instanceof ChangeEvent)) return false;
+                ChangeEvent o = (ChangeEvent) obj;
+                return type.equals(o.type) && entity.equals(o.entity);
+            }
+            
+            @Override
+            public String toString() {
+                return Objects.toStringHelper(this).add("type", 
type).add("entity", entity).toString();
+            }
+        }
+        
+        private final List<ChangeEvent> events = 
Lists.newCopyOnWriteArrayList();
+        private final Set<Entity> items = Sets.newConcurrentHashSet();
+
+        public void assertEventsEqualsEventually(final Iterable<? extends 
ChangeEvent> expected) {
+            // TODO Compiler problems - see comment at top of class
+//            Asserts.succeedsEventually(new Runnable() {
+//                public void run() {
+//                    assertEquals(events, ImmutableList.copyOf(expected));
+//                }});
+        }
+
+        public void assertItemsEqualsEventually(final Iterable<? extends 
Entity> expected) {
+            // TODO Compiler problems - see comment at top of class
+//            Asserts.succeedsEventually(new Runnable() {
+//                public void run() {
+//                    assertEquals(items, ImmutableSet.copyOf(expected));
+//                }});
+        }
+
+        // TODO Want to include @Override; compiler problems - see comment at 
top of class
+        public void onItemAdded(Entity item) {
+            items.add(item);
+            events.add(new ChangeEvent(ChangeType.ADDED, item));
+        }
+
+        // TODO Want to include @Override; compiler problems - see comment at 
top of class
+        public void onItemRemoved(Entity item) {
+            items.remove(item);
+            events.add(new ChangeEvent(ChangeType.REMOVED, item));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/software/base/src/main/java/org/apache/brooklyn/entity/brooklynnode/effector/BrooklynNodeUpgradeEffectorBody.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/main/java/org/apache/brooklyn/entity/brooklynnode/effector/BrooklynNodeUpgradeEffectorBody.java
 
b/software/base/src/main/java/org/apache/brooklyn/entity/brooklynnode/effector/BrooklynNodeUpgradeEffectorBody.java
index 021da69..4e75121 100644
--- 
a/software/base/src/main/java/org/apache/brooklyn/entity/brooklynnode/effector/BrooklynNodeUpgradeEffectorBody.java
+++ 
b/software/base/src/main/java/org/apache/brooklyn/entity/brooklynnode/effector/BrooklynNodeUpgradeEffectorBody.java
@@ -174,13 +174,13 @@ public class BrooklynNodeUpgradeEffectorBody extends 
EffectorBody<Void> {
 
         //force this to start as hot-standby
         // TODO alternatively could use REST API as in 
BrooklynClusterUpgradeEffectorBody
+        // TODO Want better way to append to the config (so can do it all in 
the spec)
         String launchParameters = 
dryRunChild.getConfig(BrooklynNode.EXTRA_LAUNCH_PARAMETERS);
         if (Strings.isBlank(launchParameters)) launchParameters = "";
         else launchParameters += " ";
         launchParameters += "--highAvailability 
"+HighAvailabilityMode.HOT_STANDBY;
         
((EntityInternal)dryRunChild).config().set(BrooklynNode.EXTRA_LAUNCH_PARAMETERS,
 launchParameters);
 
-        Entities.manage(dryRunChild);
         final String dryRunNodeUid = dryRunChild.getId();
         ((EntityInternal)dryRunChild).setDisplayName("Dry-Run Upgraded 
Brooklyn Node ("+dryRunNodeUid+")");
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/activemq/ActiveMQBrokerImpl.java
----------------------------------------------------------------------
diff --git 
a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/activemq/ActiveMQBrokerImpl.java
 
b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/activemq/ActiveMQBrokerImpl.java
index 22719d0..6954e81 100644
--- 
a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/activemq/ActiveMQBrokerImpl.java
+++ 
b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/activemq/ActiveMQBrokerImpl.java
@@ -74,7 +74,6 @@ public class ActiveMQBrokerImpl extends 
JMSBrokerImpl<ActiveMQQueue, ActiveMQTop
     @Override
     public ActiveMQQueue createQueue(Map properties) {
         ActiveMQQueue result = 
addChild(EntitySpec.create(ActiveMQQueue.class).configure(properties));
-        Entities.manage(result);
         result.create();
         return result;
     }
@@ -82,7 +81,6 @@ public class ActiveMQBrokerImpl extends 
JMSBrokerImpl<ActiveMQQueue, ActiveMQTop
     @Override
     public ActiveMQTopic createTopic(Map properties) {
         ActiveMQTopic result = 
addChild(EntitySpec.create(ActiveMQTopic.class).configure(properties));
-        Entities.manage(result);
         result.create();
         return result;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/kafka/KafkaClusterImpl.java
----------------------------------------------------------------------
diff --git 
a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/kafka/KafkaClusterImpl.java
 
b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/kafka/KafkaClusterImpl.java
index cb4481c..8f4e7fb 100644
--- 
a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/kafka/KafkaClusterImpl.java
+++ 
b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/kafka/KafkaClusterImpl.java
@@ -72,7 +72,6 @@ public class KafkaClusterImpl extends AbstractEntity 
implements KafkaCluster {
                 log.debug("creating zookeeper using custom spec for {}", this);
             }
             zookeeper = addChild(zookeeperSpec);
-            if (Entities.isManaged(this)) Entities.manage(zookeeper);
             sensors().set(ZOOKEEPER, zookeeper);
         }
 
@@ -87,7 +86,6 @@ public class KafkaClusterImpl extends AbstractEntity 
implements KafkaCluster {
         // We add the zookeeper configuration to the KafkaBroker specification 
here
         DynamicCluster cluster = 
addChild(EntitySpec.create(DynamicCluster.class)
                 .configure("memberSpec", 
EntitySpec.create(brokerSpec).configure(KafkaBroker.ZOOKEEPER, zookeeper)));
-        if (Entities.isManaged(this)) Entities.manage(cluster);
         sensors().set(CLUSTER, cluster);
         
         connectSensors();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/qpid/QpidBrokerImpl.java
----------------------------------------------------------------------
diff --git 
a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/qpid/QpidBrokerImpl.java
 
b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/qpid/QpidBrokerImpl.java
index 5b2529c..67b132c 100644
--- 
a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/qpid/QpidBrokerImpl.java
+++ 
b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/qpid/QpidBrokerImpl.java
@@ -90,14 +90,12 @@ public class QpidBrokerImpl extends 
JMSBrokerImpl<QpidQueue, QpidTopic> implemen
     
     public QpidQueue createQueue(Map properties) {
         QpidQueue result = 
addChild(EntitySpec.create(QpidQueue.class).configure(properties));
-        Entities.manage(result);
         result.create();
         return result;
     }
 
     public QpidTopic createTopic(Map properties) {
         QpidTopic result = 
addChild(EntitySpec.create(QpidTopic.class).configure(properties));
-        Entities.manage(result);
         result.create();
         return result;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/rabbit/RabbitBrokerImpl.java
----------------------------------------------------------------------
diff --git 
a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/rabbit/RabbitBrokerImpl.java
 
b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/rabbit/RabbitBrokerImpl.java
index 1227365..bdf7299 100644
--- 
a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/rabbit/RabbitBrokerImpl.java
+++ 
b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/rabbit/RabbitBrokerImpl.java
@@ -76,7 +76,6 @@ public class RabbitBrokerImpl extends SoftwareProcessImpl 
implements RabbitBroke
 
     public RabbitQueue createQueue(Map properties) {
         RabbitQueue result = 
addChild(EntitySpec.create(RabbitQueue.class).configure(properties));
-        Entities.manage(result);
         result.create();
         return result;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
----------------------------------------------------------------------
diff --git 
a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
 
b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
index be7b5a7..78898bd 100644
--- 
a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
+++ 
b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
@@ -117,7 +117,6 @@ public class ControlledDynamicWebAppClusterImpl extends 
DynamicGroupImpl impleme
         sensors().set(WEB_CLUSTER_SPEC, webClusterSpec);
         
         DynamicWebAppCluster cluster = addChild(webClusterSpec);
-        if (Entities.isManaged(this)) Entities.manage(cluster);
         sensors().set(CLUSTER, cluster);
         setEntityFilter(EntityPredicates.isMemberOf(cluster));
         
@@ -132,8 +131,10 @@ public class ControlledDynamicWebAppClusterImpl extends 
DynamicGroupImpl impleme
                 log.debug("creating controller using custom spec for {}", 
this);
             }
             controller = addChild(controllerSpec);
-            
enrichers().add(Enrichers.builder().propagating(LoadBalancer.PROXY_HTTP_PORT, 
LoadBalancer.PROXY_HTTPS_PORT).from(controller).build());
-            if (Entities.isManaged(this)) Entities.manage(controller);
+            enrichers().add(Enrichers.builder()
+                    .propagating(LoadBalancer.PROXY_HTTP_PORT, 
LoadBalancer.PROXY_HTTPS_PORT)
+                    .from(controller)
+                    .build());
             sensors().set(CONTROLLER, controller);
         }
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git 
a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
 
b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index f295e90..1876e99 100644
--- 
a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ 
b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -66,8 +66,7 @@ public class BrooklynAssemblyTemplateInstantiator implements 
AssemblyTemplateSpe
         BrooklynClassLoadingContext loader = 
JavaBrooklynClassLoadingContext.create(mgmt);
         EntitySpec<? extends Application> spec = 
createApplicationSpec(template, platform, loader);
         Application instance = mgmt.getEntityManager().createEntity(spec);
-        log.info("CAMP placing '{}' under management", instance);
-        Entities.startManagement(instance, mgmt);
+        log.info("CAMP created '{}'", instance);
         return instance;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git 
a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
 
b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
index 7425865..ca5cda4 100644
--- 
a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
+++ 
b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
@@ -192,7 +192,11 @@ public class BrooklynLauncher {
      * subsequently call {@link #start()} or {@link #getApplications()}.
      * 
      * @see #application(ApplicationBuilder)
+     * 
+     * @deprecated since 0.9.0; instead use {@link #application(String)} for 
YAML apps, or {@link #application(EntitySpec)}.
+     *             Note that apps are now auto-managed on construction through 
EntitySpec/YAML.
      */
+    @Deprecated
     public BrooklynLauncher application(Application app) {
         if (Entities.isManaged(app)) throw new 
IllegalArgumentException("Application must not already be managed");
         appsToManage.add(checkNotNull(app, "app"));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5f2a296b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
 
b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
index 2d6802e..157ba67 100644
--- 
a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ 
b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -50,6 +50,9 @@ import org.apache.brooklyn.api.location.LocationRegistry;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.entity.AbstractEntity;
@@ -268,14 +271,13 @@ public class BrooklynRestResourceUtils {
                 } else if (Application.class.isAssignableFrom(clazz)) {
                     org.apache.brooklyn.api.entity.EntitySpec<?> coreSpec = 
toCoreEntitySpec(clazz, name, configO, catalogItemId);
                     configureRenderingMetadata(spec, coreSpec);
-                    instance = (Application) 
mgmt.getEntityManager().createEntity(coreSpec);
                     for (EntitySpec entitySpec : entities) {
                         log.info("REST creating instance for entity {}", 
entitySpec.getType());
-                        
instance.addChild(mgmt.getEntityManager().createEntity(toCoreEntitySpec(entitySpec)));
+                        coreSpec.child(toCoreEntitySpec(entitySpec));
                     }
 
                     log.info("REST placing '{}' under management", 
spec.getName() != null ? spec.getName() : spec);
-                    Entities.startManagement(instance, mgmt);
+                    instance = (Application) 
mgmt.getEntityManager().createEntity(coreSpec);
 
                 } else if (Entity.class.isAssignableFrom(clazz)) {
                     if (entities.size() > 0)
@@ -284,19 +286,17 @@ public class BrooklynRestResourceUtils {
                     org.apache.brooklyn.api.entity.EntitySpec<?> coreSpec = 
toCoreEntitySpec(BasicApplication.class, name, configO, catalogItemId);
                     configureRenderingMetadata(spec, coreSpec);
 
-                    instance = (Application) 
mgmt.getEntityManager().createEntity(coreSpec);
-
-                    Entity soleChild = 
mgmt.getEntityManager().createEntity(toCoreEntitySpec(clazz, name, configO, 
catalogItemId));
-                    instance.addChild(soleChild);
-                    instance.enrichers().add(Enrichers.builder()
+                    coreSpec.child(toCoreEntitySpec(clazz, name, configO, 
catalogItemId)
+                            .configure(BrooklynCampConstants.PLAN_ID, 
"soleChildId"));
+                    coreSpec.enricher(Enrichers.builder()
                             .propagatingAllBut(Attributes.SERVICE_UP, 
Attributes.SERVICE_NOT_UP_INDICATORS, 
                                     Attributes.SERVICE_STATE_ACTUAL, 
Attributes.SERVICE_STATE_EXPECTED, 
                                     Attributes.SERVICE_PROBLEMS)
-                            .from(soleChild)
+                            .from(new DslComponent(Scope.CHILD, 
"soleChildId").newTask())
                             .build());
 
                     log.info("REST placing '{}' under management", 
spec.getName());
-                    Entities.startManagement(instance, mgmt);
+                    instance = (Application) 
mgmt.getEntityManager().createEntity(coreSpec);
 
                 } else {
                     throw new IllegalArgumentException("Class " + clazz + " 
must extend one of ApplicationBuilder, Application or Entity");

Reply via email to