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/11/13 23:23:35 UTC

[02/18] incubator-brooklyn git commit: Catalog versioning - groundwork changes

Catalog versioning - groundwork changes


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

Branch: refs/heads/master
Commit: 7f5992467762fc0fb43ca778850eaace7d4dc6fa
Parents: d1c0782
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Wed Nov 5 18:45:55 2014 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Thu Nov 13 11:49:47 2014 +0200

----------------------------------------------------------------------
 .../java/brooklyn/catalog/BrooklynCatalog.java  |  24 ++++-
 .../catalog/internal/BasicBrooklynCatalog.java  |  72 +++++++++----
 .../brooklyn/catalog/internal/CatalogDo.java    |  32 +++---
 .../catalog/internal/CatalogItemBuilder.java    |  26 +++--
 .../internal/CatalogItemDtoAbstract.java        |   2 +-
 .../catalog/internal/CatalogItemId.java         |  67 +++++++++++++
 .../brooklyn/catalog/internal/CatalogUtils.java |  23 ++++-
 .../brooklyn/camp/lite/CampYamlLiteTest.java    |   6 +-
 .../catalog/internal/CatalogDtoTest.java        |  24 +++--
 .../brooklyn/catalog/internal/CatalogItems.java |  87 ----------------
 .../entity/rebind/RebindCatalogItemTest.java    |  11 +-
 ...talogWhenCatalogPersistenceDisabledTest.java |   2 +-
 .../entity/rebind/RebindTestFixture.java        |  19 ++--
 .../persister/XmlMementoSerializerTest.java     |   2 +-
 .../osgi/OsgiVersionMoreEntityTest.java         | 100 ++++++++++++-------
 .../BrooklynComponentTemplateResolver.java      |   6 +-
 .../BrooklynEntityDecorationResolver.java       |  12 ++-
 .../lookup/AbstractTemplateBrooklynLookup.java  |  13 ++-
 .../camp/brooklyn/AbstractYamlTest.java         |   5 +-
 .../brooklyn/catalog/CatalogYamlEntityTest.java |  46 ++++++++-
 .../brooklyn/catalog/CatalogYamlPolicyTest.java |   4 +-
 21 files changed, 377 insertions(+), 206 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
index 2b58cb8..c5d0a63 100644
--- a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
+++ b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
@@ -26,17 +26,35 @@ import com.google.common.base.Predicate;
 public interface BrooklynCatalog {
 
     /** @return The item with the given ID or {@link brooklyn.catalog.CatalogItem#getRegisteredTypeName()
-     * registeredTypeName}, or null if not found. */
+     * registeredTypeName}, or null if not found.
+     * @deprecated since 0.7.0 use {@link #getCatalogItem(String, String)} */
+    @Deprecated
     CatalogItem<?,?> getCatalogItem(String idOrRegisteredTypeName);
 
+    /** @return The item with the given ID or {@link brooklyn.catalog.CatalogItem#getRegisteredTypeName()
+     * registeredTypeName}, or null if not found. */
+    CatalogItem<?,?> getCatalogItem(String idOrRegisteredTypeName, String version);
+
     /** @return Deletes the item with the given ID
-     * @throws NoSuchElementException if not found */
+     * @throws NoSuchElementException if not found
+     * @deprecated since 0.7.0 use {@link #deleteCatalogItem(String, String)} */
+    @Deprecated
     void deleteCatalogItem(String id);
 
+    /** @return Deletes the item with the given ID and version
+     * @throws NoSuchElementException if not found */
+    void deleteCatalogItem(String id, String version);
+
     /** variant of {@link #getCatalogItem(String)} which checks (and casts) type for convenience
-     * (returns null if type does not match) */
+     * (returns null if type does not match)
+     * @deprecated since 0.7.0 use {@link #getCatalogItem(Class<T>, String, String)} */
+    @Deprecated
     <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id);
 
+    /** variant of {@link #getCatalogItem(String, String)} which checks (and casts) type for convenience
+     * (returns null if type does not match) */
+    <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id, String version);
+
     /** @return All items in the catalog */
     <T,SpecT> Iterable<CatalogItem<T,SpecT>> getCatalogItems();
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/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 4d31964..eb2e793 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -72,6 +72,7 @@ import com.google.common.collect.Iterables;
 
 public class BasicBrooklynCatalog implements BrooklynCatalog {
     private static final String POLICIES_KEY = "brooklyn.policies";
+    public static final String NO_VERSION = "0.0.0_SNAPSHOT";
 
     private static final Logger log = LoggerFactory.getLogger(BasicBrooklynCatalog.class);
 
@@ -166,30 +167,45 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return catalog;
     }
 
-    protected CatalogItemDo<?,?> getCatalogItemDo(String idOrRegisteredTypeName) {
+    protected CatalogItemDo<?,?> getCatalogItemDo(String idOrRegisteredTypeName, String version) {
+        CatalogItemId versionedId = new CatalogItemId(idOrRegisteredTypeName, version);
         CatalogItemDo<?, ?> item = null;
         // TODO really need to remove redundancy of id v registered type;
         // should also remove "manual additions" bucket; just have one map a la osgi
-        if (manualAdditionsCatalog!=null) item = manualAdditionsCatalog.getIdCache().get(idOrRegisteredTypeName);
-        if (item == null) item = catalog.getIdCache().get(idOrRegisteredTypeName);
-        if (item == null && manualAdditionsCatalog!=null) item = manualAdditionsCatalog.getRegisteredTypeNameCache().get(idOrRegisteredTypeName);
-        if (item == null) item = catalog.getRegisteredTypeNameCache().get(idOrRegisteredTypeName);
+        if (manualAdditionsCatalog!=null) item = manualAdditionsCatalog.getIdCache().get(versionedId);
+        if (item == null) item = catalog.getIdCache().get(versionedId);
+        if (item == null && manualAdditionsCatalog!=null) item = manualAdditionsCatalog.getRegisteredTypeNameCache().get(versionedId);
+        if (item == null) item = catalog.getRegisteredTypeNameCache().get(versionedId);
         return item;
     }
     
     @Override
-    public CatalogItem<?,?> getCatalogItem(String idOrRegisteredTypeName) {
+    @Deprecated
+    public CatalogItem<?,?> getCatalogItem(String id) {
+        return getCatalogItem(id, NO_VERSION);
+    }
+    
+    @Override
+    public CatalogItem<?,?> getCatalogItem(String idOrRegisteredTypeName, String version) {
         if (idOrRegisteredTypeName == null) return null;
-        CatalogItemDo<?, ?> itemDo = getCatalogItemDo(idOrRegisteredTypeName);
+        checkNotNull(version, "version");
+        CatalogItemDo<?, ?> itemDo = getCatalogItemDo(idOrRegisteredTypeName, version);
         if (itemDo == null) return null;
         return itemDo.getDto();
     }
     
     @Override
+    @Deprecated
     public void deleteCatalogItem(String id) {
-        log.debug("Deleting manual catalog item from "+mgmt+": "+id);
+        deleteCatalogItem(id, NO_VERSION);
+    }
+
+    @Override
+    public void deleteCatalogItem(String id, String version) {
+        log.debug("Deleting manual catalog item from "+mgmt+": "+id + ":" + version);
         checkNotNull(id, "id");
-        CatalogItem<?, ?> item = getCatalogItem(id);
+        checkNotNull(id, "version");
+        CatalogItem<?, ?> item = getCatalogItem(id, version);
         CatalogItemDtoAbstract<?,?> itemDto = getAbstractCatalogItem(item);
         if (itemDto == null) {
             throw new NoSuchElementException("No catalog item found with id "+id);
@@ -208,11 +224,17 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
 
     }
 
-    @SuppressWarnings("unchecked")
     @Override
+    @Deprecated
     public <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id) {
-        if (id==null) return null;
-        CatalogItem<?,?> result = getCatalogItem(id);
+        return getCatalogItem(type, id, NO_VERSION);
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id, String version) {
+        if (id==null || version==null) return null;
+        CatalogItem<?,?> result = getCatalogItem(id, version);
         if (result==null) return null;
         if (type==null || type.isAssignableFrom(result.getCatalogItemJavaType())) 
             return (CatalogItem<T,SpecT>)result;
@@ -238,8 +260,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     @SuppressWarnings("unchecked")
     @Override
     public <T, SpecT> SpecT createSpec(CatalogItem<T, SpecT> item) {
-        CatalogItemDo<T,SpecT> loadedItem = (CatalogItemDo<T, SpecT>) getCatalogItemDo(item.getId());
-
+        CatalogItemDo<T,SpecT> loadedItem = (CatalogItemDo<T, SpecT>) getCatalogItemDo(item.getId(), item.getVersion());
         Class<SpecT> specType = loadedItem.getSpecType();
         if (specType==null) return null;
 
@@ -343,7 +364,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         if (log.isDebugEnabled())
             log.debug("Loading class for catalog item " + item);
         checkNotNull(item);
-        CatalogItemDo<?,?> loadedItem = getCatalogItemDo(item.getId());
+        CatalogItemDo<?,?> loadedItem = getCatalogItemDo(item.getId(), item.getVersion());
         if (loadedItem==null) throw new NoSuchElementException("Unable to load '"+item.getId()+"' to instantiate it");
         return (Class<? extends T>) loadedItem.getJavaClass();
     }
@@ -407,11 +428,20 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
             }
         }
 
+        Maybe<Object> possibleVersion = catalog.getMaybe("version");
+        String version;
+        if (possibleVersion.isAbsent()) {
+            throw new IllegalArgumentException("'version' attribute missing in 'brooklyn.catalog' section.");
+        }
+
+        //could be coalesced to a number - can be one of Integer, Double, String
+        version = possibleVersion.get().toString();
+
         CatalogUtils.installLibraries(mgmt, libraries);
 
         AbstractBrooklynObjectSpec<?, ?> spec = createSpec(plan, CatalogUtils.newClassLoadingContext(mgmt, "<not created yet>", libraries, getRootClassLoader()));
 
-        CatalogItemBuilder<?> builder = createItemBuilder(spec, registeredTypeName)
+        CatalogItemBuilder<?> builder = createItemBuilder(spec, registeredTypeName, version)
             .libraries(libraries)
             .displayName(plan.getName())
             .description(plan.getDescription())
@@ -428,8 +458,6 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         if (iconUrl.isAbsent()) iconUrl = catalog.getMaybe("icon_url");
         if (iconUrl.isPresent()) builder.iconUrl((String)iconUrl.get());
 
-        // TODO #3 support version info
-
         CatalogItemDtoAbstract<?, ?> dto = builder.build();
         // Overwrite generated ID
         if (catalog.getMaybe("id").isPresent()) {
@@ -450,15 +478,15 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         }
     }
 
-    private CatalogItemBuilder<?> createItemBuilder(AbstractBrooklynObjectSpec<?, ?> spec, String itemId) {
+    private CatalogItemBuilder<?> createItemBuilder(AbstractBrooklynObjectSpec<?, ?> spec, String itemId, String version) {
         if (spec instanceof EntitySpec) {
             if (isApplicationSpec((EntitySpec<?>)spec)) {
-                return CatalogItemBuilder.newTemplate(itemId);
+                return CatalogItemBuilder.newTemplate(itemId, version);
             } else {
-                return CatalogItemBuilder.newEntity(itemId);
+                return CatalogItemBuilder.newEntity(itemId, version);
             }
         } else if (spec instanceof PolicySpec) {
-            return CatalogItemBuilder.newPolicy(itemId);
+            return CatalogItemBuilder.newPolicy(itemId, version);
         } else {
             throw new IllegalStateException("Unknown spec type " + spec.getClass().getName() + " (" + spec + ")");
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/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 33552f0..e2249e0 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -51,8 +51,8 @@ public class CatalogDo {
     
     List<CatalogDo> childrenCatalogs = new ArrayList<CatalogDo>();
     CatalogClasspathDo classpath;
-    private Map<String, CatalogItemDo<?,?>> cacheById;
-    private Map<String, CatalogItemDo<?,?>> cacheByRegisteredTypeName;
+    private Map<CatalogItemId, CatalogItemDo<?,?>> cacheById;
+    private Map<CatalogItemId, CatalogItemDo<?,?>> cacheByRegisteredTypeName;
 
     AggregateClassLoader childrenClassLoader = AggregateClassLoader.newInstanceWithNoLoaders();
     ClassLoader recursiveClassLoader;
@@ -159,26 +159,26 @@ public class CatalogDo {
         return childL;
     }
 
-    protected Map<String, CatalogItemDo<?,?>> getIdCache() {
-        Map<String, CatalogItemDo<?,?>> cache = this.cacheById;
+    protected Map<CatalogItemId, CatalogItemDo<?,?>> getIdCache() {
+        Map<CatalogItemId, CatalogItemDo<?,?>> cache = this.cacheById;
         if (cache==null) cache = buildCaches();
         return cache;
     }
 
-    protected Map<String, CatalogItemDo<?,?>> getRegisteredTypeNameCache() {
-        Map<String, CatalogItemDo<?,?>> cache = this.cacheByRegisteredTypeName;
+    protected Map<CatalogItemId, CatalogItemDo<?,?>> getRegisteredTypeNameCache() {
+        Map<CatalogItemId, CatalogItemDo<?,?>> cache = this.cacheByRegisteredTypeName;
         if (cache==null) cache = buildCaches();
         return cache;
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    protected synchronized Map<String, CatalogItemDo<?,?>> buildCaches() {
+    protected synchronized Map<CatalogItemId, CatalogItemDo<?,?>> buildCaches() {
         if (cacheById != null) return cacheById;
         CatalogUtils.logDebugOrTraceIfRebinding(log, "Building cache for {}", this);
         if (!isLoaded()) 
             log.debug("Catalog not fully loaded when loading cache of "+this);
         
-        Map<String, CatalogItemDo<?,?>> cache = new LinkedHashMap<String, CatalogItemDo<?,?>>();
+        Map<CatalogItemId, CatalogItemDo<?,?>> cache = new LinkedHashMap<CatalogItemId, CatalogItemDo<?,?>>();
         
         // build the cache; first from children catalogs, then from local entities
         // so that root and near-root takes precedence over deeper items;
@@ -196,11 +196,11 @@ public class CatalogDo {
             List<CatalogItemDtoAbstract<?,?>> entriesReversed = MutableList.copyOf(dto.getUniqueEntries());
             Collections.reverse(entriesReversed);
             for (CatalogItemDtoAbstract<?,?> entry: entriesReversed)
-                cache.put(entry.getId(), new CatalogItemDo(this, entry));
+                cache.put(new CatalogItemId(entry), new CatalogItemDo(this, entry));
         }
-        Map<String, CatalogItemDo<?, ?>> typeNameCache = Maps.newHashMap();
+        Map<CatalogItemId, CatalogItemDo<?, ?>> typeNameCache = Maps.newHashMap();
         for (CatalogItemDo<?, ?> entry : cache.values()) {
-            typeNameCache.put(entry.getRegisteredTypeName(), entry);
+            typeNameCache.put(new CatalogItemId(entry.getRegisteredTypeName(), entry.getVersion()), entry);
         }
         this.cacheById = cache;
         this.cacheByRegisteredTypeName = typeNameCache;
@@ -225,9 +225,11 @@ public class CatalogDo {
     public synchronized void addEntry(CatalogItemDtoAbstract<?,?> entry) {
         dto.addEntry(entry);
         if (cacheById != null) {
+            CatalogItemId cdoId = new CatalogItemId(entry);
             CatalogItemDo<?, ?> cdo = new CatalogItemDo(this, entry);
-            cacheById.put(entry.getId(), cdo);
-            cacheByRegisteredTypeName.put(entry.getRegisteredTypeName(), cdo);
+            cacheById.put(cdoId, cdo);
+            CatalogItemId cdoTypeId = new CatalogItemId(entry.getRegisteredTypeName(), cdo.getVersion());
+            cacheByRegisteredTypeName.put(cdoTypeId, cdo);
         }
         if (mgmt != null) {
             mgmt.getRebindManager().getChangeListener().onManaged(entry);
@@ -240,8 +242,8 @@ public class CatalogDo {
     public synchronized void deleteEntry(CatalogItemDtoAbstract<?, ?> entry) {
         dto.removeEntry(entry);
         if (cacheById != null) {
-            cacheById.remove(entry.getId());
-            cacheByRegisteredTypeName.remove(entry.getRegisteredTypeName());
+            cacheById.remove(new CatalogItemId(entry));
+            cacheByRegisteredTypeName.remove(new CatalogItemId(entry.getRegisteredTypeName(), entry.getVersion()));
         }
         if (mgmt != null) {
             // TODO: Can the entry be in more than one catalogue? The management context has no notion of

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
index 3468f05..8d2513b 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
@@ -23,19 +23,22 @@ import com.google.common.base.Preconditions;
 public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?, ?>> {
     private CatalogItemType dto;
 
-    public static CatalogItemBuilder<CatalogEntityItemDto> newEntity(String registeredTypeName) {
+    public static CatalogItemBuilder<CatalogEntityItemDto> newEntity(String registeredTypeName, String version) {
         return new CatalogItemBuilder<CatalogEntityItemDto>(new CatalogEntityItemDto())
-                .registeredTypeName(registeredTypeName);
+                .registeredTypeName(registeredTypeName)
+                .version(version);
     }
 
-    public static CatalogItemBuilder<CatalogTemplateItemDto> newTemplate(String registeredTypeName) {
+    public static CatalogItemBuilder<CatalogTemplateItemDto> newTemplate(String registeredTypeName, String version) {
         return new CatalogItemBuilder<CatalogTemplateItemDto>(new CatalogTemplateItemDto())
-                .registeredTypeName(registeredTypeName);
+                .registeredTypeName(registeredTypeName)
+                .version(version);
     }
 
-    public static CatalogItemBuilder<CatalogPolicyItemDto> newPolicy(String registeredTypeName) {
+    public static CatalogItemBuilder<CatalogPolicyItemDto> newPolicy(String registeredTypeName, String version) {
         return new CatalogItemBuilder<CatalogPolicyItemDto>(new CatalogPolicyItemDto())
-                .registeredTypeName(registeredTypeName);
+                .registeredTypeName(registeredTypeName)
+                .version(version);
     }
 
     public CatalogItemBuilder(CatalogItemType dto) {
@@ -48,6 +51,12 @@ public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?
         return this;
     }
 
+    @Deprecated
+    public CatalogItemBuilder<CatalogItemType> javaType(String javaType) {
+        dto.javaType = javaType;
+        return this;
+    }
+
     /** @deprecated since 0.7.0 use {@link #displayName}*/
     @Deprecated
     public CatalogItemBuilder<CatalogItemType> name(String name) {
@@ -69,6 +78,11 @@ public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?
         return this;
     }
 
+    public CatalogItemBuilder<CatalogItemType> version(String version) {
+        dto.version = version;
+        return this;
+    }
+
     public CatalogItemBuilder<CatalogItemType> libraries(CatalogLibrariesDto libraries) {
         dto.libraries = libraries;
         return this;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/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 704976b..e78721a 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -49,7 +49,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
     @SetFromFlag String javaType;
     @SetFromFlag String description;
     @SetFromFlag String iconUrl;
-    @SetFromFlag String version;
+    @SetFromFlag String version = BasicBrooklynCatalog.NO_VERSION;
     @SetFromFlag CatalogLibrariesDto libraries;
     @SetFromFlag String planYaml;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/core/src/main/java/brooklyn/catalog/internal/CatalogItemId.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemId.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemId.java
new file mode 100644
index 0000000..47f7b62
--- /dev/null
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemId.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.catalog.internal;
+
+import brooklyn.catalog.CatalogItem;
+
+class CatalogItemId {
+    private String id;
+    private String version;
+    
+    public CatalogItemId(String id, String version) {
+        this.id = id;
+        this.version = version;
+    }
+    
+    public CatalogItemId(CatalogItem<?, ?> item) {
+        this(item.getId(), item.getVersion());
+    }
+    
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((id == null) ? 0 : id.hashCode());
+        result = prime * result
+                + ((version == null) ? 0 : version.hashCode());
+        return result;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        CatalogItemId other = (CatalogItemId) obj;
+        if (id == null) {
+            if (other.id != null)
+                return false;
+        } else if (!id.equals(other.id))
+            return false;
+        if (version == null) {
+            if (other.version != null)
+                return false;
+        } else if (!version.equals(other.version))
+            return false;
+        return true;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
index 6fd1f94..6f33574 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
@@ -50,6 +50,8 @@ import brooklyn.util.time.Time;
 public class CatalogUtils {
     private static final Logger log = LoggerFactory.getLogger(CatalogUtils.class);
 
+    public static final char VERSION_DELIMITER = ':';
+
     public static BrooklynClassLoadingContext newClassLoadingContext(ManagementContext mgmt, CatalogItem<?, ?> item) {
         CatalogItemLibraries libraries = item.getLibraries();
         // TODO getLibraries() should never be null but sometimes it is still
@@ -143,6 +145,25 @@ public class CatalogUtils {
         else
             log.debug(message, args);
     }
-    
+
+    public static String getIdFromVersionedId(String versionedId) {
+        if (versionedId == null) return null;
+        int versionDelimiterPos = versionedId.lastIndexOf(CatalogUtils.VERSION_DELIMITER);
+        if (versionDelimiterPos != -1) {
+            return versionedId.substring(0, versionDelimiterPos);
+        } else {
+            return null;
+        }
+    }
+
+    public static String getVersionFromVersionedId(String versionedId) {
+        if (versionedId == null) return null;
+        int versionDelimiterPos = versionedId.lastIndexOf(CatalogUtils.VERSION_DELIMITER);
+        if (versionDelimiterPos != -1) {
+            return versionedId.substring(versionDelimiterPos+1);
+        } else {
+            return null;
+        }
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/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 e952f00..9eb56fd 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -71,6 +71,7 @@ import com.google.common.collect.Sets;
 /** Tests of lightweight CAMP integration. Since the "real" integration is in brooklyn-camp project,
  * but some aspects of CAMP we want to be able to test here. */
 public class CampYamlLiteTest {
+    private static final String TEST_VERSION = "0.1.2";
 
     private static final Logger log = LoggerFactory.getLogger(CampYamlLiteTest.class);
     
@@ -209,7 +210,7 @@ public class CampYamlLiteTest {
                 "  name: My Catalog App\n" +
                 "  description: My description\n" +
                 "  icon_url: classpath:/brooklyn/osgi/tests/icon.gif\n" +
-                "  version: 0.1.2\n" +
+                "  version: " + TEST_VERSION + "\n" +
                 "  libraries:\n" +
                 "  - url: " + bundleUrl + "\n" +
                 "\n" +
@@ -218,13 +219,12 @@ public class CampYamlLiteTest {
     }
 
     private void assertMgmtHasSampleMyCatalogApp(String registeredTypeName, String bundleUrl) {
-        CatalogItem<?, ?> item = mgmt.getCatalog().getCatalogItem(registeredTypeName);
+        CatalogItem<?, ?> item = mgmt.getCatalog().getCatalogItem(registeredTypeName, TEST_VERSION);
         assertNotNull(item, "failed to load item with id=" + registeredTypeName + " from catalog. Entries were: " +
                 Joiner.on(",").join(mgmt.getCatalog().getCatalogItems()));
         assertEquals(item.getRegisteredTypeName(), registeredTypeName);
 
         // stored as yaml, not java
-//      assertEquals(entityItem.getJavaType(), "brooklyn.test.entity.TestEntity");
         assertNotNull(item.getPlanYaml());
         Assert.assertTrue(item.getPlanYaml().contains("io.camp.mock:AppServer"));
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/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 1bc4392..8e6d704 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
@@ -76,7 +76,7 @@ public class CatalogDtoTest {
         CatalogDo loader = new CatalogDo(managementContext, root).load();
         
         // test app comes from jar, by default
-        CatalogItemDo<?,?> worker = loader.getRegisteredTypeNameCache().get(TestApplication.class.getCanonicalName());
+        CatalogItemDo<?,?> worker = loader.getRegisteredTypeNameCache().get(new CatalogItemId(TestApplication.class.getCanonicalName(), BasicBrooklynCatalog.NO_VERSION));
         assertNotNull(worker);
         assertEquals(worker.getDisplayName(), "Test App from JAR");
         
@@ -96,10 +96,8 @@ public class CatalogDtoTest {
                 CatalogDto.newNamedInstance("Test Entities from Java", null, "test-java"));
         testEntitiesJavaCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
         testEntitiesJavaCatalog.addToClasspath(MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests")));
-        testEntitiesJavaCatalog.addEntry(CatalogItems.newTemplateFromJava(
-                TestApplication.class.getCanonicalName(), "Test App from JAR"));
-        testEntitiesJavaCatalog.addEntry(CatalogItems.newEntityFromJava(
-                TestEntity.class.getCanonicalName(), "Test Entity from JAR"));
+        testEntitiesJavaCatalog.addEntry(CatalogItemBuilder.newTemplate(TestApplication.class.getCanonicalName(), "Test App from JAR").build());
+        testEntitiesJavaCatalog.addEntry(CatalogItemBuilder.newEntity(TestEntity.class.getCanonicalName(), "Test Entity from JAR").build());
         root.addCatalog(testEntitiesJavaCatalog.dto);
 
         CatalogDo testEntitiesJavaCatalogScanning = new CatalogDo(
@@ -114,7 +112,7 @@ public class CatalogDtoTest {
                 CatalogDto.newNamedInstance("Test Entities from OSGi",
                         "A catalog whose entries define their libraries as a list of OSGi bundles", "test-osgi-defined"));
         osgiCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
-        CatalogEntityItemDto osgiEntity = CatalogItems.newEntityFromJava(TestEntity.class.getCanonicalName(), "Test Entity from OSGi");
+        CatalogEntityItemDto osgiEntity = CatalogItemBuilder.newEntity(TestEntity.class.getCanonicalName(), "Test Entity from OSGi").build();
         // 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);
@@ -123,4 +121,18 @@ public class CatalogDtoTest {
         root.addCatalog(CatalogDto.newLinkedInstance("classpath://brooklyn-catalog-empty.xml"));
         return root.dto;
     }
+    
+    @Test
+    public void testVersionedIdSplitter() {
+        String id = "simple.id";
+        String version = "0.1.2";
+        String versionedId = id + CatalogUtils.VERSION_DELIMITER + version;
+        
+        Assert.assertNull(CatalogUtils.getIdFromVersionedId(null));
+        Assert.assertNull(CatalogUtils.getVersionFromVersionedId(null));
+        Assert.assertNull(CatalogUtils.getIdFromVersionedId(id));
+        Assert.assertNull(CatalogUtils.getVersionFromVersionedId(version));
+        Assert.assertEquals(CatalogUtils.getIdFromVersionedId(versionedId), id);
+        Assert.assertEquals(CatalogUtils.getVersionFromVersionedId(versionedId), version);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/core/src/test/java/brooklyn/catalog/internal/CatalogItems.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogItems.java b/core/src/test/java/brooklyn/catalog/internal/CatalogItems.java
deleted file mode 100644
index 80b41d5..0000000
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogItems.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import com.google.common.annotations.Beta;
-
-import io.brooklyn.camp.spi.pdp.DeploymentPlan;
-
-/** Only for internal use / use in tests. */
-public class CatalogItems {
-
-    public static CatalogTemplateItemDto newTemplateFromJava(String javaType, String name) {
-        return newTemplateFromJava(javaType, name, null, null);
-    }
-
-    public static CatalogTemplateItemDto newTemplateFromJava(String javaType, String name, String description) {
-        return newTemplateFromJava(javaType, name, description, null);
-    }
-
-    public static CatalogTemplateItemDto newTemplateFromJava(String javaType, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogTemplateItemDto(), javaType, javaType, name, description, libraries);
-    }
-
-    public static CatalogEntityItemDto newEntityFromPlan(String registeredTypeName, CatalogLibrariesDto libraries, DeploymentPlan plan, String underlyingPlanYaml) {
-        CatalogEntityItemDto target = set(new CatalogEntityItemDto(), registeredTypeName, null, plan.getName(), plan.getDescription(), libraries);
-        target.planYaml = underlyingPlanYaml;
-        return target;
-    }
-    
-    // TODO just added this method to expose registeredTypeName for tests; but it should all go away;
-    // so long as tests pass no need to keep deprecation imho
-    @Beta
-    public static CatalogEntityItemDto newEntityFromJavaWithRegisteredTypeName(String registeredTypeName, String javaType) {
-        return set(new CatalogEntityItemDto(), registeredTypeName, javaType, registeredTypeName, null, null);
-    }
-    public static CatalogEntityItemDto newEntityFromJava(String javaType, String name) {
-        return newEntityFromJava(javaType, name, null, null);
-    }
-
-    public static CatalogEntityItemDto newEntityFromJava(String javaType, String name, String description) {
-        return newEntityFromJava(javaType, name, description, null);
-    }
-
-    public static CatalogEntityItemDto newEntityFromJava(String javaType, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogEntityItemDto(), javaType, javaType, name, description, libraries);
-    }
-
-    public static CatalogPolicyItemDto newPolicyFromJava(String javaType, String name) {
-        return newPolicyFromJava(javaType, name, null, null);
-    }
-
-    public static CatalogPolicyItemDto newPolicyFromJava(String javaType, String name, String description) {
-        return newPolicyFromJava(javaType, name, description, null);
-    }
-
-    public static CatalogPolicyItemDto newPolicyFromJava(String javaType, String name, String description, CatalogLibrariesDto libraries) {
-        return set(new CatalogPolicyItemDto(), javaType, javaType, name, description, libraries);
-    }
- 
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    private static <T extends CatalogItemDtoAbstract> T set(T target, String registeredType, String javaType, String name,
-            String description, CatalogLibrariesDto libraries) {
-        target.registeredType = registeredType;
-        target.javaType = javaType;
-        target.name = name;
-        target.description = description;
-        target.libraries = libraries != null ? libraries : new CatalogLibrariesDto();
-        return target;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
index f2f4fad..a601bb7 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
@@ -47,6 +47,8 @@ import com.google.common.collect.Iterables;
 
 public class RebindCatalogItemTest extends RebindTestFixtureWithApp {
 
+    private static final String TEST_VERSION = "0.0.1";
+
     private static final Logger LOG = LoggerFactory.getLogger(RebindCatalogItemTest.class);
     public static class MyPolicy extends AbstractPolicy {}
     private boolean catalogPersistenceWasEnabled;
@@ -101,7 +103,10 @@ public class RebindCatalogItemTest extends RebindTestFixtureWithApp {
 
     @Test
     public void testAddAndRebindEntity() throws Exception {
-        String yaml = "name: rebind-yaml-catalog-item-test\n" +
+        String yaml = 
+                "name: rebind-yaml-catalog-item-test\n" +
+                "brooklyn.catalog:\n" +
+                "  version: " + TEST_VERSION + "\n" +
                 "services:\n" +
                 "- type: io.camp.mock:AppServer";
         CatalogItem<?, ?> added = origManagementContext.getCatalog().addItem(yaml);
@@ -121,7 +126,7 @@ public class RebindCatalogItemTest extends RebindTestFixtureWithApp {
         String yaml = "name: Test Policy\n" +
                 "brooklyn.catalog:\n" +
                 "  id: sample_policy\n" +
-                "  version: 0.1.0\n" +
+                "  version: " + TEST_VERSION + "\n" +
                 "brooklyn.policies: \n" +
                 "- type: brooklyn.entity.rebind.RebindCatalogItemTest$MyPolicy\n" +
                 "  brooklyn.config:\n" +
@@ -145,7 +150,7 @@ public class RebindCatalogItemTest extends RebindTestFixtureWithApp {
         // persistence window. Because BrooklynMementoPersisterToObjectStore applies writes/deletes
         // asynchronously the winner is down to a race and the test might pass or fail.
         origManagementContext.getRebindManager().forcePersistNow();
-        origManagementContext.getCatalog().deleteCatalogItem(toRemove.getId());
+        origManagementContext.getCatalog().deleteCatalogItem(toRemove.getId(), toRemove.getVersion());
         assertEquals(Iterables.size(origManagementContext.getCatalog().getCatalogItems()), 0);
         rebindAndAssertCatalogsAreEqual();
         assertEquals(Iterables.size(newManagementContext.getCatalog().getCatalogItems()), 0);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
index 8852e15..728126e 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
@@ -82,7 +82,7 @@ public class RebindCatalogWhenCatalogPersistenceDisabledTest extends RebindTestF
     public void testModificationsToCatalogAreNotPersistedWhenCatalogPersistenceFeatureIsDisabled() throws Exception {
         assertEquals(Iterables.size(origManagementContext.getCatalog().getCatalogItems()), 1);
         CatalogItem<Object, Object> toRemove = Iterables.getOnlyElement(origManagementContext.getCatalog().getCatalogItems());
-        origManagementContext.getCatalog().deleteCatalogItem(toRemove.getId());
+        origManagementContext.getCatalog().deleteCatalogItem(toRemove.getId(), toRemove.getVersion());
         assertEquals(Iterables.size(origManagementContext.getCatalog().getCatalogItems()), 0);
 
         rebind();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
index fb4e286..2973276 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
@@ -32,9 +32,9 @@ import org.testng.annotations.BeforeMethod;
 
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.config.BrooklynProperties;
 import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityFunctions;
 import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
 import brooklyn.entity.rebind.persister.FileBasedObjectStore;
@@ -53,7 +53,6 @@ import brooklyn.util.time.Duration;
 
 import com.google.api.client.util.Sets;
 import com.google.common.annotations.Beta;
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
@@ -242,16 +241,20 @@ public abstract class RebindTestFixture<T extends StartableApplication> {
         Set<String> expectedIds = getCatalogItemIds(expected.getCatalogItems());
         assertEquals(actualIds.size(), Iterables.size(actual.getCatalogItems()), "id keyset size != size of catalog. Are there duplicates in the catalog?");
         assertEquals(actualIds, expectedIds);
-        for (String id : actualIds) {
-            assertCatalogItemsEqual(actual.getCatalogItem(id), expected.getCatalogItem(id));
+        for (String versionedId : actualIds) {
+            String id = CatalogUtils.getIdFromVersionedId(versionedId);
+            String version = CatalogUtils.getVersionFromVersionedId(versionedId);
+            assertCatalogItemsEqual(actual.getCatalogItem(id, version), expected.getCatalogItem(id, version));
         }
     }
 
     private Set<String> getCatalogItemIds(Iterable<CatalogItem<Object, Object>> catalogItems) {
-        return FluentIterable.from(catalogItems)
-                .transform(EntityFunctions.id())
-                .copyInto(Sets.<String>newHashSet());
-    }
+        Set<String> itemIds = Sets.<String>newHashSet();
+        for (CatalogItem<?, ?> item : catalogItems) {
+            itemIds.add(item.getId() + ":" + item.getVersion());
+        }
+        return itemIds;
+   }
 
     protected void assertCatalogItemsEqual(CatalogItem<?, ?> actual, CatalogItem<?, ?> expected) {
         assertEquals(actual.getClass(), expected.getClass());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java b/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
index ebcd0e3..37c9815 100644
--- a/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
@@ -161,7 +161,7 @@ public class XmlMementoSerializerTest {
         final TestApplication app = TestApplication.Factory.newManagedInstanceForTests();
         ManagementContext managementContext = app.getManagementContext();
         try {
-            CatalogItem<?, ?> catalogItem = CatalogItemBuilder.newEntity("registeredtypename")
+            CatalogItem<?, ?> catalogItem = CatalogItemBuilder.newEntity("registeredtypename", "0.0.1")
                     .displayName("test catalog item")
                     .description("description")
                     .plan("yaml plan")

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
index 4b653ab..92fdb47 100644
--- a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
@@ -21,6 +21,7 @@ package brooklyn.management.osgi;
 import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
 import java.util.List;
 
 import org.osgi.framework.Bundle;
@@ -33,7 +34,8 @@ import org.testng.annotations.Test;
 
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.internal.CatalogEntityItemDto;
-import brooklyn.catalog.internal.CatalogItems;
+import brooklyn.catalog.internal.CatalogItemBuilder;
+import brooklyn.catalog.internal.CatalogLibrariesDto;
 import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.Entities;
@@ -71,6 +73,8 @@ public class OsgiVersionMoreEntityTest {
     public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH = OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH;
     public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL = "classpath:"+BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH;
     
+    public static final String TEST_VERSION = "0.1.0";
+    
     protected LocalManagementContext mgmt;
     protected TestApplication app;
 
@@ -119,25 +123,26 @@ public class OsgiVersionMoreEntityTest {
         }
     }
     
-    protected CatalogItem<?, ?> addCatalogItemWithTypeAsName(String type, String ...libraries) {
-        return addCatalogItemWithNameAndType(type, type, libraries);
+    protected CatalogItem<?, ?> addCatalogItemWithTypeAsName(String type, String version, String ...libraries) {
+        return addCatalogItemWithNameAndType(type, version, type, libraries);
     }
     @SuppressWarnings("deprecation")
-    protected CatalogItem<?, ?> addCatalogItemWithNameAndType(String symName, String type, String ...libraries) {
-        CatalogEntityItemDto c1 = newCatalogItemWithNameAndType(symName, type, libraries);
+    protected CatalogItem<?, ?> addCatalogItemWithNameAndType(String symName, String version, String type, String ...libraries) {
+        CatalogEntityItemDto c1 = newCatalogItemWithNameAndType(symName, version, type, libraries);
         mgmt.getCatalog().addItem(c1);
-        CatalogItem<?, ?> c2 = mgmt.getCatalog().getCatalogItem(type);
+        CatalogItem<?, ?> c2 = mgmt.getCatalog().getCatalogItem(type, version);
         return c2;
     }
 
-    static CatalogEntityItemDto newCatalogItemWithTypeAsName(String type, String ...libraries) {
-        return newCatalogItemWithNameAndType(type, type, libraries);
+    static CatalogEntityItemDto newCatalogItemWithTypeAsName(String type, String version, String ...libraries) {
+        return newCatalogItemWithNameAndType(type, version, type, libraries);
     }
-    static CatalogEntityItemDto newCatalogItemWithNameAndType(String symName, String type, String ...libraries) {
-        CatalogEntityItemDto c1 = CatalogItems.newEntityFromJavaWithRegisteredTypeName(symName, type);
-        c1.setCatalogItemId(symName);
-        for (String library: libraries)
-            c1.getLibrariesDto().addBundle(library);
+    static CatalogEntityItemDto newCatalogItemWithNameAndType(String symName, String version, String type, String ...libraries) {
+        CatalogEntityItemDto c1 = CatalogItemBuilder.newEntity(symName, version)
+                .javaType(type)
+                .libraries(CatalogLibrariesDto.from(Arrays.asList(libraries)))
+                .build();
+        c1.setCatalogItemId(type);
         return c1;
     }
 
@@ -183,7 +188,10 @@ public class OsgiVersionMoreEntityTest {
 
     @Test
     public void testMoreEntitiesV1() throws Exception {
-        CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+        CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
+                OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+                TEST_VERSION,
+                BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
         
         // test load and instantiate
         Entity me = addItemFromCatalog(c2);
@@ -209,13 +217,18 @@ public class OsgiVersionMoreEntityTest {
 
     @Test
     public void testMoreEntitiesV1Policy() throws Exception {
-        CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+        CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
+                OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+                TEST_VERSION,
+                BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
         
         // test load and instantiate
         Entity me = addItemFromCatalog(c2);
 
-        CatalogItem<?, ?> cp = addCatalogItemWithTypeAsName(OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY, 
-            BROOKLYN_TEST_OSGI_ENTITIES_URL);
+        CatalogItem<?, ?> cp = addCatalogItemWithTypeAsName(
+                OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY,
+                TEST_VERSION,
+                BROOKLYN_TEST_OSGI_ENTITIES_URL);
         me.addPolicy(getPolicySpec(cp));
         
         Assert.assertEquals(me.getPolicies().size(), 1, "Wrong number of policies: "+me.getPolicies());
@@ -229,8 +242,10 @@ public class OsgiVersionMoreEntityTest {
 
     @Test
     public void testMoreEntitiesV2FailsWithoutBasicTestOsgiEntitiesBundle() throws Exception {
-        CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
-            BROOKLYN_TEST_MORE_ENTITIES_V2_URL);
+        CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
+                OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+                TEST_VERSION,
+                BROOKLYN_TEST_MORE_ENTITIES_V2_URL);
         
         // test load and instantiate
         try {
@@ -247,8 +262,11 @@ public class OsgiVersionMoreEntityTest {
     // and has policy, with policy item catalog ID is reasonable
     @Test
     public void testMoreEntitiesV2() throws Exception {
-        CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
-            BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
+        CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
+                OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+                TEST_VERSION,
+                BROOKLYN_TEST_MORE_ENTITIES_V2_URL,
+                BROOKLYN_TEST_OSGI_ENTITIES_URL);
         
         // test load and instantiate
         Entity me = addItemFromCatalog(c2);
@@ -266,13 +284,17 @@ public class OsgiVersionMoreEntityTest {
 
     @Test
     public void testMoreEntitiesV1ThenV2GivesV2() throws Exception {
-        addCatalogItemWithTypeAsName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
-            BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
-        addCatalogItemWithTypeAsName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
-            BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
+        addCatalogItemWithTypeAsName(
+                OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+                TEST_VERSION,
+                BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+        addCatalogItemWithTypeAsName(
+                OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+                TEST_VERSION,
+                BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
         
         // test load and instantiate
-        Entity me = addItemFromCatalog( mgmt.getCatalog().getCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY) );
+        Entity me = addItemFromCatalog( mgmt.getCatalog().getCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION) );
         
         assertV2MethodCall(me);
         assertV2EffectorCall(me);
@@ -281,13 +303,17 @@ public class OsgiVersionMoreEntityTest {
 
     @Test
     public void testMoreEntitiesV2ThenV1GivesV1() throws Exception {
-        addCatalogItemWithTypeAsName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
-            BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
-        addCatalogItemWithTypeAsName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
-            BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+        addCatalogItemWithTypeAsName(
+                OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+                TEST_VERSION,
+                BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
+        addCatalogItemWithTypeAsName(
+                OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+                TEST_VERSION,
+                BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
         
         // test load and instantiate
-        Entity me = addItemFromCatalog( mgmt.getCatalog().getCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY) );
+        Entity me = addItemFromCatalog( mgmt.getCatalog().getCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION) );
         /*
          * WARNING - Weird maven-bundle-plugin and OSGi behaviour.  Some caveats:
          * <p>
@@ -346,30 +372,30 @@ public class OsgiVersionMoreEntityTest {
 
         Maybe<Bundle> versionIgnoresInvalidPreferredUrl = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework())
             .symbolicName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL)
-            .version("0.1.0")
+            .version(TEST_VERSION)
             .preferringFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL).find();
         Assert.assertTrue(versionIgnoresInvalidPreferredUrl.isPresent());
-        Assert.assertEquals(versionIgnoresInvalidPreferredUrl.get().getVersion().toString(), "0.1.0");
+        Assert.assertEquals(versionIgnoresInvalidPreferredUrl.get().getVersion().toString(), TEST_VERSION);
 
         Maybe<Bundle> versionRespectsInvalidRequiredUrl = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework())
             .symbolicName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL)
-            .version("0.1.0")
+            .version(TEST_VERSION)
             .requiringFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL).find();
         Assert.assertFalse(versionRespectsInvalidRequiredUrl.isPresent());
 
         // test entity resolution
         
-        Entity v2 = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v2") );
+        Entity v2 = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v2", TEST_VERSION) );
         assertV2MethodCall(v2);
         assertV2EffectorCall(v2);
         Assert.assertEquals(v2.getPolicies().size(), 1, "Wrong number of policies: "+v2.getPolicies());
 
-        Entity v2_evil = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v2-evil") );
+        Entity v2_evil = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v2-evil", TEST_VERSION) );
         assertV2EvilTwinMethodCall(v2_evil);
         assertV2EvilTwinEffectorCall(v2_evil);
         Assert.assertEquals(v2_evil.getPolicies().size(), 1, "Wrong number of policies: "+v2_evil.getPolicies());
 
-        Entity v1 = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v1") );
+        Entity v1 = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v1", TEST_VERSION) );
         assertV1MethodCall(v1);
         assertV1EffectorCall(v1);
         Assert.assertEquals(v1.getPolicies().size(), 0, "Wrong number of policies: "+v1.getPolicies());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 2adad06..b384d98 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -36,6 +36,7 @@ import javax.annotation.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.config.ConfigKey;
@@ -190,7 +191,10 @@ public class BrooklynComponentTemplateResolver {
     public CatalogItem<Entity,EntitySpec<?>> getCatalogItem() {
         String type = getBrooklynType();
         if (type != null) {
-            return loader.getManagementContext().getCatalog().getCatalogItem(Entity.class, type);
+            BrooklynCatalog catalog = loader.getManagementContext().getCatalog();
+            return catalog.getCatalogItem(Entity.class,
+                    CatalogUtils.getIdFromVersionedId(type),
+                    CatalogUtils.getVersionFromVersionedId(type));
         } else {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
index 0025cf8..13c6454 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
@@ -25,6 +25,7 @@ import java.util.Map;
 
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.entity.proxying.EntityInitializer;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.ManagementContext;
@@ -108,7 +109,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
             String policyType = decoLoader.getTypeName().get();
             ManagementContext mgmt = instantiator.loader.getManagementContext();
             BrooklynCatalog catalog = mgmt.getCatalog();
-            CatalogItem<?, ?> item = catalog.getCatalogItem(policyType);
+            CatalogItem<?, ?> item = getPolicyCatalogItem(catalog, policyType);
             PolicySpec<? extends Policy> spec;
             if (item != null) {
                 spec = (PolicySpec<? extends Policy>) catalog.createSpec(item);
@@ -120,6 +121,15 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
             }
             decorations.add(spec);
         }
+        private CatalogItem<?, ?> getPolicyCatalogItem(BrooklynCatalog catalog, String policyType) {
+            String id = CatalogUtils.getIdFromVersionedId(policyType);
+            String version = CatalogUtils.getVersionFromVersionedId(policyType);
+            if (id != null) {
+                return catalog.getCatalogItem(id, version);
+            } else {
+                return catalog.getCatalogItem(policyType);
+            }
+        }
     }
 
     public static class EnricherSpecResolver extends BrooklynEntityDecorationResolver<EnricherSpec<?>> {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
index 8d815ee..c329193 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
@@ -26,6 +26,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.entity.Entity;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.ManagementContext;
@@ -40,7 +41,7 @@ public abstract class AbstractTemplateBrooklynLookup<T extends AbstractResource>
 
     @Override
     public T get(String id) {
-        CatalogItem<?,?> item = bmc.getCatalog().getCatalogItem(id);
+        CatalogItem<?,?> item = getCatalogItem(id);
         if (item==null) {
             log.warn("Could not find item '"+id+"' in Brooklyn catalog; returning null");
             return null;
@@ -48,6 +49,16 @@ public abstract class AbstractTemplateBrooklynLookup<T extends AbstractResource>
         return adapt(item);
     }
 
+    private CatalogItem<?, ?> getCatalogItem(String versionedId) {
+        String id = CatalogUtils.getIdFromVersionedId(versionedId);
+        String version = CatalogUtils.getVersionFromVersionedId(versionedId);
+        if (id != null) {
+            return bmc.getCatalog().getCatalogItem(id, version);
+        } else {
+            return bmc.getCatalog().getCatalogItem(id);
+        }
+    }
+
     public abstract T adapt(CatalogItem<?,?> item);
 
     protected ResolvableLink<T> newLink(CatalogItem<? extends Entity,EntitySpec<?>> li) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlTest.java
index d9186a3..61e3e4f 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlTest.java
@@ -44,6 +44,7 @@ import com.google.common.base.Joiner;
 public abstract class AbstractYamlTest {
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractYamlTest.class);
+    protected static final String TEST_VERSION = "0.1.2";
 
     private ManagementContext brooklynMgmt;
     protected BrooklynCampPlatform platform;
@@ -137,9 +138,9 @@ public abstract class AbstractYamlTest {
     }
 
     protected void deleteCatalogEntity(String catalogItem) {
-        mgmt().getCatalog().deleteCatalogItem(catalogItem);
+        mgmt().getCatalog().deleteCatalogItem(catalogItem, TEST_VERSION);
     }
-    
+
     protected Logger getLogger() {
         return LOG;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
index 83cd46d..dfbc96b 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
@@ -28,6 +28,7 @@ import java.util.Collection;
 import org.testng.annotations.Test;
 
 import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.BasicEntity;
 import brooklyn.management.osgi.OsgiStandaloneTest;
@@ -44,30 +45,62 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
     public void testAddCatalogItem() throws Exception {
         String registeredTypeName = "my.catalog.app.id.load";
         addCatalogOSGiEntity(registeredTypeName);
-
-        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName);
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName, TEST_VERSION);
         assertEquals(item.getRegisteredTypeName(), registeredTypeName);
 
         deleteCatalogEntity(registeredTypeName);
     }
 
     @Test
+    public void testAddCatalogItemWithoutVersionFail() throws Exception {
+        try {
+            addCatalogItem(
+                "brooklyn.catalog:",
+                "  name: My Catalog App",
+                "services:",
+                "- type: " + SIMPLE_ENTITY_TYPE);
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertEquals(e.getMessage(), "'version' attribute missing in 'brooklyn.catalog' section.");
+        }
+    }
+
+    @Test
     public void testLaunchApplicationReferencingCatalog() throws Exception {
         String registeredTypeName = "my.catalog.app.id.launch";
         registerAndLaunchAndAssertSimpleEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
     }
 
     @Test
+    public void testLaunchApplicationReferencingUnversionedCatalogFail() throws Exception {
+        String registeredTypeName = "my.catalog.app.id.fail";
+        addCatalogOSGiEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
+        try {
+            String yaml = "name: simple-app-yaml\n" +
+                          "location: localhost\n" +
+                          "services: \n" +
+                          "  - serviceType: " + registeredTypeName;
+            try {
+                createAndStartApplication(yaml);
+            } catch (UnsupportedOperationException e) {
+                assertTrue(e.getMessage().endsWith("cannot be matched"));
+            }
+        } finally {
+            deleteCatalogEntity(registeredTypeName);
+        }
+    }
+
+    @Test
     public void testLaunchApplicationWithCatalogReferencingOtherCatalog() throws Exception {
         String referencedRegisteredTypeName = "my.catalog.app.id.referenced";
         String referrerRegisteredTypeName = "my.catalog.app.id.referring";
         addCatalogOSGiEntity(referencedRegisteredTypeName, SIMPLE_ENTITY_TYPE);
-        addCatalogOSGiEntity(referrerRegisteredTypeName, referencedRegisteredTypeName);
+        addCatalogOSGiEntity(referrerRegisteredTypeName, ver(referencedRegisteredTypeName));
 
         String yaml = "name: simple-app-yaml\n" +
                       "location: localhost\n" +
                       "services: \n" +
-                      "  - serviceType: "+referrerRegisteredTypeName;
+                      "  - serviceType: " + ver(referrerRegisteredTypeName);
         Entity app = createAndStartApplication(yaml);
 
         Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
@@ -159,7 +192,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
             "  name: My Catalog App",
             "  description: My description",
             "  icon_url: classpath://path/to/myicon.jpg",
-            "  version: 0.1.2",
+            "  version: " + TEST_VERSION,
             "  libraries:",
             "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
             "",
@@ -184,4 +217,7 @@ public class CatalogYamlEntityTest extends AbstractYamlTest {
             "  - type: " + serviceType);
     }
 
+    private String ver(String id) {
+        return id + CatalogUtils.VERSION_DELIMITER + TEST_VERSION;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7f599246/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
index 0d5c44d..e704ea1 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
@@ -43,7 +43,7 @@ public class CatalogYamlPolicyTest extends AbstractYamlTest {
         String registeredTypeName = "my.catalog.policy.id.load";
         addCatalogOSGiPolicy(registeredTypeName, SIMPLE_POLICY_TYPE);
 
-        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName);
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName, TEST_VERSION);
         assertEquals(item.getRegisteredTypeName(), registeredTypeName);
         assertEquals(countCatalogPolicies(), 1);
 
@@ -117,7 +117,7 @@ public class CatalogYamlPolicyTest extends AbstractYamlTest {
             "  name: My Catalog Policy",
             "  description: My description",
             "  icon_url: classpath://path/to/myicon.jpg",
-            "  version: 0.1.2",
+            "  version: " + TEST_VERSION,
             "  libraries:",
             "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
             "",