address most review comments on relations
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/ed113a34 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/ed113a34 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/ed113a34 Branch: refs/heads/master Commit: ed113a348dbf214a2d8977e6179d5c0ebbf8c439 Parents: 1b71134 Author: Alex Heneveld <[email protected]> Authored: Tue Oct 27 11:29:00 2015 +0000 Committer: Alex Heneveld <[email protected]> Committed: Tue Oct 27 11:51:42 2015 +0000 ---------------------------------------------------------------------- .../org/apache/brooklyn/api/entity/Entity.java | 8 +- .../apache/brooklyn/api/location/Location.java | 7 -- .../api/mgmt/rebind/RebindExceptionHandler.java | 5 ++ .../mementos/BrooklynMementoPersister.java | 5 +- .../api/mgmt/rebind/mementos/Memento.java | 3 +- .../brooklyn/api/objs/BrooklynObject.java | 4 +- .../apache/brooklyn/api/objs/Configurable.java | 3 +- .../org/apache/brooklyn/api/policy/Policy.java | 5 -- .../core/catalog/internal/CatalogItemDo.java | 6 +- .../brooklyn/core/entity/EntityRelations.java | 8 +- .../AbstractBrooklynObjectRebindSupport.java | 14 +++- .../mgmt/rebind/RebindContextLookupContext.java | 18 +++++ .../mgmt/rebind/RebindExceptionHandlerImpl.java | 17 ++++- .../core/mgmt/rebind/dto/AbstractMemento.java | 19 +++-- .../mgmt/rebind/dto/MementosGenerators.java | 15 ++-- .../relations/AbstractBasicRelationSupport.java | 8 +- .../relations/ByObjectBasicRelationSupport.java | 7 +- .../core/relations/EmptyRelationSupport.java | 60 +++++++++++++++ .../mgmt/persist/XmlMementoSerializerTest.java | 18 +++++ .../rebind/RebindClassInitializationTest.java | 78 ++++++++++++++++++++ .../core/mgmt/rebind/RebindEntityTest.java | 3 +- 21 files changed, 254 insertions(+), 57 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java index a15f4e1..3b333e0 100644 --- a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java +++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java @@ -216,15 +216,9 @@ public interface Entity extends BrooklynObject { * via code like {@code sensors().get(key)}. */ <T> T getAttribute(AttributeSensor<T> sensor); - - /** - * Convenience for calling {@link ConfigurationSupport#get(ConfigKey)}, - * via code like {@code config().get(key)}. - */ - <T> T getConfig(ConfigKey<T> key); /** - * @see #getConfig(ConfigKey)} + * @see {@link #getConfig(ConfigKey)} */ <T> T getConfig(HasConfigKey<T> key); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/location/Location.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/location/Location.java b/api/src/main/java/org/apache/brooklyn/api/location/Location.java index 392af13..84e371b 100644 --- a/api/src/main/java/org/apache/brooklyn/api/location/Location.java +++ b/api/src/main/java/org/apache/brooklyn/api/location/Location.java @@ -89,13 +89,6 @@ public interface Location extends Serializable, BrooklynObject { */ boolean containsLocation(Location potentialDescendent); - /** - * Returns configuration set at this location or inherited or default. - * - * Convenience method for {@code config().get(key)} - */ - <T> T getConfig(ConfigKey<T> key); - /** * Convenience method for {@code config().get(key)} * http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java index 48bb07f..9660930 100644 --- a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java +++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java @@ -80,6 +80,11 @@ public interface RebindExceptionHandler { */ CatalogItem<?, ?> onDanglingCatalogItemRef(String id); + /** + * @return the item to use in place of the missing one + */ + BrooklynObject onDanglingUntypedItemRef(String id); + void onCreateFailed(BrooklynObjectType type, String id, String instanceType, Exception e); void onNotFound(BrooklynObjectType type, String id); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java index e554e08..03673fd 100644 --- a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java +++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java @@ -57,9 +57,10 @@ public interface BrooklynMementoPersister { Feed lookupFeed(String id); CatalogItem<?, ?> lookupCatalogItem(String id); - BrooklynObject lookup(BrooklynObjectType type, String objectId); + /** retrieve the item with the given ID, optionally ensuring it is of the indicated type; null if not found */ + BrooklynObject lookup(@Nullable BrooklynObjectType type, String objectId); /** like {@link #lookup(BrooklynObjectType, String)} but doesn't record an exception if not found */ - BrooklynObject peek(BrooklynObjectType type, String objectId); + BrooklynObject peek(@Nullable BrooklynObjectType type, String objectId); } /** http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java index b57780d..5911f28 100644 --- a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java +++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java @@ -25,7 +25,6 @@ import java.util.Set; import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.mgmt.rebind.RebindSupport; -import org.apache.brooklyn.api.objs.BrooklynObject; import org.apache.brooklyn.api.objs.EntityAdjunct; /** @@ -79,7 +78,7 @@ public interface Memento extends Serializable { public Collection<Object> getTags(); - Map<String, Set<BrooklynObject>> getRelations(); + public Map<String,Set<String>> getRelations(); /** Null for {@link Entity}, but important for adjuncts; see {@link EntityAdjunct#getUniqueTag()} */ public String getUniqueTag(); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java index 8648491..9e1640f 100644 --- a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java +++ b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java @@ -151,8 +151,8 @@ public interface BrooklynObject extends Identifiable, Configurable { } public interface RelationSupport<T extends BrooklynObject> { - public <U extends BrooklynObject> void add(Relationship<? super T,U> relationship, U target); - public <U extends BrooklynObject> void remove(Relationship<? super T,U> relationship, U target); + public <U extends BrooklynObject> void add(Relationship<? super T,? super U> relationship, U target); + public <U extends BrooklynObject> void remove(Relationship<? super T,? super U> relationship, U target); public Set<Relationship<? super T,? extends BrooklynObject>> getRelationships(); public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super T,U> relationship); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java index 5f1b294..84b1fcb 100644 --- a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java +++ b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java @@ -42,7 +42,8 @@ public interface Configurable { public <T> T setConfig(ConfigKey<T> key, T val); /** - * Convenience method for {@code config().get(key)} + * Convenience for calling {@link ConfigurationSupport#get(ConfigKey)}, + * via code like {@code config().get(key)}. */ <T> T getConfig(ConfigKey<T> key); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java b/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java index 957da0a..0235bac 100644 --- a/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java +++ b/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java @@ -60,11 +60,6 @@ public interface Policy extends EntityAdjunct, Rebindable, Configurable { boolean isSuspended(); /** - * Convenience method for {@code config().get(key)} - */ - <T> T getConfig(ConfigKey<T> key); - - /** * @deprecated since 0.7.0; use {@link #config()}, such as {@code policy.config().set(key, val)} */ @Deprecated http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java index 7f3a54a..a3ae36e 100644 --- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java +++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java @@ -29,6 +29,7 @@ import org.apache.brooklyn.api.mgmt.rebind.RebindSupport; import org.apache.brooklyn.api.mgmt.rebind.mementos.CatalogItemMemento; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.objs.BrooklynObjectInternal; +import org.apache.brooklyn.core.relations.EmptyRelationSupport; import com.google.common.base.Preconditions; @@ -65,11 +66,12 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObj } /** - * @throws UnsupportedOperationException; relations are not supported for catalog items + * @return an immutable empty relation support object; relations are not supported, + * but we do not throw on access to enable reads in a consistent manner */ @Override public RelationSupportInternal<CatalogItem<T,SpecT>> relations() { - throw new UnsupportedOperationException(); + return new EmptyRelationSupport<CatalogItem<T,SpecT>>(this); } @Override http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java index 7b20845..7dfa93e 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java @@ -136,23 +136,23 @@ public class EntityRelations<T extends BrooklynObject> { } @SuppressWarnings({ "rawtypes", "unchecked" }) - public static <T extends BrooklynObject> Set<Relationship<? super T,? extends BrooklynObject>> getRelations(T source) { + public static <T extends BrooklynObject> Set<Relationship<? super T,? extends BrooklynObject>> getRelationships(T source) { return ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelationships(); } @SuppressWarnings({ "rawtypes", "unchecked" }) - public static <T extends BrooklynObject,U extends BrooklynObject> Set<U> getRelationships(Relationship<? super T,U> relationship, T source) { + public static <T extends BrooklynObject,U extends BrooklynObject> Set<U> getRelations(Relationship<? super T,U> relationship, T source) { return ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelations(relationship); } @SuppressWarnings({ "rawtypes", "unchecked" }) - public static <T extends BrooklynObject,U extends BrooklynObject> void add(T source, Relationship<? super T,U> relationship, U target) { + public static <T extends BrooklynObject,U extends BrooklynObject> void add(T source, Relationship<? super T,? super U> relationship, U target) { ((BrooklynObjectInternal)source).relations().getLocalBackingStore().add(relationship, target); ((BrooklynObjectInternal)target).relations().getLocalBackingStore().add(relationship.getInverseRelationship(), source); } @SuppressWarnings({ "rawtypes", "unchecked" }) - public static <T extends BrooklynObject,U extends BrooklynObject> void remove(T source, Relationship<? super T,U> relationship, U target) { + public static <T extends BrooklynObject,U extends BrooklynObject> void remove(T source, Relationship<? super T,? super U> relationship, U target) { ((BrooklynObjectInternal)source).relations().getLocalBackingStore().remove(relationship, target); ((BrooklynObjectInternal)target).relations().getLocalBackingStore().remove(relationship.getInverseRelationship(), source); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java index 74a7dca..414cdbe 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java @@ -86,11 +86,19 @@ public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> imp @SuppressWarnings({ "unchecked", "rawtypes" }) protected void addRelations(RebindContext rebindContext, T memento) { - for (Map.Entry<String,Set<BrooklynObject>> rEntry : memento.getRelations().entrySet()) { + for (Map.Entry<String,Set<String>> rEntry : memento.getRelations().entrySet()) { Relationship<? extends BrooklynObject, ? extends BrooklynObject> r = EntityRelations.lookup(instance.getManagementContext(), rEntry.getKey()); if (r==null) throw new IllegalStateException("Unsupported relationship -- "+rEntry.getKey() + " -- in "+memento); - for (BrooklynObject item: rEntry.getValue()) - instance.relations().add((Relationship)r, item); + for (String itemId: rEntry.getValue()) { + BrooklynObject item = rebindContext.lookup().lookup(null, itemId); + if (item != null) { + instance.relations().add((Relationship)r, item); + } else { + LOG.warn("Item not found; discarding item {} relation {} of entity {}({})", + new Object[] {itemId, r, memento.getType(), memento.getId()}); + rebindContext.getExceptionHandler().onDanglingUntypedItemRef(itemId); + } + } } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextLookupContext.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextLookupContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextLookupContext.java index 550f376..1faaa1c 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextLookupContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextLookupContext.java @@ -18,6 +18,8 @@ */ package org.apache.brooklyn.core.mgmt.rebind; +import java.util.NoSuchElementException; + import javax.annotation.Nullable; import org.slf4j.Logger; @@ -127,6 +129,14 @@ public class RebindContextLookupContext implements LookupContext { @Override public BrooklynObject lookup(BrooklynObjectType type, String id) { + if (type==null) { + BrooklynObject result = peek(null, id); + if (result==null) { + exceptionHandler.onDanglingUntypedItemRef(id); + } + type = BrooklynObjectType.of(result); + } + switch (type) { case CATALOG_ITEM: return lookupCatalogItem(id); case ENRICHER: return lookupEnricher(id); @@ -141,6 +151,14 @@ public class RebindContextLookupContext implements LookupContext { @Override public BrooklynObject peek(BrooklynObjectType type, String id) { + if (type==null) { + for (BrooklynObjectType typeX: BrooklynObjectType.values()) { + BrooklynObject result = peek(typeX, id); + if (result!=null) return result; + } + return null; + } + switch (type) { case CATALOG_ITEM: return rebindContext.getCatalogItem(id); case ENRICHER: return rebindContext.getEnricher(id); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindExceptionHandlerImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindExceptionHandlerImpl.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindExceptionHandlerImpl.java index b6b7fc4..7b4cd00 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindExceptionHandlerImpl.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindExceptionHandlerImpl.java @@ -65,6 +65,7 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler { protected final Set<String> missingEnrichers = Sets.newConcurrentHashSet(); protected final Set<String> missingFeeds = Sets.newConcurrentHashSet(); protected final Set<String> missingCatalogItems = Sets.newConcurrentHashSet(); + protected final Set<String> missingUntypedItems = Sets.newConcurrentHashSet(); protected final Set<String> creationFailedIds = Sets.newConcurrentHashSet(); protected final Set<Exception> addPolicyFailures = Sets.newConcurrentHashSet(); @@ -237,6 +238,17 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler { } @Override + public CatalogItem<?, ?> onDanglingUntypedItemRef(String id) { + missingUntypedItems.add(id); + if (danglingRefFailureMode == RebindManager.RebindFailureMode.FAIL_FAST) { + throw new IllegalStateException("No item found with id "+id); + } else { + warn("No item found with id "+id+"; dangling reference on rebind"); + return null; + } + } + + @Override public void onCreateFailed(BrooklynObjectType type, String id, String instanceType, Exception e) { Exceptions.propagateIfFatal(e); String errmsg = "problem creating "+type+" "+id+" of type "+instanceType; @@ -395,7 +407,7 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler { } done = true; - List<String> danglingIds = MutableList.copyOf(missingEntities).appendAll(missingLocations).appendAll(missingPolicies).appendAll(missingEnrichers).appendAll(missingFeeds).appendAll(missingCatalogItems); + List<String> danglingIds = MutableList.copyOf(missingEntities).appendAll(missingLocations).appendAll(missingPolicies).appendAll(missingEnrichers).appendAll(missingFeeds).appendAll(missingCatalogItems).appendAll(missingUntypedItems); int totalDangling = danglingIds.size(); if (totalDangling>0) { int totalFound = context.getAllBrooklynObjects().size(); @@ -441,6 +453,9 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler { if (!missingCatalogItems.isEmpty()) { allExceptions.add(new IllegalStateException("Missing referenced catalog item" + Strings.s(missingCatalogItems) + ": " + missingCatalogItems)); } + if (!missingUntypedItems.isEmpty()) { + allExceptions.add(new IllegalStateException("Missing referenced untyped items" + Strings.s(missingUntypedItems) + ": " + missingUntypedItems)); + } } if (rebindFailureMode != RebindManager.RebindFailureMode.CONTINUE) { allExceptions.addAll(exceptions); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java index 1fae585..6fae7f5 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java @@ -25,14 +25,15 @@ import java.util.Map; import java.util.Set; import org.apache.brooklyn.api.mgmt.rebind.mementos.Memento; -import org.apache.brooklyn.api.objs.BrooklynObject; import org.apache.brooklyn.core.BrooklynVersion; import org.apache.brooklyn.core.config.Sanitizer; import com.google.common.base.Objects; import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; public abstract class AbstractMemento implements Memento, Serializable { @@ -47,8 +48,8 @@ public abstract class AbstractMemento implements Memento, Serializable { protected String catalogItemId; protected Map<String, Object> customFields = Maps.newLinkedHashMap(); protected List<Object> tags = Lists.newArrayList(); - protected Map<String,Set<BrooklynObject>> relations = Maps.newLinkedHashMap(); - + protected Map<String,Set<String>> relations = Maps.newLinkedHashMap(); + // only supported for EntityAdjuncts protected String uniqueTag; @@ -86,7 +87,7 @@ public abstract class AbstractMemento implements Memento, Serializable { private String displayName; private String catalogItemId; private List<Object> tags; - private Map<String, Set<BrooklynObject>> relations; + private Map<String,Set<String>> relations; // for EntityAdjuncts; not used for entity private String uniqueTag; @@ -156,7 +157,7 @@ public abstract class AbstractMemento implements Memento, Serializable { } @Override - public Map<String, Set<BrooklynObject>> getRelations() { + public Map<String,Set<String>> getRelations() { return fromPersistedMap(relations); } @@ -218,4 +219,12 @@ public abstract class AbstractMemento implements Memento, Serializable { if (m==null || m.isEmpty()) return null; return m; } + protected <K,V> Multimap<K,V> fromPersistedMultimap(Multimap<K,V> m) { + if (m==null) return ImmutableMultimap.of(); + return ImmutableMultimap.copyOf(m); + } + protected <K,V> Multimap<K,V> toPersistedMultimap(Multimap<K,V> m) { + if (m==null || m.isEmpty()) return null; + return m; + } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java index 6cfda79..918278c 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java @@ -66,6 +66,7 @@ import org.apache.brooklyn.util.core.flags.FlagUtils; import com.google.common.annotations.Beta; import com.google.common.base.Function; import com.google.common.base.Predicates; +import com.google.common.collect.Sets; import brooklyn.basic.relations.Relationship; @@ -431,7 +432,6 @@ public class MementosGenerators { return builder.build(); } - @SuppressWarnings({ "unchecked", "rawtypes" }) private static void populateBrooklynObjectMementoBuilder(BrooklynObject instance, AbstractMemento.Builder<?> builder) { if (Proxy.isProxyClass(instance.getClass())) { throw new IllegalStateException("Attempt to create memento from proxy "+instance+" (would fail with wrong type)"); @@ -448,12 +448,13 @@ public class MementosGenerators { for (Object tag : instance.tags().getTags()) { builder.tags.add(tag); } - if (!(instance instanceof CatalogItem)) { - // CatalogItem is a BrooklynObject so it can be persisted - // but it does not support relations - for (Relationship<?,? extends BrooklynObject> relationship: instance.relations().getRelationships()) { - builder.relations.put(relationship.getRelationshipTypeName(), instance.relations().getRelations((Relationship)relationship)); - } + // CatalogItems return empty support, so this is safe even through they don't support relations + for (Relationship<?,? extends BrooklynObject> relationship: instance.relations().getRelationships()) { + @SuppressWarnings({ "unchecked", "rawtypes" }) + Set relations = instance.relations().getRelations((Relationship)relationship); + Set<String> relationIds = Sets.newLinkedHashSet(); + for (Object r: relations) relationIds.add( ((BrooklynObject)r).getId() ); + builder.relations.put(relationship.getRelationshipTypeName(), relationIds); } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java index e87d0ea..3694fa8 100644 --- a/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java +++ b/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java @@ -34,21 +34,21 @@ public abstract class AbstractBasicRelationSupport<SourceType extends BrooklynOb @Override public Set<Relationship<? super SourceType, ? extends BrooklynObject>> getRelationships() { - return EntityRelations.getRelations(source); + return EntityRelations.getRelationships(source); } @Override public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super SourceType, U> relationship) { - return EntityRelations.getRelationships(relationship, source); + return EntityRelations.getRelations(relationship, source); } @Override - public <U extends BrooklynObject> void add(Relationship<? super SourceType, U> relationship, U target) { + public <U extends BrooklynObject> void add(Relationship<? super SourceType, ? super U> relationship, U target) { EntityRelations.add(source, relationship, target); } @Override - public <U extends BrooklynObject> void remove(Relationship<? super SourceType, U> relationship, U target) { + public <U extends BrooklynObject> void remove(Relationship<? super SourceType, ? super U> relationship, U target) { EntityRelations.remove(source, relationship, target); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java index 1152e85..3600640 100644 --- a/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java +++ b/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java @@ -78,17 +78,18 @@ public class ByObjectBasicRelationSupport<SourceType extends BrooklynObject> ext } } + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override - public <U extends BrooklynObject> void add(Relationship<? super T,U> relationship, U target) { + public <U extends BrooklynObject> void add(Relationship<? super T,? super U> relationship, U target) { synchronized (relations) { - relationships.put(relationship.getRelationshipTypeName(), relationship); + relationships.put(relationship.getRelationshipTypeName(), (Relationship)relationship); relations.put(relationship.getRelationshipTypeName(), target); } onRelationsChanged(); } @Override - public <U extends BrooklynObject> void remove(Relationship<? super T,U> relationship, U target) { + public <U extends BrooklynObject> void remove(Relationship<? super T,? super U> relationship, U target) { synchronized (relations) { relations.remove(relationship.getRelationshipTypeName(), target); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java new file mode 100644 index 0000000..40b001a --- /dev/null +++ b/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.core.relations; + +import java.util.Collections; +import java.util.Set; + +import org.apache.brooklyn.api.objs.BrooklynObject; +import org.apache.brooklyn.api.objs.BrooklynObject.RelationSupport; +import org.apache.brooklyn.core.objs.BrooklynObjectInternal.RelationSupportInternal; + +import brooklyn.basic.relations.Relationship; + +public final class EmptyRelationSupport<SourceType extends BrooklynObject> implements RelationSupportInternal<SourceType> { + + final SourceType source; + + public EmptyRelationSupport(SourceType source) { this.source = source; } + + @Override + public Set<Relationship<? super SourceType, ? extends BrooklynObject>> getRelationships() { + return Collections.emptySet(); + } + + @Override + public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super SourceType, U> relationship) { + return Collections.emptySet(); + } + + @Override + public <U extends BrooklynObject> void add(Relationship<? super SourceType, ? super U> relationship, U target) { + throw new UnsupportedOperationException("Relations not available on "+source); + } + + @Override + public <U extends BrooklynObject> void remove(Relationship<? super SourceType, ? super U> relationship, U target) { + } + + @Override + public RelationSupport<SourceType> getLocalBackingStore() { + throw new UnsupportedOperationException("Relations not available on "+source); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java index 246e214..3ed5486 100644 --- a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java @@ -516,6 +516,16 @@ System.out.println("XXX: "+x); @Override public BrooklynObject lookup(BrooklynObjectType type, String id) { + if (type==null) { + BrooklynObject result = peek(null, id); + if (result==null) { + if (failOnDangling) { + throw new NoSuchElementException("no brooklyn object with id "+id+"; type not specified"); + } + } + type = BrooklynObjectType.of(result); + } + switch (type) { case CATALOG_ITEM: return lookupCatalogItem(id); case ENRICHER: return lookupEnricher(id); @@ -529,6 +539,14 @@ System.out.println("XXX: "+x); } @Override public BrooklynObject peek(BrooklynObjectType type, String id) { + if (type==null) { + for (BrooklynObjectType typeX: BrooklynObjectType.values()) { + BrooklynObject result = peek(typeX, id); + if (result!=null) return result; + } + return null; + } + switch (type) { case CATALOG_ITEM: return catalogItems.get(id); case ENRICHER: return enrichers.get(id); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindClassInitializationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindClassInitializationTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindClassInitializationTest.java new file mode 100644 index 0000000..a5105cc --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindClassInitializationTest.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.core.mgmt.rebind; + +import java.util.List; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.core.entity.AbstractEntity; +import org.apache.brooklyn.util.collections.MutableList; +import org.apache.brooklyn.util.text.Strings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class RebindClassInitializationTest extends RebindTestFixtureWithApp { + + private static final Logger log = LoggerFactory.getLogger(RebindClassInitializationTest.class); + static List<String> messages = MutableList.of(); + + @Test + public void testRestoresSimpleApp() throws Exception { + messages.clear(); + messages.add("creating"); + origApp.createAndManageChild(EntitySpec.create(Entity.class, MyEntityForClassInitializationTesting.class)); + messages.add("created"); + messages.add("rebinding"); + newApp = rebind(); + messages.add("rebinded"); + + log.debug("Create and rebind message sequence is:\n- "+Strings.join(messages, "\n- ")); + Assert.assertEquals(messages, MutableList.of( + "creating", "ME.static_initializer", "ME.initializer", + "WIM.static_initializer", "WIM.initializer", "WIM.constructor", + "ME.constructor", "created", + "rebinding", "ME.initializer", "WIM.initializer", "WIM.constructor", + "ME.constructor", "rebinded")); + } + + public static class MyEntityForClassInitializationTesting extends AbstractEntity { + + { messages.add("ME.initializer"); } + + static { messages.add("ME.static_initializer"); } + + @SuppressWarnings("unused") + private final Object dummy = new WriteInitMessage(); + + public MyEntityForClassInitializationTesting() { + messages.add("ME.constructor"); + } + } + + private static class WriteInitMessage { + public WriteInitMessage() { messages.add("WIM.constructor"); } + + { messages.add("WIM.initializer"); } + + static { messages.add("WIM.static_initializer"); } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java index 900b492..7c726e4 100644 --- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java @@ -49,9 +49,9 @@ import org.apache.brooklyn.api.mgmt.rebind.RebindSupport; import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoManifest; import org.apache.brooklyn.api.mgmt.rebind.mementos.EntityMemento; import org.apache.brooklyn.api.sensor.AttributeSensor; +import org.apache.brooklyn.api.sensor.AttributeSensor.SensorPersistenceMode; import org.apache.brooklyn.api.sensor.SensorEvent; import org.apache.brooklyn.api.sensor.SensorEventListener; -import org.apache.brooklyn.api.sensor.AttributeSensor.SensorPersistenceMode; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.config.BasicConfigKey; import org.apache.brooklyn.core.entity.AbstractEntity; @@ -61,7 +61,6 @@ import org.apache.brooklyn.core.entity.trait.Resizable; import org.apache.brooklyn.core.entity.trait.Startable; import org.apache.brooklyn.core.location.LocationConfigTest.MyLocation; import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; -import org.apache.brooklyn.core.mgmt.rebind.BasicEntityRebindSupport; import org.apache.brooklyn.core.sensor.BasicAttributeSensor; import org.apache.brooklyn.core.sensor.BasicSensorEvent; import org.apache.brooklyn.core.sensor.DependentConfiguration;
