You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/07/04 11:51:11 UTC

[29/45] git commit: create specs from catalog items, and use these in many places. also fix some NPE and serialization issues.

create specs from catalog items, and use these in many places.  also fix some NPE and serialization issues.


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

Branch: refs/heads/master
Commit: 468d788542d19810062d3e0b8a41019aa699f740
Parents: 407de80
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 02:29:47 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 02:29:47 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/catalog/CatalogItem.java | 17 +++-
 .../camp/test/mock/web/MockWebPlatform.java     | 15 ++-
 .../api/AssemblyTemplateSpecInstantiator.java   | 12 +++
 .../api/HasBrooklynManagementContext.java       |  9 ++
 .../brooklyn/catalog/CatalogPredicates.java     |  9 ++
 .../catalog/internal/BasicBrooklynCatalog.java  | 99 ++++++++++++++++----
 .../catalog/internal/CatalogClasspathDo.java    | 10 +-
 .../internal/CatalogConfigurationDto.java       | 11 +++
 .../brooklyn/catalog/internal/CatalogDo.java    | 13 ++-
 .../brooklyn/catalog/internal/CatalogDto.java   |  9 +-
 .../catalog/internal/CatalogEntityItemDto.java  | 12 +++
 .../catalog/internal/CatalogItemDo.java         | 32 ++++++-
 .../internal/CatalogItemDtoAbstract.java        | 74 ++++++++++-----
 .../catalog/internal/CatalogLibrariesDo.java    |  9 +-
 .../catalog/internal/CatalogLibrariesDto.java   |  9 +-
 .../catalog/internal/CatalogPolicyItemDto.java  |  6 ++
 .../internal/CatalogTemplateItemDto.java        | 10 +-
 .../dto/BasicManagementNodeSyncRecord.java      | 12 ++-
 .../lite/CampPlatformWithJustBrooklynMgmt.java  | 23 +++++
 .../brooklyn/camp/lite/CampYamlLiteTest.java    | 37 ++++++--
 .../camp/lite/TestAppAssemblyInstantiator.java  | 40 ++++++--
 .../catalog/internal/CatalogDtoTest.java        | 74 +++++++--------
 .../camp/brooklyn/BrooklynCampPlatform.java     |  2 +-
 .../BrooklynAssemblyTemplateInstantiator.java   | 35 +++++--
 .../platform/BrooklynImmutableCampPlatform.java |  1 +
 .../platform/HasBrooklynManagementContext.java  |  9 --
 .../brooklyn/EmptySoftwareProcessYamlTest.java  |  5 +-
 usage/cli/src/main/java/brooklyn/cli/Main.java  |  8 +-
 .../brooklyn/launcher/BrooklynLauncher.java     | 10 +-
 .../resources/AbstractBrooklynRestResource.java |  5 +-
 30 files changed, 465 insertions(+), 152 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index fe844b8..276eba4 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -1,7 +1,9 @@
 package brooklyn.catalog;
 
 import java.util.List;
+
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 public interface CatalogItem<T,SpecT> {
     
@@ -14,15 +16,28 @@ public interface CatalogItem<T,SpecT> {
     }
 
     public CatalogItemType getCatalogItemType();
+    /** the high-level type of this entity, e.g. Entity (not a specific Entity class) */
     public Class<T> getCatalogItemJavaType();
+    /** the type of the spec e.g. EntitySpec corresponding to {@link #getCatalogItemJavaType()} */
+    public Class<SpecT> getSpecType();
     
+    /** the explicit ID of this item, or the type if not supplied */
     public String getId();
-    public String getJavaType();
+    
+    /** the type name registered in the catalog for this item */ 
+    public String getRegisteredTypeName();
+    
+    /** the underlying java type of the item represented, or null if not known (e.g. if it comes from yaml) */
+    // TODO references to this should probably query getRegisteredType
+    @Nullable public String getJavaType();
+    
     public String getName();
     public String getDescription();
     public String getIconUrl();
     public String getVersion();
 
+    // FIXME many of the static methods in CatalogItemAbstractDto which create CatalogItems set this as null
+    // I (alex) suggest removing the annotation, here, and in subclasses where the method is defined
     @Nonnull
     public CatalogItemLibraries getLibraries();
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java b/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
index e547d91..389ec41 100644
--- a/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
+++ b/camp/camp-base/src/test/java/io/brooklyn/camp/test/mock/web/MockWebPlatform.java
@@ -1,5 +1,7 @@
 package io.brooklyn.camp.test.mock.web;
 
+import javax.annotation.Nullable;
+
 import brooklyn.util.guava.Maybe;
 import io.brooklyn.camp.BasicCampPlatform;
 import io.brooklyn.camp.spi.ApplicationComponentTemplate;
@@ -7,6 +9,7 @@ import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.PlatformComponentTemplate;
 import io.brooklyn.camp.spi.collection.BasicResourceLookup;
 import io.brooklyn.camp.spi.collection.ResolvableLink;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 import io.brooklyn.camp.spi.pdp.Artifact;
 import io.brooklyn.camp.spi.pdp.AssemblyTemplateConstructor;
 import io.brooklyn.camp.spi.pdp.Service;
@@ -57,7 +60,7 @@ public class MockWebPlatform {
         }
     };
 
-    public static final PdpMatcher newLiteralServiceTypeToPlatformComponentTemplateMatcher(final BasicCampPlatform platform) {
+    public static final PdpMatcher newLiteralServiceTypeToPlatformComponentTemplateMatcher(final BasicCampPlatform platform, @Nullable final Class<? extends AssemblyTemplateInstantiator> instantiator) {
         return new PdpMatcher() {
             public boolean apply(Object item, AssemblyTemplateConstructor atc) {
                 if (!(item instanceof Service)) return false;
@@ -71,8 +74,11 @@ public class MockWebPlatform {
                             .customAttribute("serviceType", type)
                             .description(Maybe.fromNullable(svc.getDescription()).or(t.resolve().getDescription()))
                             .build();
-                        if (atc!=null)
+                        if (atc!=null) {
                             atc.add(pct);
+                            if (instantiator!=null)
+                                atc.instantiator(instantiator);
+                        }
                         return true;
                     }
                 }
@@ -87,12 +93,15 @@ public class MockWebPlatform {
     }
     
     public static <T extends BasicCampPlatform> T populate(T platform) {
+        return populate(platform, null);
+    }
+    public static <T extends BasicCampPlatform> T populate(T platform, @Nullable Class<? extends AssemblyTemplateInstantiator> instantiator) {
         platform.platformComponentTemplates().addAll(APPSERVER, DATABASE);
         platform.applicationComponentTemplates().add(WAR);
         platform.assemblyTemplates().add(ASSEMBLY1);
         
         platform.pdp().addMatcher(WAR_GETS_WAR_MATCHER);
-        platform.pdp().addMatcher(newLiteralServiceTypeToPlatformComponentTemplateMatcher(platform));
+        platform.pdp().addMatcher(newLiteralServiceTypeToPlatformComponentTemplateMatcher(platform, instantiator));
         
         return platform;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java b/core/src/main/java/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
new file mode 100644
index 0000000..0054a80
--- /dev/null
+++ b/core/src/main/java/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
@@ -0,0 +1,12 @@
+package brooklyn.camp.brooklyn.api;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+import brooklyn.entity.proxying.EntitySpec;
+
+public interface AssemblyTemplateSpecInstantiator extends AssemblyTemplateInstantiator {
+
+    EntitySpec<?> createSpec(AssemblyTemplate template, CampPlatform platform);
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/camp/brooklyn/api/HasBrooklynManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/camp/brooklyn/api/HasBrooklynManagementContext.java b/core/src/main/java/brooklyn/camp/brooklyn/api/HasBrooklynManagementContext.java
new file mode 100644
index 0000000..e21bff1
--- /dev/null
+++ b/core/src/main/java/brooklyn/camp/brooklyn/api/HasBrooklynManagementContext.java
@@ -0,0 +1,9 @@
+package brooklyn.camp.brooklyn.api;
+
+import brooklyn.management.ManagementContext;
+
+public interface HasBrooklynManagementContext {
+
+    public ManagementContext getBrooklynManagementContext();
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
index 5c3d884..6dfe89a 100644
--- a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
+++ b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
@@ -47,6 +47,15 @@ public class CatalogPredicates {
         };
     }
 
+    public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> registeredType(final Predicate<? super String> filter) {
+        return new Predicate<CatalogItem<T,SpecT>>() {
+            @Override
+            public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
+                return (item != null) && filter.apply(item.getRegisteredTypeName());
+            }
+        };
+    }
+
     public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> javaType(final Predicate<? super String> filter) {
         return new Predicate<CatalogItem<T,SpecT>>() {
             @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index 4bbb02c..6a4f3d2 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -1,7 +1,10 @@
 package brooklyn.catalog.internal;
 
 import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 import io.brooklyn.camp.spi.pdp.DeploymentPlan;
+import io.brooklyn.camp.spi.pdp.Service;
 
 import java.util.NoSuchElementException;
 
@@ -10,6 +13,7 @@ import javax.annotation.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
@@ -18,7 +22,9 @@ import brooklyn.management.ManagementContext;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.javalang.AggregateClassLoader;
 import brooklyn.util.javalang.LoadedClassLoader;
+import brooklyn.util.javalang.Reflections;
 import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
 import brooklyn.util.time.Duration;
 import brooklyn.util.time.Time;
 
@@ -96,14 +102,57 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         }
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public <T, SpecT> SpecT createSpec(CatalogItem<T, SpecT> item) {
-        // TODO #2
-        throw new UnsupportedOperationException();
+        CatalogItemDo<T,SpecT> loadedItem = (CatalogItemDo<T, SpecT>) getCatalogItemDo(item.getId());
+        
+        Class<SpecT> specType = loadedItem.getSpecType();
+        if (specType==null) return null;
+            
+        String yaml = loadedItem.getYaml();
+        SpecT spec = null;
+            
+        if (yaml!=null) {
+            DeploymentPlan plan = makePlanFromYaml(yaml);
+            CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+            
+            // TODO should not register new AT each time we instantiate from the same plan; use some kind of cache
+            AssemblyTemplate at = camp.pdp().registerDeploymentPlan(plan);
+            
+            try {
+                AssemblyTemplateInstantiator instantiator = at.getInstantiator().newInstance();
+                if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
+                    return (SpecT) ((AssemblyTemplateSpecInstantiator)instantiator).createSpec(at, camp);
+                }
+                throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at);
+            } catch (Exception e) {
+                throw Exceptions.propagate(e);
+            }
+        }
+            
+        // revert to legacy mechanism
+        try {
+            if (loadedItem.getJavaType()!=null) {
+                @SuppressWarnings({ "deprecation" })
+                SpecT specT = (SpecT) Reflections.findMethod(specType, "create", Class.class).invoke(null, loadedItem.getJavaClass());
+                spec = specT;
+            }
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            throw new IllegalStateException("Unsupported creation of spec type "+specType+"; it must have a public static create(Class) method", e);
+        }
+
+        if (spec==null) 
+            throw new IllegalStateException("Unknown how to create instance of "+this);
+
+        return spec;
     }
     
     @SuppressWarnings("unchecked")
     @Override
+    /** @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
+    @Deprecated
     public <T,SpecT> Class<? extends T> loadClass(CatalogItem<T,SpecT> item) {
         if (log.isDebugEnabled())
             log.debug("Loading class for catalog item " + item);
@@ -115,6 +164,8 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     
     @SuppressWarnings("unchecked")
     @Override
+    /** @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
+    @Deprecated
     public <T> Class<? extends T> loadClassByType(String typeName, Class<T> typeClass) {
         Iterable<CatalogItem<Object,Object>> resultL = getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(typeName)));
         if (Iterables.isEmpty(resultL)) throw new NoSuchElementException("Unable to find catalog item for type "+typeName);
@@ -125,7 +176,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return (Class<? extends T>) loadClass(resultI);
     }
 
-    @Deprecated
+    @Deprecated /** @deprecated since 0.7.0 only used by other deprecated items */ 
     private <T,SpecT> CatalogItemDtoAbstract<T,SpecT> getAbstractCatalogItem(CatalogItem<T,SpecT> item) {
         while (item instanceof CatalogItemDo) item = ((CatalogItemDo<T,SpecT>)item).itemDto;
         if (item==null) return null;
@@ -133,21 +184,37 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         throw new IllegalStateException("Cannot unwrap catalog item '"+item+"' (type "+item.getClass()+") to restore DTO");
     }
 
-    private <T,SpecT> CatalogItemDtoAbstract<T,SpecT> getAbstractCatalogItem(String yaml) {
-        CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+    private CatalogItemDtoAbstract<?,?> getAbstractCatalogItem(String yaml) {
+        DeploymentPlan plan = makePlanFromYaml(yaml);
         
-        DeploymentPlan plan = camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
+        // TODO #2 parse brooklyn.catalog for metadata - name, bundles/libraries, etc
+        // (for now we default to taking the name from the plan or from a single service type therein, below)
+        String name = null;
+        CatalogLibrariesDto libraries = null;
         
-        // TODO #2 parse brooklyn.catalog metadata, bundles etc.
-        // for now take the name from the plan or from a single service type therein
+        // TODO #3 support version info
         
-        // TODO #3 version info
+        // take name from plan if not specified in brooklyn.catalog section not supplied
+        if (Strings.isBlank(name)) {
+            name = plan.getName();
+            if (Strings.isBlank(name)) {
+                if (plan.getServices().size()==1) {
+                    Service svc = Iterables.getOnlyElement(plan.getServices());
+                    name = svc.getServiceType();
+                }
+            }
+        }
         
-        // TODO #1 build the catalog item from the plan (as CatalogItem<Entity> ?)
-//        plan.getName()
-        // TODO #2 then support instantiating from the item, replacing 
+        // build the catalog item from the plan (as CatalogItem<Entity> for now)
+        // TODO applications / templates
+        // TODO long-term support policies etc
         
-        throw new UnsupportedOperationException();
+        return CatalogItemDtoAbstract.newEntityFromPlan(name, libraries, plan, yaml);
+    }
+
+    private DeploymentPlan makePlanFromYaml(String yaml) {
+        CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+        return camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
     }
 
     @Override
@@ -160,7 +227,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return itemDto;
     }
 
-    @Override @Deprecated
+    @Override @Deprecated /** @deprecated see super */
     public void addItem(CatalogItem<?,?> item) {
         log.debug("Adding manual catalog item to "+mgmt+": "+item);
         Preconditions.checkNotNull(item, "item");
@@ -168,7 +235,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         manualAdditionsCatalog.addEntry(getAbstractCatalogItem(item));
     }
 
-    @Override @Deprecated
+    @Override @Deprecated /** @deprecated see super */
     public CatalogItem<?,?> addItem(Class<?> type) {
         log.debug("Adding manual catalog item to "+mgmt+": "+type);
         Preconditions.checkNotNull(type, "type");
@@ -177,7 +244,6 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return manualAdditionsCatalog.classpath.addCatalogEntry(type);
     }
 
-    @Deprecated
     private synchronized void loadManualAdditionsCatalog() {
         if (manualAdditionsCatalog!=null) return;
         CatalogDto manualAdditionsCatalogDto = CatalogDto.newNamedInstance(
@@ -218,7 +284,6 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return Iterables.transform(filtered, BasicBrooklynCatalog.<T,SpecT>itemDoToDto());
     }
 
-    @SuppressWarnings({ "unchecked" })
     private static <T,SpecT> Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>> itemDoToDto() {
         return new Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>>() {
             @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
index 06d0914..badf319 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
@@ -207,7 +207,9 @@ public class CatalogClasspathDo {
         return Iterables.filter(input, f);
     }
 
-    /** augments the given item with annotations and class data for the given class, then adds to catalog */
+    /** augments the given item with annotations and class data for the given class, then adds to catalog
+     * @deprecated since 0.7.0 the classpath DO is replaced by libraries */
+    @Deprecated
     public CatalogItem<?,?> addCatalogEntry(Class<?> c) {
         if (Application.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogTemplateItemDto(), c);
         if (ApplicationBuilder.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogTemplateItemDto(), c);
@@ -217,10 +219,12 @@ public class CatalogClasspathDo {
     }
     
     /** augments the given item with annotations and class data for the given class, then adds to catalog 
-     */
+     * @deprecated since 0.7.0 the classpath DO is replaced by libraries */
+    @Deprecated
     public CatalogItem<?,?> addCatalogEntry(CatalogItemDtoAbstract<?,?> item, Class<?> c) {
         Catalog annotations = c.getAnnotation(Catalog.class);
-        item.type = c.getName();
+        item.registeredType = c.getName();
+        item.javaType = c.getName();
         item.name = firstNonEmpty(c.getSimpleName(), c.getName());
         if (annotations!=null) {
             item.name = firstNonEmpty(annotations.name(), item.name);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
index d52b539..f07c942 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
@@ -12,4 +12,15 @@ public class CatalogConfigurationDto extends CatalogItemDtoAbstract<ConfigKey,Vo
     }
 
     public Class<ConfigKey> getCatalogItemJavaType() { return ConfigKey.class; }
+
+    @Override
+    public String getRegisteredTypeName() {
+        return getJavaType();
+    }
+    
+    @Override
+    public Class<Void> getSpecType() {
+        return null;
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index c571585..5cda68d 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -92,10 +92,15 @@ public class CatalogDo {
 
     private void loadCatalogItems() {
         List<CatalogLibrariesDo> loadedLibraries = Lists.newLinkedList();
-        for (CatalogItemDtoAbstract<?,?> entry : dto.entries) {
-            CatalogLibrariesDo library = new CatalogLibrariesDo(entry.getLibrariesDto());
-            library.load(mgmt);
-            loadedLibraries.add(library);
+        List<CatalogItemDtoAbstract<?, ?>> entries = dto.entries;
+        if (entries!=null) {
+            for (CatalogItemDtoAbstract<?,?> entry : entries) {
+                if (entry.getLibrariesDto()!=null) {
+                    CatalogLibrariesDo library = new CatalogLibrariesDo(entry.getLibrariesDto());
+                    library.load(mgmt);
+                    loadedLibraries.add(library);
+                }
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
index bd34020..655ed29 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
@@ -7,10 +7,11 @@ import java.util.List;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Objects;
-
 import brooklyn.util.ResourceUtils;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.PropagatedRuntimeException;
+
+import com.google.common.base.Objects;
 
 public class CatalogDto {
 
@@ -42,8 +43,8 @@ public class CatalogDto {
             if (LOG.isDebugEnabled()) LOG.debug("Retrieved catalog from: {}", url);
             return result;
         } catch (Throwable t) {
-            LOG.debug("Unable to retrieve catalog from: " + url + " (" + t + ")");
-            throw Exceptions.propagate(t);
+            Exceptions.propagateIfFatal(t);
+            throw new PropagatedRuntimeException("Unable to retrieve catalog from " + url + ": " + t, t);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
index 8a61f24..60d6fbe 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
@@ -6,6 +6,8 @@ import brooklyn.entity.proxying.EntitySpec;
 
 public class CatalogEntityItemDto extends CatalogItemDtoAbstract<Entity,EntitySpec<?>> {
     
+    String planYaml;
+
     @Override
     public CatalogItemType getCatalogItemType() {
         return CatalogItemType.ENTITY;
@@ -16,4 +18,14 @@ public class CatalogEntityItemDto extends CatalogItemDtoAbstract<Entity,EntitySp
         return Entity.class;
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Class<EntitySpec<?>> getSpecType() {
+        return (Class)EntitySpec.class;
+    }
+
+    public String getPlanYaml() {
+        return planYaml;
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index 1a6c804..200db52 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -1,22 +1,23 @@
 package brooklyn.catalog.internal;
 
 import javax.annotation.Nonnull;
-
-import com.google.common.base.Preconditions;
+import javax.annotation.Nullable;
 
 import brooklyn.catalog.CatalogItem;
 import brooklyn.util.exceptions.Exceptions;
 
+import com.google.common.base.Preconditions;
+
 public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
 
     protected final CatalogDo catalog;
-    protected final CatalogItem<T,SpecT> itemDto;
+    protected final CatalogItemDtoAbstract<T,SpecT> itemDto;
 
     protected volatile Class<T> javaClass; 
     
     public CatalogItemDo(CatalogDo catalog, CatalogItem<T,SpecT> itemDto) {
         this.catalog = Preconditions.checkNotNull(catalog, "catalog");
-        this.itemDto = Preconditions.checkNotNull(itemDto, "itemDto");
+        this.itemDto = (CatalogItemDtoAbstract<T, SpecT>) Preconditions.checkNotNull(itemDto, "itemDto");
     }
 
     public CatalogItem<T,SpecT> getDto() {
@@ -39,6 +40,11 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     }
 
     @Override
+    public String getRegisteredTypeName() {
+        return itemDto.getRegisteredTypeName();
+    }
+    
+    @Override
     public String getJavaType() {
         return itemDto.getJavaType();
     }
@@ -69,6 +75,17 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
         return itemDto.getLibraries();
     }
 
+    @Nullable
+    public String getYaml() {
+        if (itemDto instanceof CatalogEntityItemDto) {
+            return ((CatalogEntityItemDto)itemDto).getPlanYaml();
+        }
+        return null;
+    }
+    
+    /** @deprecated since 0.7.0 this is the legacy mechanism; still needed for policies and apps, but being phased out.
+     * new items should use {@link #getYaml()} */
+    @Deprecated
     public Class<T> getJavaClass() {
         if (javaClass==null) loadJavaClass();
         return javaClass;
@@ -78,6 +95,9 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     protected Class<? extends T> loadJavaClass() {
         try {
             if (javaClass!=null) return javaClass;
+            
+            // TODO use OSGi
+            
             javaClass = (Class<T>) catalog.getRootClassLoader().loadClass(getJavaType());
             return javaClass;
         } catch (ClassNotFoundException e) {
@@ -93,5 +113,9 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     public String toXmlString() {
         return itemDto.toXmlString();
     }
+
+    public Class<SpecT> getSpecType() {
+        return itemDto.getSpecType();
+    }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index 771e37b..4957474 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -1,26 +1,45 @@
 package brooklyn.catalog.internal;
 
+import io.brooklyn.camp.spi.pdp.DeploymentPlan;
+
 import javax.annotation.Nonnull;
 
 import brooklyn.catalog.CatalogItem;
 
 public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,SpecT> {
 
+    // TODO are ID and registeredType the same?
     String id;
-    String type;
+    String registeredType;
+    
+    String javaType;
     String name;
     String description;
     String iconUrl;
     String version;
     CatalogLibrariesDto libraries;
     
+    /** @deprecated since 0.7.0.
+     * used for backwards compatibility when deserializing.
+     * when catalogs are converted to new yaml format, this can be removed. */
+    @Deprecated
+    String type;
+    
     public String getId() {
         if (id!=null) return id;
-        return type;
+        return getRegisteredTypeName();
+    }
+    
+    @Override
+    public String getRegisteredTypeName() {
+        if (registeredType!=null) return registeredType;
+        return getJavaType();
     }
     
     public String getJavaType() {
-        return type;
+        if (javaType!=null) return javaType;
+        if (type!=null) return type;
+        return null;
     }
     
     public String getName() {
@@ -49,41 +68,48 @@ public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,S
         return libraries;
     }
 
-    public static CatalogTemplateItemDto newTemplate(String type, String name) {
-        return newTemplate(null, type, name, null);
+    public static CatalogTemplateItemDto newTemplateFromJava(String javaType, String name) {
+        return newTemplateFromJava(null, javaType, name, null);
     }
-    public static CatalogTemplateItemDto newTemplate(String id, String type, String name, String description) {
-        return newTemplate(id, type, name, description, null);
+    public static CatalogTemplateItemDto newTemplateFromJava(String id, String javaType, String name, String description) {
+        return newTemplateFromJava(id, javaType, name, description, null);
     }
-    public static CatalogTemplateItemDto newTemplate(String id, String type, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogTemplateItemDto(), id, type, name, description, libraries);
+    public static CatalogTemplateItemDto newTemplateFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogTemplateItemDto(), id, javaType, javaType, name, description, libraries);
     }
 
-    public static CatalogEntityItemDto newEntity(String type, String name) {
-        return newEntity(null, type, name, null);
+    public static CatalogEntityItemDto newEntityFromPlan(String registeredTypeName, CatalogLibrariesDto libraries, DeploymentPlan plan, String underlyingPlanYaml) {
+        CatalogEntityItemDto target = set(new CatalogEntityItemDto(), null, registeredTypeName, null, plan.getName(), plan.getDescription(), libraries);
+        target.planYaml = underlyingPlanYaml;
+        return target;
     }
-    public static CatalogEntityItemDto newEntity(String id, String type, String name, String description) {
-        return newEntity(id, type, name, description, null);
+    
+    public static CatalogEntityItemDto newEntityFromJava(String javaType, String name) {
+        return newEntityFromJava(null, javaType, name, null);
+    }
+    public static CatalogEntityItemDto newEntityFromJava(String id, String javaType, String name, String description) {
+        return newEntityFromJava(id, javaType, name, description, null);
     }
-    public static CatalogEntityItemDto newEntity(String id, String type, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogEntityItemDto(), id, type, name, description, libraries);
+    public static CatalogEntityItemDto newEntityFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogEntityItemDto(), id, javaType, javaType, name, description, libraries);
     }
 
-    public static CatalogPolicyItemDto newPolicy(String type, String name) {
-        return newPolicy(null, type, name, null);
+    public static CatalogPolicyItemDto newPolicyFromJava(String javaType, String name) {
+        return newPolicyFromJava(null, javaType, name, null);
     }
-    public static CatalogPolicyItemDto newPolicy(String id, String type, String name, String description) {
-        return newPolicy(id, type, name, description, null);
+    public static CatalogPolicyItemDto newPolicyFromJava(String id, String javaType, String name, String description) {
+        return newPolicyFromJava(id, javaType, name, description, null);
     }
-    public static CatalogPolicyItemDto newPolicy(String id, String type, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogPolicyItemDto(), id, type, name, description, libraries);
+    public static CatalogPolicyItemDto newPolicyFromJava(String id, String javaType, String name, String description, CatalogLibrariesDto libraries) {
+        return set(new CatalogPolicyItemDto(), id, javaType, javaType, name, description, libraries);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    private static <T extends CatalogItemDtoAbstract> T set(T target, String id, String type, String name,
+    private static <T extends CatalogItemDtoAbstract> T set(T target, String id, String registeredType, String javaType, String name,
             String description, CatalogLibrariesDto libraries) {
         target.id = id;
-        target.type = type;
+        target.registeredType = registeredType;
+        target.javaType = javaType;
         target.name = name;
         target.description = description;
         target.libraries = libraries != null ? libraries : new CatalogLibrariesDto();
@@ -106,5 +132,7 @@ public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,S
         if (serializer==null) 
             serializer = new CatalogXmlSerializer();
     }
+
+    public abstract Class<SpecT> getSpecType();
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
index 86295a1..0892c31 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
@@ -5,18 +5,17 @@ import java.util.List;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Stopwatch;
-
 import brooklyn.catalog.CatalogItem;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.ha.OsgiManager;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.util.guava.Maybe;
-import brooklyn.util.text.Strings;
 import brooklyn.util.time.Time;
 
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+
 public class CatalogLibrariesDo implements CatalogItem.CatalogItemLibraries {
 
     private static final Logger LOG = LoggerFactory.getLogger(CatalogLibrariesDo.class);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
index 3c05387..a408921 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
@@ -1,8 +1,10 @@
 package brooklyn.catalog.internal;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import brooklyn.catalog.CatalogItem;
@@ -12,11 +14,16 @@ public class CatalogLibrariesDto implements CatalogItem.CatalogItemLibraries {
     private List<String> bundles = new CopyOnWriteArrayList<String>();
 
     public void addBundle(String url) {
-        bundles.add(url);
+        Preconditions.checkNotNull(url, "Cannot add a bundle to a deserialized DTO");
+        bundles.add( Preconditions.checkNotNull(url) );
     }
 
     /** @return An immutable copy of the bundle URLs referenced by this object */
     public List<String> getBundles() {
+        if (bundles==null)  {
+            // can be null on deserialization
+            return Collections.emptyList();
+        }
         return ImmutableList.copyOf(bundles);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
index 00ba3f6..a077819 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
@@ -16,4 +16,10 @@ public class CatalogPolicyItemDto extends CatalogItemDtoAbstract<Policy,PolicySp
         return Policy.class;
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Class<PolicySpec<?>> getSpecType() {
+        return (Class)PolicySpec.class;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
index e4016d9..76531e9 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
@@ -3,7 +3,7 @@ package brooklyn.catalog.internal;
 import brooklyn.entity.Application;
 import brooklyn.entity.proxying.EntitySpec;
 
-public class CatalogTemplateItemDto extends CatalogItemDtoAbstract<Application,EntitySpec<?>> {
+public class CatalogTemplateItemDto extends CatalogItemDtoAbstract<Application,EntitySpec<? extends Application>> {
 
     @Override
     public CatalogItemType getCatalogItemType() {
@@ -14,5 +14,11 @@ public class CatalogTemplateItemDto extends CatalogItemDtoAbstract<Application,E
     public Class<Application> getCatalogItemJavaType() {
         return Application.class;
     }
-    
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public Class<EntitySpec<? extends Application>> getSpecType() {
+        return (Class)EntitySpec.class;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/main/java/brooklyn/entity/rebind/plane/dto/BasicManagementNodeSyncRecord.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/plane/dto/BasicManagementNodeSyncRecord.java b/core/src/main/java/brooklyn/entity/rebind/plane/dto/BasicManagementNodeSyncRecord.java
index e731f4b..2d9ea91 100644
--- a/core/src/main/java/brooklyn/entity/rebind/plane/dto/BasicManagementNodeSyncRecord.java
+++ b/core/src/main/java/brooklyn/entity/rebind/plane/dto/BasicManagementNodeSyncRecord.java
@@ -78,8 +78,14 @@ public class BasicManagementNodeSyncRecord implements ManagementNodeSyncRecord,
     private String nodeId;
     private URI uri;
     private ManagementNodeState status;
-    private long localTimestamp;
+    private Long localTimestamp;
     private Long remoteTimestamp;
+    
+    /** @deprecated since 0.7.0, use {@link #localTimestamp} or {@link #remoteTimestamp},
+     * but kept (or rather added back in) to support deserializing previous instances */
+    @Deprecated
+    private Long timestampUtc;
+
 
     // for de-serialization
     @SuppressWarnings("unused")
@@ -118,7 +124,9 @@ public class BasicManagementNodeSyncRecord implements ManagementNodeSyncRecord,
     
     @Override
     public long getLocalTimestamp() {
-        return localTimestamp;
+        if (localTimestamp!=null) return localTimestamp;
+        if (timestampUtc!=null) return timestampUtc;
+        throw new NullPointerException("localTimestamp not known for "+getNodeId());
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/test/java/brooklyn/camp/lite/CampPlatformWithJustBrooklynMgmt.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampPlatformWithJustBrooklynMgmt.java b/core/src/test/java/brooklyn/camp/lite/CampPlatformWithJustBrooklynMgmt.java
new file mode 100644
index 0000000..89e6b2e
--- /dev/null
+++ b/core/src/test/java/brooklyn/camp/lite/CampPlatformWithJustBrooklynMgmt.java
@@ -0,0 +1,23 @@
+package brooklyn.camp.lite;
+
+import io.brooklyn.camp.BasicCampPlatform;
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.management.ManagementContext;
+
+public class CampPlatformWithJustBrooklynMgmt extends BasicCampPlatform implements HasBrooklynManagementContext {
+
+    private ManagementContext mgmt;
+
+    public CampPlatformWithJustBrooklynMgmt(ManagementContext mgmt) {
+        this.mgmt = mgmt;
+        ((BrooklynProperties)mgmt.getConfig()).put(BrooklynServerConfig.CAMP_PLATFORM, this);
+    }
+    
+    @Override
+    public ManagementContext getBrooklynManagementContext() {
+        return mgmt;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
index 6a17c28..9bbadf7 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -1,12 +1,10 @@
 package brooklyn.camp.lite;
 
-import io.brooklyn.camp.BasicCampPlatform;
 import io.brooklyn.camp.spi.Assembly;
 import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.pdp.PdpYamlTest;
 import io.brooklyn.camp.test.mock.web.MockWebPlatform;
 
-import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.util.Map;
@@ -18,12 +16,17 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.CatalogPredicates;
 import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.internal.LocalManagementContext;
 import brooklyn.test.entity.LocalManagementContextForTests;
 import brooklyn.test.entity.TestApplication;
 import brooklyn.test.entity.TestEntity;
+import brooklyn.util.stream.Streams;
 
+import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;
 
 /** Tests of lightweight CAMP integration. Since the "real" integration is in brooklyn-camp project,
@@ -33,10 +36,12 @@ public class CampYamlLiteTest {
     private static final Logger log = LoggerFactory.getLogger(CampYamlLiteTest.class);
     
     protected LocalManagementContext mgmt;
+    protected CampPlatformWithJustBrooklynMgmt platform;
     
     @BeforeMethod(alwaysRun=true)
     public void setUp() {
-        mgmt = new LocalManagementContextForTests();        
+        mgmt = new LocalManagementContextForTests();
+        platform = new CampPlatformWithJustBrooklynMgmt(mgmt);
     }
     
     @AfterMethod(alwaysRun=true)
@@ -47,8 +52,9 @@ public class CampYamlLiteTest {
     /** based on {@link PdpYamlTest} for parsing,
      * then creating a {@link TestAppAssembly} */
     @Test
-    public void testYamlServiceMatchAndBrooklynInstantiate() throws IOException {
-        BasicCampPlatform platform = MockWebPlatform.populate(new BasicCampPlatform());
+    public void testYamlServiceMatchAndBrooklynInstantiate() throws Exception {
+        MockWebPlatform.populate(platform, TestAppAssemblyInstantiator.class);
+        
         Reader input = new InputStreamReader(getClass().getResourceAsStream("test-app-service-blueprint.yaml"));
         AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
         log.info("AT is:\n"+at.toString());
@@ -56,7 +62,7 @@ public class CampYamlLiteTest {
         Assert.assertEquals(at.getPlatformComponentTemplates().links().size(), 1);
         
         // now use brooklyn to instantiate
-        Assembly assembly = new TestAppAssemblyInstantiator(mgmt).instantiate(at, platform);
+        Assembly assembly = at.getInstantiator().newInstance().instantiate(at, platform);
         
         TestApplication app = ((TestAppAssembly)assembly).getBrooklynApp();
         Assert.assertEquals( app.getConfig(TestEntity.CONF_NAME), "sample" );
@@ -71,5 +77,22 @@ public class CampYamlLiteTest {
         // desc ensures we got the information from the matcher, as this value is NOT in the yaml
         Assert.assertEquals( map.get("desc"), MockWebPlatform.APPSERVER.getDescription() );
     }
-    
+
+    @Test(groups="WIP")
+    public void testYamlServiceForCatalog() {
+        MockWebPlatform.populate(platform, TestAppAssemblyInstantiator.class);
+        
+        CatalogItem<?, ?> realItem = mgmt.getCatalog().addItem(Streams.readFullyString(getClass().getResourceAsStream("test-app-service-blueprint.yaml")));
+        Iterable<CatalogItem<Object, Object>> retrievedItems = mgmt.getCatalog().getCatalogItems(CatalogPredicates.registeredType(Predicates.equalTo("sample")));
+        
+        Assert.assertEquals(Iterables.size(retrievedItems), 1, "Wrong retrieved items: "+retrievedItems);
+        CatalogItem<Object, Object> retrievedItem = Iterables.getOnlyElement(retrievedItems);
+        Assert.assertEquals(retrievedItem, realItem);
+        
+        EntitySpec<?> spec1 = (EntitySpec<?>) mgmt.getCatalog().createSpec(retrievedItem);
+        Assert.assertNotNull(spec1);
+        Assert.assertEquals(spec1.getConfig().get(TestEntity.CONF_NAME), "sample");
+        
+        // TODO other assertions, about children
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java b/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
index a00a3bf..e8b7ff8 100644
--- a/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
+++ b/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
@@ -6,9 +6,11 @@ import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.PlatformComponentTemplate;
 import io.brooklyn.camp.spi.collection.ResolvableLink;
 import io.brooklyn.camp.spi.instantiate.BasicAssemblyTemplateInstantiator;
+import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
 import brooklyn.entity.basic.ApplicationBuilder;
 import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.management.ManagementContext;
 import brooklyn.test.entity.TestApplication;
 import brooklyn.test.entity.TestEntity;
 import brooklyn.util.collections.MutableMap;
@@ -17,16 +19,20 @@ import brooklyn.util.collections.MutableMap;
  * all setting {@link TestEntity#CONF_NAME} for the name in the plan and in the service specs
  * <p>
  * the "real" instantiator for brooklyn is in brooklyn-camp project, not visible here, so let's have something we can test */
-public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiator {
+public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator {
 
-    protected final LocalManagementContext mgmt;
-    
-    public TestAppAssemblyInstantiator(LocalManagementContext mgmt) {
-        this.mgmt = mgmt;
-    }
-    
     @Override
     public Assembly instantiate(AssemblyTemplate template, CampPlatform platform) {
+        if (!(platform instanceof HasBrooklynManagementContext)) {
+            throw new IllegalStateException("Instantiator can only be used with CAMP platforms with a Brooklyn management context");
+        }
+        ManagementContext mgmt = ((HasBrooklynManagementContext)platform).getBrooklynManagementContext();
+        
+        // TODO when createSpec is working:
+//        TestApplication app = (TestApplication) mgmt.getEntityManager().createEntity( createSpec(template, platform) );
+//        mgmt.getEntityManager().manage(app);
+        
+        // workaround until above is reacy
         TestApplication app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class)
             .configure(TestEntity.CONF_NAME, template.getName())
             .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", template.getType(), "desc", template.getDescription()))
@@ -37,7 +43,25 @@ public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiat
                 .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", t.resolve().getType(), "desc", t.resolve().getDescription()))
                 );
         }
+
         return new TestAppAssembly(app);
     }
 
+    @Override
+    public EntitySpec<?> createSpec(AssemblyTemplate template, CampPlatform platform) {
+        EntitySpec<TestApplication> app = EntitySpec.create(TestApplication.class)
+            .configure(TestEntity.CONF_NAME, template.getName())
+            .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", template.getType(), "desc", template.getDescription()));
+        
+        for (ResolvableLink<PlatformComponentTemplate> t: template.getPlatformComponentTemplates().links()) {
+            // TODO use EntitySpec.child(...)
+//            app.child(EntitySpec.create(TestEntity.class)
+//                .configure(TestEntity.CONF_NAME, t.getName())
+//                .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", t.resolve().getType(), "desc", t.resolve().getDescription()))
+//                );
+        }
+        
+        return app;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
index 51c60ee..1989cb2 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
@@ -11,6 +11,10 @@ import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
 import brooklyn.entity.basic.Entities;
 import brooklyn.management.internal.LocalManagementContext;
 import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.util.BrooklynMavenArtifacts;
+import brooklyn.util.maven.MavenRetriever;
 
 public class CatalogDtoTest {
 
@@ -31,28 +35,31 @@ public class CatalogDtoTest {
     @Test(groups="Integration")
     public void testCatalogLookup() {
         CatalogDto root = buildExampleCatalog();
-        checkHadoopsExample(root);
+        checkCatalogHealthy(root);
     }
     
     @Test(groups="Integration")
     public void testCatalogSerializeAndLookup() {
         CatalogDto root = buildExampleCatalog();
-        CatalogXmlSerializer seriailizer = new CatalogXmlSerializer();
+        CatalogXmlSerializer serializer = new CatalogXmlSerializer();
         
-        String xml = seriailizer.toString(root);
-        log.info("Hadoops example catalog serialized as:\n"+xml);
+        String xml = serializer.toString(root);
+        log.info("Example catalog serialized as:\n"+xml);
         
-        CatalogDto root2 = (CatalogDto) seriailizer.fromString(xml);
-        checkHadoopsExample(root2);
+        CatalogDto root2 = (CatalogDto) serializer.fromString(xml);
+        checkCatalogHealthy(root2);
     }
 
-    protected void checkHadoopsExample(CatalogDto root) {
-        Assert.assertEquals(root.catalogs.size(), 5);
+    protected void checkCatalogHealthy(CatalogDto root) {
+        Assert.assertEquals(root.catalogs.size(), 4);
         CatalogDo loader = new CatalogDo(root).load(managementContext, null);
         
-        CatalogItemDo<?,?> worker = loader.getCache().get("io.brooklyn.mapr.m3.WorkerNode");
+        // test app comes from jar, by default
+        CatalogItemDo<?,?> worker = loader.getCache().get(TestApplication.class.getCanonicalName());
         Assert.assertNotNull(worker);
-        Assert.assertEquals(worker.getName(), "M3 Worker Node");
+        Assert.assertEquals(worker.getName(), "Test App from JAR");
+        
+        // TODO can test scanned elements, links to other catalogs, etc
     }
 
     public static CatalogDto buildExampleCatalog() {
@@ -61,39 +68,30 @@ public class CatalogDtoTest {
         		"intended partly as a teaching example for what can be expressed, and how"));
         root.setClasspathScanForEntities(CatalogScanningModes.NONE);
         
-        CatalogDo m3Catalog = new CatalogDo(CatalogDto.newNamedInstance("MapR M3", null));
-        m3Catalog.addToClasspath("file://~/.m2/repository/io/cloudsoft/brooklyn-mapr/1.0.0-SNAPSHOT/brooklyn-mapr.jar");
-        m3Catalog.addEntry(CatalogItemDtoAbstract.newTemplate(
-                "io.brooklyn.mapr.M3App", "M3 Application"));
-        m3Catalog.addEntry(CatalogItemDtoAbstract.newEntity(
-                "io.brooklyn.mapr.m3.ZookeperWorkerNode", "M3 Zookeeper+Worker Node"));
-        m3Catalog.addEntry(CatalogItemDtoAbstract.newEntity(
-                "io.brooklyn.mapr.m3.WorkerNode", "M3 Worker Node"));
-        root.addCatalog(m3Catalog.dto);
-        
-        CatalogDo cdhCatalog = new CatalogDo(CatalogDto.newNamedInstance("Cloudera", 
-                "CDH catalog, pointing to JARs as I have them installed on my machine already, "+
-                "tweaked for my preferences (overriding templates scanned from these JARs)"));
-        cdhCatalog.setClasspathScanForEntities(CatalogScanningModes.ANNOTATIONS);
-        cdhCatalog.addToClasspath(
-                "file://~/.m2/repository/io/cloudsoft/brooklyn-cdh/1.0.0-SNAPSHOT/brooklyn-cdh.jar",
-                "file://~/.m2/repository/io/cloudsoft/brooklyn-cdh/1.0.0-SNAPSHOT/whirr-cm.jar");
-        cdhCatalog.addEntry(CatalogItemDtoAbstract.newTemplate(
-                "io.brooklyn.cloudera.ClouderaForHadoopWithManager",
-                "RECOMMENDED: CDH Hadoop Application with Cloudera Manager"));
-        root.addCatalog(cdhCatalog.dto);
+        CatalogDo testEntitiesJavaCatalog = new CatalogDo(CatalogDto.newNamedInstance("Test Entities from Java", null));
+        testEntitiesJavaCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
+        testEntitiesJavaCatalog.addToClasspath(MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests")));
+        testEntitiesJavaCatalog.addEntry(CatalogItemDtoAbstract.newTemplateFromJava(
+                TestApplication.class.getCanonicalName(), "Test App from JAR"));
+        testEntitiesJavaCatalog.addEntry(CatalogItemDtoAbstract.newEntityFromJava(
+                TestEntity.class.getCanonicalName(), "Test Entity from JAR"));
+        root.addCatalog(testEntitiesJavaCatalog.dto);
 
-        CatalogDo osgiCatalog = new CatalogDo(CatalogDto.newNamedInstance("OSGi",
+        CatalogDo testEntitiesJavaCatalogScanning = new CatalogDo(CatalogDto.newNamedInstance("Test Entities from Java Scanning", null));
+        testEntitiesJavaCatalogScanning.addToClasspath(MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests")));
+        testEntitiesJavaCatalogScanning.setClasspathScanForEntities(CatalogScanningModes.ANNOTATIONS);
+        root.addCatalog(testEntitiesJavaCatalogScanning.dto);
+        
+        CatalogDo osgiCatalog = new CatalogDo(CatalogDto.newNamedInstance("Test Entities from OSGi",
                 "A catalog whose entries define their libraries as a list of OSGi bundles"));
         osgiCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
-        CatalogLibrariesDto m3Context = new CatalogLibrariesDto();
-        m3Context.addBundle("file://~/.m2/repository/io/cloudsoft/brooklyn-mapr/1.0.0-SNAPSHOT/brooklyn-mapr.jar");
-        osgiCatalog.addEntry(CatalogItemDtoAbstract.newTemplate("M3App", "io.brooklyn.mapr.M3App", "M3 Application",
-                "Description", m3Context));
+        CatalogEntityItemDto osgiEntity = CatalogItemDtoAbstract.newEntityFromJava(TestEntity.class.getCanonicalName(), "Test Entity from OSGi");
+        // NB: this is not actually an OSGi bundle, but it's okay as we don't instantiate the bundles ahead of time (currently)
+        osgiEntity.libraries.addBundle(MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests")));
+        testEntitiesJavaCatalog.addEntry(osgiEntity);
         root.addCatalog(osgiCatalog.dto);
 
-        root.addCatalog(CatalogDto.newLinkedInstance("http://cloudsoftcorp.com/amp-brooklyn-catalog.xml"));
-        root.addCatalog(CatalogDto.newLinkedInstance("http://microsoot.com/oofice-catalog.xml"));
+        root.addCatalog(CatalogDto.newLinkedInstance("classpath://brooklyn-catalog-empty.xml"));
         return root.dto;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampPlatform.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampPlatform.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampPlatform.java
index f0f2b9d..32102ee 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampPlatform.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/BrooklynCampPlatform.java
@@ -5,8 +5,8 @@ import io.brooklyn.camp.CampPlatform;
 import io.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
 import io.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslInterpreter;
 import io.brooklyn.camp.brooklyn.spi.platform.BrooklynImmutableCampPlatform;
-import io.brooklyn.camp.brooklyn.spi.platform.HasBrooklynManagementContext;
 import io.brooklyn.camp.spi.PlatformRootSummary;
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
 import brooklyn.config.BrooklynProperties;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.ManagementContext.PropertiesReloadListener;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 2652c59..fbdd5ec 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -1,12 +1,10 @@
 package io.brooklyn.camp.brooklyn.spi.creation;
 
 import io.brooklyn.camp.CampPlatform;
-import io.brooklyn.camp.brooklyn.spi.platform.HasBrooklynManagementContext;
 import io.brooklyn.camp.spi.Assembly;
 import io.brooklyn.camp.spi.AssemblyTemplate;
 import io.brooklyn.camp.spi.PlatformComponentTemplate;
 import io.brooklyn.camp.spi.collection.ResolvableLink;
-import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 
 import java.lang.reflect.Constructor;
 import java.util.LinkedHashMap;
@@ -17,6 +15,8 @@ import java.util.Map.Entry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.config.ConfigKey;
@@ -44,7 +44,7 @@ import brooklyn.util.text.Strings;
 
 import com.google.common.collect.Maps;
 
-public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateInstantiator {
+public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator {
 
     private static final Logger log = LoggerFactory.getLogger(BrooklynAssemblyTemplateInstantiator.class);
     
@@ -76,6 +76,11 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
         }
     }
 
+    public EntitySpec<?> createSpec(AssemblyTemplate template, CampPlatform platform) {
+        // TODO rewrite this class so everything below returns a spec, then rewrite above just to instantiate (and start?) the spec
+        throw new UnsupportedOperationException();
+    }
+    
     protected Application createApplicationFromCatalog(CampPlatform platform, CatalogItem<?,?> item, AssemblyTemplate template) {
         ManagementContext mgmt = getBrooklynManagementContext(platform);
 
@@ -112,9 +117,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
                 appBuilder.configure( convertFlagsToKeys(appBuilder.getType(), configO) );
                 instance = appBuilder.manage(mgmt);
                 
-                List<Location> locations = new BrooklynYamlLocationResolver(mgmt).resolveLocations(template.getCustomAttributes(), false);
-                if (locations!=null)
-                    ((EntityInternal)instance).addLocations(locations);
+                applyLocations(mgmt, template, instance);
                 
             } else if (Application.class.isAssignableFrom(clazz)) {
                 // TODO use resolver's configureEntitySpec instead
@@ -126,9 +129,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
                 log.info("CAMP placing '{}' under management", instance);
                 Entities.startManagement(instance, mgmt);
                 
-                List<Location> locations = new BrooklynYamlLocationResolver(mgmt).resolveLocations(template.getCustomAttributes(), false);
-                if (locations!=null)
-                    ((EntityInternal)instance).addLocations(locations);
+                applyLocations(mgmt, template, instance);
                 
             } else {
                 throw new IllegalArgumentException("Class "+clazz+" must extend one of ApplicationBuilder or Application");
@@ -142,6 +143,12 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
         }
     }
 
+    private void applyLocations(ManagementContext mgmt, AssemblyTemplate template, final Application instance) {
+        List<Location> locations = new BrooklynYamlLocationResolver(mgmt).resolveLocations(template.getCustomAttributes(), false);
+        if (locations!=null)
+            ((EntityInternal)instance).addLocations(locations);
+    }
+
     private ManagementContext getBrooklynManagementContext(CampPlatform platform) {
         return ((HasBrooklynManagementContext)platform).getBrooklynManagementContext();
     }
@@ -216,6 +223,13 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
 
         Map<Entity, EntitySpec<?>> rootEntities = Maps.newLinkedHashMap();
         Map<Entity, EntitySpec<?>> allEntities = Maps.newLinkedHashMap();
+        /* FIXME there is a subtlety here, and tests failing;
+         * OT1H we might not want/need the wrapper application if we are creating a single one,   
+         * but OTOH we might need a guarantee of an app at root, if we are creating certain nested entities
+         * 
+         * i (alex) think the solution is to use the new createSpec(...) and interrogate it
+         * to see if we need the wrapper or not
+         */
         buildEntities(template, rootEntities, allEntities, mgmt);
         
         EntitySpec<StartableApplication> appSpec;
@@ -230,11 +244,12 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateIns
             Entry<Entity, EntitySpec<?>> entry = rootEntities.entrySet().iterator().next();
             app = (StartableApplication)entry.getKey();
             appSpec = (EntitySpec<StartableApplication>)entry.getValue();
+            applyLocations(mgmt, template, app);
         }
         
         initEntities(mgmt, allEntities);
         
-        log.info("CAMP placing '{}' under management", appSpec);
+        log.info("CAMP placing '{}' under`` management", appSpec);
         Entities.startManagement(app, mgmt);
 
         return app;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
index e52327f..8ddcdda 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
@@ -16,6 +16,7 @@ import io.brooklyn.camp.spi.PlatformTransaction;
 import io.brooklyn.camp.spi.collection.BasicResourceLookup;
 import io.brooklyn.camp.spi.collection.ResourceLookup;
 import io.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
 import brooklyn.management.ManagementContext;
 
 /** Immutable CAMP platform which reflects things in the underlying Brooklyn system */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/HasBrooklynManagementContext.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/HasBrooklynManagementContext.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/HasBrooklynManagementContext.java
deleted file mode 100644
index a91a32a..0000000
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/platform/HasBrooklynManagementContext.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package io.brooklyn.camp.brooklyn.spi.platform;
-
-import brooklyn.management.ManagementContext;
-
-public interface HasBrooklynManagementContext {
-
-    public ManagementContext getBrooklynManagementContext();
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EmptySoftwareProcessYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EmptySoftwareProcessYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EmptySoftwareProcessYamlTest.java
index f5bea03..c4703e8 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EmptySoftwareProcessYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EmptySoftwareProcessYamlTest.java
@@ -55,14 +55,14 @@ public class EmptySoftwareProcessYamlTest extends AbstractYamlTest {
 
     @Test
     // for issue #1377
-    // currently provisions in the loopback-on-app location, rather surprisingly;
-    // but not sure that's the desired behaviour
     public void testWithAppAndEntityLocations() throws Exception {
         Entity app = createAndStartApplication(Streams.newReaderWithContents("services:\n"+
             "- serviceType: "+EmptySoftwareProcess.class.getName()+"\n"+
             "  location: localhost:(name=localhost on entity)"+"\n"+
             "location: byon:(hosts=\"127.0.0.1\", name=loopback on app)"));
         waitForApplicationTasks(app);
+        Entities.dumpInfo(app);
+        
         Assert.assertEquals(app.getLocations().size(), 1);
         Assert.assertEquals(app.getChildren().size(), 1);
         Entity entity = app.getChildren().iterator().next();
@@ -75,6 +75,7 @@ public class EmptySoftwareProcessYamlTest extends AbstractYamlTest {
         Assert.assertEquals(entityLocationIterator.next().getDisplayName(), "localhost on entity");
         Location actualMachine = entityLocationIterator.next();
         Assert.assertTrue(actualMachine instanceof SshMachineLocation, "wrong location: "+actualMachine);
+        // TODO this, below, probably should be 'localhost on entity', see #1377
         Assert.assertEquals(actualMachine.getParent().getDisplayName(), "loopback on app");
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/cli/src/main/java/brooklyn/cli/Main.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/brooklyn/cli/Main.java b/usage/cli/src/main/java/brooklyn/cli/Main.java
index 339c0fe..0a0e67b 100644
--- a/usage/cli/src/main/java/brooklyn/cli/Main.java
+++ b/usage/cli/src/main/java/brooklyn/cli/Main.java
@@ -402,7 +402,13 @@ public class Main {
             BrooklynServerDetails server = launcher.getServerDetails();
             ManagementContext ctx = server.getManagementContext();
             
-            populateCatalog(launcher.getServerDetails().getManagementContext().getCatalog());
+            try {
+                populateCatalog(launcher.getServerDetails().getManagementContext().getCatalog());
+            } catch (Exception e) {
+                Exceptions.propagateIfFatal(e);
+                // don't fail to start just because catalog is not available
+                log.error("Error populating catalog: "+e, e);
+            }
 
             if (verbose) {
                 Entities.dumpInfo(launcher.getApplications());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
index 8fba37b..9e8c01a 100644
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
@@ -32,6 +32,7 @@ import brooklyn.entity.Application;
 import brooklyn.entity.basic.ApplicationBuilder;
 import brooklyn.entity.basic.BrooklynShutdownHooks;
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.RebindManager;
@@ -628,9 +629,8 @@ public class BrooklynLauncher {
     }
 
     protected Application getAppFromYaml(String input) {
-        AssemblyTemplate at = campPlatform.pdp()
-                .registerDeploymentPlan(new StringReader(input));
-         BrooklynAssemblyTemplateInstantiator instantiator;
+        AssemblyTemplate at = campPlatform.pdp().registerDeploymentPlan(new StringReader(input));
+        BrooklynAssemblyTemplateInstantiator instantiator;
         try {
             AssemblyTemplateInstantiator ati = at.getInstantiator().newInstance();
             if (ati instanceof BrooklynAssemblyTemplateInstantiator) {
@@ -641,7 +641,9 @@ public class BrooklynLauncher {
         } catch (Exception e) {
             throw Exceptions.propagate(e);
         }
-        return instantiator.create(at, campPlatform);
+        Application app = instantiator.create(at, campPlatform);
+//        ((EntityInternal)app).addLocations(XXX);
+        return app;
     }
     
     protected void startApps() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/468d7885/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
index 2b8151b..6dc15ad 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
@@ -8,6 +8,7 @@ import javax.ws.rs.core.Context;
 
 import org.codehaus.jackson.map.ObjectMapper;
 
+import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.BrooklynServiceAttributes;
 import brooklyn.management.ManagementContext;
 import brooklyn.rest.util.BrooklynRestResourceUtils;
@@ -63,9 +64,7 @@ public abstract class AbstractBrooklynRestResource {
     }
 
     protected CampPlatform camp() {
-        CampPlatform camp = mgmt().getConfig().getConfig(BrooklynCampConstants.CAMP_PLATFORM);
-        if (camp!=null) return camp;
-        throw new IllegalStateException("CAMP platform server not enabled");
+        return BrooklynServerConfig.getCampPlatform(mgmt()).get();
     }
     
 }