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 2015/09/15 18:53:29 UTC

[10/15] incubator-brooklyn git commit: allow CAMP to instantiate non-CAMP items, and tidy esp generics and errors

allow CAMP to instantiate non-CAMP items, and tidy esp generics and errors

previously if a CAMP plan referred to a catalog item, it assumed that item
was parsable as CAMP.  now it can delegate to the plan transformers.
this is messier than it should be because it is also looking to see if the
type is a java type, and we did self-referencing checks; would be nice to
make the resolution logic more straightforward, and shouldn't be too hard.

this also tries to make the generics a bit nicer, with more "? extends T" in places,
for catalog items.  it's a bit better in Eclipse but now introduces awful cases
where maven complains and eclipse doesn't.  we should back out a lot of the generics,
perhaps as part of making the catalog much more forgiving about types.

also adds more + cleaner error reporting when resolving plans.


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

Branch: refs/heads/master
Commit: eee436133cc8a227b6c0da53b6ca597d9f7e360b
Parents: 02d86fc
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Sep 11 10:21:09 2015 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Sep 11 10:54:42 2015 +0100

----------------------------------------------------------------------
 .../brooklyn/api/catalog/BrooklynCatalog.java   |  4 +-
 .../catalog/internal/BasicBrooklynCatalog.java  | 35 ++++++++---
 .../core/location/CatalogLocationResolver.java  |  9 ++-
 .../core/mgmt/EntityManagementUtils.java        |  9 ++-
 .../brooklyn/core/plan/PlanToSpecFactory.java   |  6 +-
 .../core/plan/PlanToSpecTransformer.java        |  2 +-
 .../core/plan/XmlPlanToSpecTransformer.java     |  8 +--
 .../BrooklynAssemblyTemplateInstantiator.java   | 27 +++++----
 .../BrooklynComponentTemplateResolver.java      | 42 +++++++++----
 .../BrooklynEntityDecorationResolver.java       | 11 ++--
 .../spi/creation/BrooklynEntityMatcher.java     |  1 +
 .../spi/creation/CampToSpecTransformer.java     | 64 ++++++++++++--------
 .../CatalogOsgiVersionMoreEntityTest.java       |  3 +-
 .../brooklyn/catalog/CatalogYamlEntityTest.java |  3 +-
 .../catalog/CatalogYamlLocationTest.java        |  5 +-
 .../brooklyn/test/lite/CampYamlLiteTest.java    |  3 +-
 .../main/java/org/apache/brooklyn/cli/Main.java |  3 +-
 .../rest/resources/CatalogResource.java         |  6 +-
 .../rest/transform/CatalogTransformer.java      | 14 ++---
 19 files changed, 157 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/api/src/main/java/org/apache/brooklyn/api/catalog/BrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/catalog/BrooklynCatalog.java b/api/src/main/java/org/apache/brooklyn/api/catalog/BrooklynCatalog.java
index 21002d9..0bc0dfe 100644
--- a/api/src/main/java/org/apache/brooklyn/api/catalog/BrooklynCatalog.java
+++ b/api/src/main/java/org/apache/brooklyn/api/catalog/BrooklynCatalog.java
@@ -21,6 +21,8 @@ package org.apache.brooklyn.api.catalog;
 import java.util.Collection;
 import java.util.NoSuchElementException;
 
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+
 import com.google.common.base.Predicate;
 
 public interface BrooklynCatalog {
@@ -76,7 +78,7 @@ public interface BrooklynCatalog {
 
     /** creates a spec for the given catalog item, throwing exceptions if any problems */
     // TODO this should be cached on the item and renamed getSpec(...), else we re-create it too often (every time catalog is listed)
-    <T,SpecT> SpecT createSpec(CatalogItem<T,SpecT> item);
+    <T, SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createSpec(CatalogItem<T, SpecT> item);
     
     /** throws exceptions if any problems 
      * @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index b2ec24d..cc4cffe 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -26,7 +26,6 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
-import java.util.Set;
 
 import javax.annotation.Nullable;
 
@@ -34,6 +33,7 @@ import org.apache.brooklyn.api.catalog.BrooklynCatalog;
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
 import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
@@ -312,7 +312,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
 
     @Override
-    public <T, SpecT> SpecT createSpec(CatalogItem<T, SpecT> item) {
+    public <T, SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createSpec(CatalogItem<T, SpecT> item) {
         if (item == null) return null;
         @SuppressWarnings("unchecked")
         CatalogItemDo<T,SpecT> loadedItem = (CatalogItemDo<T, SpecT>) getCatalogItemDo(item.getSymbolicName(), item.getVersion());
@@ -321,7 +321,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         if (specType==null) return null;
 
         if (loadedItem.getPlanYaml() != null) {
-            SpecT yamlSpec = (SpecT) EntityManagementUtils.createCatalogSpec(mgmt, loadedItem);
+            SpecT yamlSpec = EntityManagementUtils.createCatalogSpec(mgmt, loadedItem);
             if (yamlSpec != null) {
                 return yamlSpec;
             }
@@ -348,7 +348,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         }
 
         if (spec==null) 
-            throw new IllegalStateException("Unknown how to create instance of "+this);
+            throw new IllegalStateException("No known mechanism to create instance of "+item);
 
         return spec;
     }
@@ -516,9 +516,11 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
 
         PlanInterpreterGuessingType planInterpreter = new PlanInterpreterGuessingType(null, item, sourceYaml, itemType, libraryBundles, result).reconstruct();
         if (!planInterpreter.isResolved()) {
-            throw Exceptions.create("Could not resolve item "
-                + (Strings.isNonBlank(id) ? id : Strings.isNonBlank(symbolicName) ? symbolicName : Strings.isNonBlank(name) ? name : "<no-name>")
-                + ":\n"+sourceYaml, planInterpreter.getErrors());
+            throw Exceptions.create("Could not resolve item"
+                + (Strings.isNonBlank(id) ? " "+id : Strings.isNonBlank(symbolicName) ? " "+symbolicName : Strings.isNonBlank(name) ? name : "")
+                // better not to show yaml, takes up lots of space, and with multiple plan transformers there might be multiple errors 
+//                + ":\n"+sourceYaml
+                , planInterpreter.getErrors());
         }
         itemType = planInterpreter.getCatalogItemType();
         Map<?, ?> itemAsMap = planInterpreter.getItem();
@@ -543,6 +545,8 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
             } else {
                 symbolicName = setFromItemIfUnset(symbolicName, itemAsMap, "id");
                 symbolicName = setFromItemIfUnset(symbolicName, itemAsMap, "name");
+                // TODO we should let the plan transformer give us this
+                symbolicName = setFromItemIfUnset(symbolicName, itemAsMap, "template_name");
                 if (Strings.isBlank(symbolicName)) {
                     log.error("Can't infer catalog item symbolicName from the following plan:\n" + sourceYaml);
                     throw new IllegalStateException("Can't infer catalog item symbolicName from catalog item metadata");
@@ -563,6 +567,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
                 version = CatalogUtils.getVersionFromVersionedId(name);
             } else if (Strings.isBlank(version)) {
                 version = setFromItemIfUnset(version, itemAsMap, "version");
+                version = setFromItemIfUnset(version, itemAsMap, "template_version");
                 if (version==null) {
                     log.warn("No version specified for catalog item " + symbolicName + ". Using default value.");
                     version = null;
@@ -685,6 +690,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         String planYaml;
         boolean resolved = false;
         List<Exception> errors = MutableList.of();
+        List<Exception> entityErrors = MutableList.of();
         
         public PlanInterpreterGuessingType(@Nullable String id, Object item, String itemYaml, @Nullable CatalogItemType optionalCiType, 
                 Collection<CatalogBundle> libraryBundles, List<CatalogItemDtoAbstract<?,?>> itemsDefinedSoFar) {
@@ -731,6 +737,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         /** Returns potentially useful errors encountered while guessing types. 
          * May only be available where the type is known. */
         public List<Exception> getErrors() {
+            if (errors.isEmpty()) return entityErrors;
             return errors;
         }
         
@@ -778,10 +785,12 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
             
             // then try parsing plan - this will use loader
             try {
-                CatalogItem<?, ?> itemToAttempt = createItemBuilder(candidateCiType, getIdWithRandomDefault(), DEFAULT_VERSION)
+                @SuppressWarnings("rawtypes")
+                CatalogItem itemToAttempt = createItemBuilder(candidateCiType, getIdWithRandomDefault(), DEFAULT_VERSION)
                     .plan(candidateYaml)
                     .libraries(libraryBundles)
                     .build();
+                @SuppressWarnings("unchecked")
                 Object spec = EntityManagementUtils.createCatalogSpec(mgmt, itemToAttempt);
                 if (spec!=null) {
                     catalogItemType = candidateCiType;
@@ -800,7 +809,11 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
                     // (when we're not given a key, the previous block should apply)
                     errors.add(e);
                 } else {
-                    // all other cases, the error is probably due to us not getting the type right, ignore it
+                    // all other cases, the error is probably due to us not getting the type right, probably ignore it
+                    // but cache it if we've checked entity, we'll use that as fallback errors
+                    if (candidateCiType==CatalogItemType.ENTITY) {
+                        entityErrors.add(e);
+                    }
                     if (log.isTraceEnabled())
                         log.trace("Guessing type of plan, it looks like it isn't "+candidateCiType+"/"+key+": "+e);
                 }
@@ -810,10 +823,12 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
             if (type!=null && key!=null) {
                 try {
                     String cutDownYaml = key + ":\n" + makeAsIndentedList("type: "+type);
-                    CatalogItem<?, ?> itemToAttempt = createItemBuilder(candidateCiType, getIdWithRandomDefault(), DEFAULT_VERSION)
+                    @SuppressWarnings("rawtypes")
+                    CatalogItem itemToAttempt = createItemBuilder(candidateCiType, getIdWithRandomDefault(), DEFAULT_VERSION)
                             .plan(cutDownYaml)
                             .libraries(libraryBundles)
                             .build();
+                    @SuppressWarnings("unchecked")
                     Object cutdownSpec = EntityManagementUtils.createCatalogSpec(mgmt, itemToAttempt);
                     if (cutdownSpec!=null) {
                         catalogItemType = candidateCiType;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/core/src/main/java/org/apache/brooklyn/core/location/CatalogLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/CatalogLocationResolver.java b/core/src/main/java/org/apache/brooklyn/core/location/CatalogLocationResolver.java
index 2cc7b9f..db4c0d5 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/CatalogLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/CatalogLocationResolver.java
@@ -22,8 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.util.Map;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationRegistry;
@@ -31,6 +29,8 @@ import org.apache.brooklyn.api.location.LocationResolver;
 import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Given a location spec in the form {@code brooklyn.catalog:<symbolicName>:<version>}, 
@@ -38,7 +38,6 @@ import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
  */
 public class CatalogLocationResolver implements LocationResolver {
 
-    @SuppressWarnings("unused")
     private static final Logger log = LoggerFactory.getLogger(CatalogLocationResolver.class);
 
     public static final String NAME = "brooklyn.catalog";
@@ -61,8 +60,8 @@ public class CatalogLocationResolver implements LocationResolver {
             log.warn("Use of deprecated catalog item "+item.getSymbolicName()+":"+item.getVersion());
         }
         
-        LocationSpec<?> origLocSpec = managementContext.getCatalog().createSpec((CatalogItem<Location, LocationSpec<?>>)item);
-        LocationSpec<?> locSpec = LocationSpec.create(origLocSpec)
+        LocationSpec origLocSpec = (LocationSpec) managementContext.getCatalog().createSpec((CatalogItem)item);
+        LocationSpec locSpec = LocationSpec.create(origLocSpec)
                 .configure(locationFlags);
         return managementContext.getLocationManager().createLocation(locSpec);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/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 b86a0a8..3a46416 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
@@ -96,12 +96,11 @@ public class EntityManagementUtils {
         }).get();
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public static AbstractBrooklynObjectSpec<?, ?> createCatalogSpec(ManagementContext mgmt, final CatalogItem<?, ?> item) {
-        return PlanToSpecFactory.attemptWithLoaders(mgmt, new Function<PlanToSpecTransformer, AbstractBrooklynObjectSpec<?, ?>>() {
+    public static <T,SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(ManagementContext mgmt, final CatalogItem<T, SpecT> item) {
+        return PlanToSpecFactory.attemptWithLoaders(mgmt, new Function<PlanToSpecTransformer, SpecT>() {
             @Override
-            public AbstractBrooklynObjectSpec<?, ?> apply(PlanToSpecTransformer input) {
-                return input.createCatalogSpec((CatalogItem)item);
+            public SpecT apply(PlanToSpecTransformer input) {
+                return input.createCatalogSpec(item);
             }
         }).get();
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
index 491a74e..3328545 100644
--- a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
@@ -25,6 +25,7 @@ import java.util.ServiceLoader;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
@@ -106,7 +107,7 @@ public class PlanToSpecFactory {
                     (Strings.isNonBlank(e.getMessage()) ? " ("+e.getMessage()+")" : ""));
             } catch (Throwable e) {
                 Exceptions.propagateIfFatal(e);
-                otherProblemsFromTransformers.add(new IllegalArgumentException("Transformer for "+t.getShortDescription()+" gave an error creating this plan: "+
+                otherProblemsFromTransformers.add(new PropagatedRuntimeException("Transformer for "+t.getShortDescription()+" gave an error creating this plan: "+
                     Exceptions.collapseText(e), e));
             }
         }
@@ -115,7 +116,8 @@ public class PlanToSpecFactory {
         if (!otherProblemsFromTransformers.isEmpty()) {
             // at least one thought he could do it
             log.debug("Plan could not be transformed; failure will be propagated (other transformers tried = "+transformersWhoDontSupport+"): "+otherProblemsFromTransformers);
-            result = Exceptions.create(null, otherProblemsFromTransformers);
+            result = otherProblemsFromTransformers.size()==1 ? Exceptions.create(null, otherProblemsFromTransformers) :
+                Exceptions.create("Plan transformers all failed", otherProblemsFromTransformers);
         } else {
             result = new PlanNotRecognizedException("Invalid plan; format could not be recognized, trying with: "+transformersWhoDontSupport);
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecTransformer.java b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecTransformer.java
index 63d5c1f..c6e3a4a 100644
--- a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecTransformer.java
@@ -56,6 +56,6 @@ public interface PlanToSpecTransformer extends ManagementContextInjectable {
      * implementations will typically look at the {@link CatalogItem#getCatalogItemType()} first.
      * <p>
      * should throw {@link PlanNotRecognizedException} if this transformer does not know what to do with the plan. */
-    <T,SpecT extends AbstractBrooklynObjectSpec<T, SpecT>> AbstractBrooklynObjectSpec<T, SpecT> createCatalogSpec(CatalogItem<T, SpecT> item) throws PlanNotRecognizedException;
+    <T,SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(CatalogItem<T, SpecT> item) throws PlanNotRecognizedException;
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java b/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
index 5fc103d..a535932 100644
--- a/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
+++ b/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
@@ -72,15 +72,15 @@ public class XmlPlanToSpecTransformer implements PlanToSpecTransformer {
         }
     }
 
-    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @SuppressWarnings({ "unchecked" })
     @Override
-    public <T, SpecT extends AbstractBrooklynObjectSpec<T, SpecT>> AbstractBrooklynObjectSpec<T, SpecT> createCatalogSpec(CatalogItem<T, SpecT> item) {
+    public <T, SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(CatalogItem<T, SpecT> item) {
         if (item.getPlanYaml()==null) throw new PlanNotRecognizedException("Plan is null");
         if (item.getCatalogItemType()==CatalogItemType.ENTITY) {
-            return (EntitySpec)toEntitySpec(parseXml(item.getPlanYaml()), 1);
+            return (SpecT)toEntitySpec(parseXml(item.getPlanYaml()), 1);
         }
         if (item.getCatalogItemType()==CatalogItemType.TEMPLATE) {
-            return (EntitySpec)toEntitySpec(parseXml(item.getPlanYaml()), 0);
+            return (SpecT)toEntitySpec(parseXml(item.getPlanYaml()), 0);
         }
         throw new PlanNotRecognizedException("Type "+item.getCatalogItemType()+" not supported");
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/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 d582c45..63f111a 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
@@ -94,11 +94,11 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
 
         BrooklynComponentTemplateResolver resolver = BrooklynComponentTemplateResolver.Factory.newInstance(
             loader, buildWrapperAppTemplate(template));
-        EntitySpec<? extends Application> app = resolver.resolveSpec(null);
+        EntitySpec<? extends Application> app = resolver.resolveSpec(null, false);
         app.configure(EntityManagementUtils.WRAPPER_APP_MARKER, Boolean.TRUE);
 
         // first build the children into an empty shell app
-        List<EntitySpec<?>> childSpecs = buildTemplateServicesAsSpecs(loader, template, platform);
+        List<EntitySpec<?>> childSpecs = buildTemplateServicesAsSpecs(loader, template, platform, true);
         for (EntitySpec<?> childSpec : childSpecs) {
             app.child(childSpec);
         }
@@ -130,28 +130,30 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         return EntityManagementUtils.canPromoteWrappedApplication(app);
     }
 
-    private List<EntitySpec<?>> buildTemplateServicesAsSpecs(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform) {
-        return buildTemplateServicesAsSpecsImpl(loader, template, platform, Sets.<String>newLinkedHashSet());
+    private List<EntitySpec<?>> buildTemplateServicesAsSpecs(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform, boolean canUseOtherTransformers) {
+        return buildTemplateServicesAsSpecsImpl(loader, template, platform, Sets.<String>newLinkedHashSet(), canUseOtherTransformers);
     }
 
-    private List<EntitySpec<?>> buildTemplateServicesAsSpecsImpl(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform, Set<String> encounteredCatalogTypes) {
+    private List<EntitySpec<?>> buildTemplateServicesAsSpecsImpl(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform, Set<String> encounteredCatalogTypes, boolean canUseOtherTransformers) {
         List<EntitySpec<?>> result = Lists.newArrayList();
 
         for (ResolvableLink<PlatformComponentTemplate> ctl: template.getPlatformComponentTemplates().links()) {
             PlatformComponentTemplate appChildComponentTemplate = ctl.resolve();
             BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, appChildComponentTemplate);
-            EntitySpec<?> spec = resolveSpec(platform, ResourceUtils.create(this), entityResolver, encounteredCatalogTypes);
-
+            EntitySpec<?> spec;
+            spec = resolveCampSpec(platform, ResourceUtils.create(this), entityResolver, encounteredCatalogTypes, canUseOtherTransformers);
             result.add(spec);
         }
         return result;
     }
 
-    static EntitySpec<?> resolveSpec(
+    static EntitySpec<?> resolveCampSpec(
             CampPlatform platform,
             ResourceUtils ru,
             BrooklynComponentTemplateResolver entityResolver,
-            Set<String> encounteredCatalogTypes) {
+            Set<String> encounteredCatalogTypes,
+            boolean canUseOtherTransformers) {
+        
         String brooklynType = entityResolver.getServiceTypeResolver().getBrooklynType(entityResolver.getDeclaredType());
         CatalogItem<Entity, EntitySpec<?>> item = entityResolver.getServiceTypeResolver().getCatalogItem(entityResolver, entityResolver.getDeclaredType());
 
@@ -177,7 +179,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
 
         if (spec == null) {
             // load from java or yaml
-            spec = entityResolver.resolveSpec(encounteredCatalogTypes);
+            spec = entityResolver.resolveSpec(encounteredCatalogTypes, canUseOtherTransformers);
         }
 
         return spec;
@@ -206,11 +208,12 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         }
     }
 
-    static EntitySpec<?> resolveCatalogYamlReferenceSpec(
+    static EntitySpec<?> resolveCatalogYamlReferenceCampSpec(
             CampPlatform platform,
             CatalogItem<Entity, EntitySpec<?>> item,
             Set<String> encounteredCatalogTypes) {
         ManagementContext mgmt = getManagementContext(platform);
+
         String yaml = item.getPlanYaml();
         Reader input = new StringReader(yaml);
         BrooklynClassLoadingContext itemLoader = CatalogUtils.newClassLoadingContext(mgmt, item);
@@ -251,7 +254,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         try {
             AssemblyTemplateInstantiator ati = template.getInstantiator().newInstance();
             if (ati instanceof BrooklynAssemblyTemplateInstantiator) {
-                List<EntitySpec<?>> specs = ((BrooklynAssemblyTemplateInstantiator)ati).buildTemplateServicesAsSpecsImpl(itemLoader, template, platform, encounteredCatalogTypes);
+                List<EntitySpec<?>> specs = ((BrooklynAssemblyTemplateInstantiator)ati).buildTemplateServicesAsSpecsImpl(itemLoader, template, platform, encounteredCatalogTypes, false);
                 if (specs.size() > 1) {
                     throw new UnsupportedOperationException("Only supporting single service in catalog item currently: got "+specs);
                 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 52e6fb1..aef991f 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -49,6 +49,7 @@ import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.entity.AbstractEntity;
 import org.apache.brooklyn.core.mgmt.BrooklynTags;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
+import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
 import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
@@ -61,6 +62,7 @@ import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.flags.FlagUtils;
 import org.apache.brooklyn.util.core.flags.FlagUtils.FlagConfigKeyAndValueRecord;
 import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.javalang.Reflections;
 import org.apache.brooklyn.util.text.Strings;
@@ -217,19 +219,32 @@ public class BrooklynComponentTemplateResolver {
     }
 
     /** resolves the spec, updating the loader if a catalog item is loaded */
-    protected <T extends Entity> EntitySpec<T> resolveSpec(Set<String> encounteredCatalogTypes) {
+    @SuppressWarnings("unchecked")
+    protected <T extends Entity> EntitySpec<T> resolveSpec(Set<String> encounteredCatalogTypes, boolean canUseOtherTransformers) {
         if (alreadyBuilt.getAndSet(true))
             throw new IllegalStateException("Spec can only be used once: "+this);
 
-        EntitySpec<T> spec = createSpec(encounteredCatalogTypes);
-        populateSpec(spec);
-
-        return spec;
+        CatalogItem<Entity, EntitySpec<?>> item = getServiceTypeResolver().getCatalogItem(this, getDeclaredType());
+        try {
+            EntitySpec<T> spec = createSpec(item, encounteredCatalogTypes);
+            populateSpec(spec);
+            return spec;
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            
+            // maybe it requires a different transformer? TODO better would be to know this from a transformer type on the catalog item type
+            if (item!=null && canUseOtherTransformers) {
+                log.debug("Could not resolve child "+item+" as CAMP; trying other transformers: "+e);
+                // should only be called when resolving children. and encountered types should probably be empty. 
+                return (EntitySpec<T>) EntityManagementUtils.createCatalogSpec(mgmt, (CatalogItem) item);
+            } else {
+                throw Exceptions.propagate(e);
+            }
+        }
     }
 
     @SuppressWarnings({ "unchecked" })
-    protected <T extends Entity> EntitySpec<T> createSpec(Set<String> encounteredCatalogTypes) {
-        CatalogItem<Entity, EntitySpec<?>> item = getServiceTypeResolver().getCatalogItem(this, getDeclaredType());
+    protected <T extends Entity> EntitySpec<T> createSpec(CatalogItem<Entity, EntitySpec<?>> item, Set<String> encounteredCatalogTypes) {
         if (item == null) {
             // ignore; presumably a java type or some such?
         } else if (item.isDisabled()) {
@@ -262,11 +277,12 @@ public class BrooklynComponentTemplateResolver {
             }
             return createSpecFromJavaType();
 
-        // Only case that's left is a catalog item with YAML content - try to parse it recursively
-        // including it's OSGi bundles in the loader classpath.
+        // Only case that's left is a catalog item with CAMP YAML content - try to parse it recursively
+        // including its OSGi bundles in the loader classpath.
         } else {
-            // TODO perhaps migrate to catalog.createSpec ?
-            EntitySpec<?> spec = BrooklynAssemblyTemplateInstantiator.resolveCatalogYamlReferenceSpec(getCampPlatform(), item, encounteredCatalogTypes);
+            // TODO if it isn't camp it will throw. better would be to know the transformers type for the item!
+
+            EntitySpec<?> spec = BrooklynAssemblyTemplateInstantiator.resolveCatalogYamlReferenceCampSpec(getCampPlatform(), item, encounteredCatalogTypes);
             spec.catalogItemId(item.getId());
             
             return (EntitySpec<T>)spec;
@@ -319,7 +335,7 @@ public class BrooklynComponentTemplateResolver {
             Iterable<Map<String,?>> children = (Iterable<Map<String,?>>)childrenObj;
             for (Map<String,?> childAttrs : children) {
                 BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, childAttrs);
-                EntitySpec<? extends Entity> childSpec = BrooklynAssemblyTemplateInstantiator.resolveSpec(getCampPlatform(), ResourceUtils.create(this), entityResolver, encounteredCatalogTypes);
+                EntitySpec<? extends Entity> childSpec = BrooklynAssemblyTemplateInstantiator.resolveCampSpec(getCampPlatform(), ResourceUtils.create(this), entityResolver, encounteredCatalogTypes, true);
                 spec.child(childSpec);
             }
         }
@@ -485,7 +501,7 @@ public class BrooklynComponentTemplateResolver {
                 @SuppressWarnings("unchecked")
                 Map<String, Object> resolvedConfig = (Map<String, Object>)transformSpecialFlags(specConfig.getSpecConfiguration());
                 specConfig.setSpecConfiguration(resolvedConfig);
-                return Factory.newInstance(getLoader(), specConfig.getSpecConfiguration()).resolveSpec(null);
+                return Factory.newInstance(getLoader(), specConfig.getSpecConfiguration()).resolveSpec(null, false);
             }
             if (flag instanceof ManagementContextInjectable) {
                 log.debug("Injecting Brooklyn management context info object: {}", flag);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
index eee5834..a7a7530 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
@@ -109,10 +109,10 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
             String policyType = decoLoader.getTypeName().get();
             ManagementContext mgmt = instantiator.loader.getManagementContext();
             BrooklynCatalog catalog = mgmt.getCatalog();
-            CatalogItem<?, ?> item = getPolicyCatalogItem(catalog, policyType);
+            CatalogItem<Policy, PolicySpec<?>> item = getPolicyCatalogItem(catalog, policyType);
             PolicySpec<? extends Policy> spec;
             if (item != null) {
-                spec = (PolicySpec<? extends Policy>) catalog.createSpec(item);
+                spec = (PolicySpec) catalog.createSpec((CatalogItem) item);
                 spec.configure(decoLoader.getConfigMap());
             } else {
                 // this pattern of creating a spec could be simplified with a "Configurable" superinterface on *Spec  
@@ -121,13 +121,14 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
             }
             decorations.add(spec);
         }
-        private CatalogItem<?, ?> getPolicyCatalogItem(BrooklynCatalog catalog, String policyType) {
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        private CatalogItem<Policy, PolicySpec<?>> getPolicyCatalogItem(BrooklynCatalog catalog, String policyType) {
             if (CatalogUtils.looksLikeVersionedId(policyType)) {
                 String id = CatalogUtils.getIdFromVersionedId(policyType);
                 String version = CatalogUtils.getVersionFromVersionedId(policyType);
-                return catalog.getCatalogItem(id, version);
+                return (CatalogItem) catalog.getCatalogItem(id, version);
             } else {
-                return catalog.getCatalogItem(policyType, BrooklynCatalog.DEFAULT_VERSION);
+                return (CatalogItem) catalog.getCatalogItem(policyType, BrooklynCatalog.DEFAULT_VERSION);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
index 8a632e6..c0a2e19 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
@@ -64,6 +64,7 @@ public class BrooklynEntityMatcher implements PdpMatcher {
             Service service = (Service)deploymentPlanItem;
 
             String serviceType = service.getServiceType();
+            if (serviceType==null) throw new NullPointerException("Service must declare a type ("+service+")");
             BrooklynClassLoadingContext loader = BasicBrooklynCatalog.BrooklynLoaderTracker.getLoader();
             if (loader == null) loader = JavaBrooklynClassLoadingContext.create(mgmt);
             if (BrooklynComponentTemplateResolver.Factory.supportsType(loader, serviceType))

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
index 7ab200d..9b9f1ec 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
@@ -31,13 +31,18 @@ import org.apache.brooklyn.camp.spi.AssemblyTemplate;
 import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.plan.PlanNotRecognizedException;
 import org.apache.brooklyn.core.plan.PlanToSpecTransformer;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class CampToSpecTransformer implements PlanToSpecTransformer {
 
     public static final String YAML_CAMP_PLAN_TYPE = "org.apache.brooklyn.camp/yaml";
 
+    private static final Logger log = LoggerFactory.getLogger(CampToSpecTransformer.class);
+    
     private ManagementContext mgmt;
 
     @Override
@@ -52,34 +57,45 @@ public class CampToSpecTransformer implements PlanToSpecTransformer {
 
     @Override
     public EntitySpec<? extends Application> createApplicationSpec(String plan) {
-      CampPlatform camp = CampCatalogUtils.getCampPlatform(mgmt);
-      AssemblyTemplate at = camp.pdp().registerDeploymentPlan( new StringReader(plan) );
-      AssemblyTemplateInstantiator instantiator;
-      try {
-          instantiator = at.getInstantiator().newInstance();
-      } catch (Exception e) {
-          throw Exceptions.propagate(e);
-      }
-      if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
-          BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt);
-          return ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp, loader, true);
-      } else {
-          // The unknown instantiator can create the app (Assembly), but not a spec.
-          // Currently, all brooklyn plans should produce the above.
-          if (at.getPlatformComponentTemplates()==null || at.getPlatformComponentTemplates().isEmpty()) {
-              if (at.getCustomAttributes().containsKey("brooklyn.catalog"))
-                  throw new IllegalArgumentException("Unrecognized application blueprint format: expected an application, not a brooklyn.catalog");
-              throw new IllegalArgumentException("Unrecognized application blueprint format: no services defined");
-          }
-          // map this (expected) error to a nicer message
-          throw new IllegalArgumentException("Unrecognized application blueprint format");
-      }
+        try {
+            CampPlatform camp = CampCatalogUtils.getCampPlatform(mgmt);
+            AssemblyTemplate at = camp.pdp().registerDeploymentPlan( new StringReader(plan) );
+            AssemblyTemplateInstantiator instantiator;
+            try {
+                instantiator = at.getInstantiator().newInstance();
+            } catch (Exception e) {
+                throw Exceptions.propagate(e);
+            }
+            if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
+                BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt);
+                return ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp, loader, true);
+            } else {
+                // The unknown instantiator can create the app (Assembly), but not a spec.
+                // Currently, all brooklyn plans should produce the above.
+                if (at.getPlatformComponentTemplates()==null || at.getPlatformComponentTemplates().isEmpty()) {
+                    if (at.getCustomAttributes().containsKey("brooklyn.catalog"))
+                        throw new IllegalArgumentException("Unrecognized application blueprint format: expected an application, not a brooklyn.catalog");
+                    throw new IllegalArgumentException("Unrecognized application blueprint format: no services defined");
+                }
+                // map this (expected) error to a nicer message
+                throw new IllegalArgumentException("Unrecognized application blueprint format");
+            }
+        } catch (Exception e) {
+            if (e instanceof PlanNotRecognizedException) {
+                if (log.isTraceEnabled())
+                    log.debug("Failed to create entity from CAMP spec:\n" + plan, e);
+            } else {
+                if (log.isDebugEnabled())
+                    log.debug("Failed to create entity from CAMP spec:\n" + plan, e);
+            }
+            throw Exceptions.propagate(e);
+        }
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
     @Override
-    public <T, SpecT extends AbstractBrooklynObjectSpec<T, SpecT>> AbstractBrooklynObjectSpec<T, SpecT> createCatalogSpec(CatalogItem<T, SpecT> item) {
-        return (AbstractBrooklynObjectSpec<T, SpecT>) CampCatalogUtils.createSpec(mgmt, (CatalogItem)item);
+    public <T, SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(CatalogItem<T, SpecT> item) {
+        return (SpecT) CampCatalogUtils.createSpec(mgmt, (CatalogItem)item);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index f93f45b..de40d41 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -238,7 +238,8 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
         BrooklynCatalog catalog = mgmt().getCatalog();
         Iterable<CatalogItem<Object, Object>> items = catalog.getCatalogItems();
         for (CatalogItem<Object, Object> item: items) {
-            Object spec = catalog.createSpec(item);
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            Object spec = catalog.createSpec((CatalogItem)item);
             switch (item.getCatalogItemType()) {
                 case TEMPLATE:
                 case ENTITY:

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
index 0063916..7389190 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
@@ -525,7 +525,8 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
         addCatalogOSGiEntity(id);
         BrooklynCatalog catalog = mgmt().getCatalog();
         CatalogItem<?, ?> item = catalog.getCatalogItem(id, TEST_VERSION);
-        Object spec = catalog.createSpec(item);
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        Object spec = catalog.createSpec((CatalogItem) item);
         Assert.assertNotNull(spec);
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
index 868a8e6..e5a8457 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
@@ -105,8 +105,9 @@ public class CatalogYamlLocationTest extends AbstractYamlTest {
         assertEquals(Iterables.getOnlyElement(libs).getUrl(), Iterables.getOnlyElement(getOsgiLibraries()));
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
     private void assertAdded(String symbolicName, String expectedJavaType) {
-        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        CatalogItem item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
         assertEquals(item.getSymbolicName(), symbolicName);
         assertEquals(countCatalogLocations(), 1);
 
@@ -115,7 +116,7 @@ public class CatalogYamlLocationTest extends AbstractYamlTest {
         assertEquals(def.getId(), symbolicName);
         assertEquals(def.getName(), symbolicName);
         
-        LocationSpec<?> spec = (LocationSpec<?>)mgmt().getCatalog().createSpec(item);
+        LocationSpec spec = (LocationSpec) mgmt().getCatalog().createSpec(item);
         assertEquals(spec.getType().getName(), expectedJavaType);
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
index 2eda1d5..b325c62 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
@@ -168,7 +168,8 @@ public class CampYamlLiteTest {
         Assert.assertEquals(bundle.getUrl(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL);
         Assert.assertEquals(bundle.getVersion(), "0.1.0");
 
-        EntitySpec<?> spec1 = (EntitySpec<?>) mgmt.getCatalog().createSpec(retrievedItem);
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        EntitySpec<?> spec1 = (EntitySpec<?>) mgmt.getCatalog().createSpec((CatalogItem)retrievedItem);
         assertNotNull(spec1);
         Assert.assertEquals(spec1.getConfig().get(TestEntity.CONF_NAME), "sample");
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java b/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
index 1b39015..b546d7b 100644
--- a/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
+++ b/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
@@ -631,7 +631,8 @@ public class Main extends AbstractMain {
                         // and additionally they might contain multiple items in which case
                         // the validation below won't work anyway (you need to go via a deployment plan)
                     } else {
-                        Object spec = catalog.createSpec(item);
+                        @SuppressWarnings({ "unchecked", "rawtypes" })
+                        Object spec = catalog.createSpec((CatalogItem)item);
                         if (spec instanceof EntitySpec) {
                             BrooklynTypes.getDefinedEntityType(((EntitySpec<?>)spec).getType());
                         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index d7c26df..38b7815 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -243,7 +243,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
                 Entitlements.getEntitlementContext().user());
         }
 
-        CatalogItem<? extends Entity,EntitySpec<?>> result =
+        CatalogItem<Entity,EntitySpec<?>> result =
                 CatalogUtils.getCatalogItemOptionalVersion(mgmt(), Entity.class, entityId);
 
         if (result==null) {
@@ -263,8 +263,8 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
         //TODO These casts are not pretty, we could just provide separate get methods for the different types?
         //Or we could provide asEntity/asPolicy cast methods on the CataloItem doing a safety check internally
         @SuppressWarnings("unchecked")
-        CatalogItem<? extends Entity, EntitySpec<?>> result =
-              (CatalogItem<? extends Entity, EntitySpec<?>>) brooklyn().getCatalog().getCatalogItem(symbolicName, version);
+        CatalogItem<Entity, EntitySpec<?>> result =
+              (CatalogItem<Entity, EntitySpec<?>>) brooklyn().getCatalog().getCatalogItem(symbolicName, version);
 
         if (result==null) {
             throw WebResourceUtils.notFound("Entity with id '%s:%s' not found", symbolicName, version);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/eee43613/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/CatalogTransformer.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/CatalogTransformer.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/CatalogTransformer.java
index dae4164..e3e53f9 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/CatalogTransformer.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/CatalogTransformer.java
@@ -58,13 +58,13 @@ public class CatalogTransformer {
 
     private static final org.slf4j.Logger log = LoggerFactory.getLogger(CatalogTransformer.class);
     
-    public static CatalogEntitySummary catalogEntitySummary(BrooklynRestResourceUtils b, CatalogItem<? extends Entity,EntitySpec<?>> item) {
+    public static <T extends Entity> CatalogEntitySummary catalogEntitySummary(BrooklynRestResourceUtils b, CatalogItem<T,EntitySpec<? extends T>> item) {
         Set<EntityConfigSummary> config = Sets.newTreeSet(SummaryComparators.nameComparator());
         Set<SensorSummary> sensors = Sets.newTreeSet(SummaryComparators.nameComparator());
         Set<EffectorSummary> effectors = Sets.newTreeSet(SummaryComparators.nameComparator());
 
         try {
-            EntitySpec<?> spec = b.getCatalog().createSpec(item);
+            EntitySpec<?> spec = (EntitySpec<?>) b.getCatalog().createSpec((CatalogItem) item);
             EntityDynamicType typeMap = BrooklynTypes.getDefinedEntityType(spec.getType());
             EntityType type = typeMap.getSnapshot();
 
@@ -94,17 +94,17 @@ public class CatalogTransformer {
             item.isDeprecated(), makeLinks(item));
     }
 
-    @SuppressWarnings("unchecked")
-    public static CatalogItemSummary catalogItemSummary(BrooklynRestResourceUtils b, CatalogItem<?,?> item) {
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static CatalogItemSummary catalogItemSummary(BrooklynRestResourceUtils b, CatalogItem item) {
         try {
             switch (item.getCatalogItemType()) {
             case TEMPLATE:
             case ENTITY:
-                return catalogEntitySummary(b, (CatalogItem<? extends Entity, EntitySpec<?>>) item);
+                return catalogEntitySummary(b, item);
             case POLICY:
-                return catalogPolicySummary(b, (CatalogItem<? extends Policy, PolicySpec<?>>) item);
+                return catalogPolicySummary(b, item);
             case LOCATION:
-                return catalogLocationSummary(b, (CatalogItem<? extends Location, LocationSpec<?>>) item);
+                return catalogLocationSummary(b, item);
             default:
                 log.warn("Unexpected catalog item type when getting self link (supplying generic item): "+item.getCatalogItemType()+" "+item);
             }