This is an automated email from the ASF dual-hosted git repository.

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git


The following commit(s) were added to refs/heads/master by this push:
     new 83c17b5f71 accept policy and adjunct spec as registered types from 
workflow blueprint
83c17b5f71 is described below

commit 83c17b5f71b5296227743ff0b6800a809710742a
Author: Alex Heneveld <[email protected]>
AuthorDate: Mon Dec 12 11:10:08 2022 +0000

    accept policy and adjunct spec as registered types from workflow blueprint
---
 .../brooklyn/spi/creation/CampInternalUtils.java   | 36 +++++----
 .../camp/brooklyn/spi/creation/CampResolver.java   | 86 +++++++++++++++++-----
 .../spi/dsl/methods/BrooklynDslCommon.java         | 23 ++++--
 .../brooklyn/camp/brooklyn/WorkflowYamlTest.java   | 36 +++++++++
 .../brooklyn/core/mgmt/EntityManagementUtils.java  |  1 +
 .../typereg/RegisteredTypeLoadingContexts.java     |  4 +-
 .../steps/appmodel/AddPolicyWorkflowStep.java      | 20 +++--
 .../brooklyn/util/exceptions/Exceptions.java       |  5 +-
 8 files changed, 166 insertions(+), 45 deletions(-)

diff --git 
a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
 
b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
index e2423967ef..b916e09b6d 100644
--- 
a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
+++ 
b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
@@ -125,13 +125,17 @@ class CampInternalUtils {
 
         //Would ideally re-use the PolicySpecResolver
         //but it is CAMP specific and there is no easy way to get hold of it.
-        Object policies = 
checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.POLICIES_KEY), 
"policy config");
-        if (!(policies instanceof Iterable<?>)) {
-            throw new IllegalStateException("The value of " + 
BasicBrooklynCatalog.POLICIES_KEY + " must be an Iterable.");
+        Object policy;
+        if 
(plan.getCustomAttributes().containsKey(BasicBrooklynCatalog.POLICIES_KEY)) {
+            Object policies = 
checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.POLICIES_KEY), 
"policy config");
+            if (!(policies instanceof Iterable<?>)) {
+                throw new IllegalStateException("The value of " + 
BasicBrooklynCatalog.POLICIES_KEY + " must be an Iterable.");
+            }
+            policy = Iterables.getOnlyElement((Iterable<?>) policies);
+        } else {
+            policy = Iterables.getOnlyElement(Yamls.parseAll(yamlPlan));
         }
 
-        Object policy = Iterables.getOnlyElement((Iterable<?>)policies);
-
         return createPolicySpec(loader, policy, encounteredCatalogTypes);
     }
 
@@ -155,16 +159,22 @@ class CampInternalUtils {
     static EnricherSpec<?> createEnricherSpec(String yamlPlan, 
BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes) {
         DeploymentPlan plan = makePlanFromYaml(loader.getManagementContext(), 
yamlPlan);
 
-        //Would ideally re-use the EnricherSpecResolver
-        //but it is CAMP specific and there is no easy way to get hold of it.
-        Object enrichers = 
checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.ENRICHERS_KEY),
 "enricher config");
-        if (!(enrichers instanceof Iterable<?>)) {
-            throw new IllegalStateException("The value of " + 
BasicBrooklynCatalog.ENRICHERS_KEY + " must be an Iterable.");
-        }
+        Object enricher;
+        if 
(plan.getCustomAttributes().containsKey(BasicBrooklynCatalog.ENRICHERS_KEY)) {
+            //Would ideally re-use the EnricherSpecResolver
+            //but it is CAMP specific and there is no easy way to get hold of 
it.
+            Object enrichers = 
checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.ENRICHERS_KEY),
 "enricher config");
+            if (!(enrichers instanceof Iterable<?>)) {
+                throw new IllegalStateException("The value of " + 
BasicBrooklynCatalog.ENRICHERS_KEY + " must be an Iterable.");
+            }
+
+            enricher = Iterables.getOnlyElement((Iterable<?>)enrichers);
 
-        Object policy = Iterables.getOnlyElement((Iterable<?>)enrichers);
+        } else {
+            enricher = Iterables.getOnlyElement(Yamls.parseAll(yamlPlan));
+        }
 
-        return createEnricherSpec(loader, policy, encounteredCatalogTypes);
+        return createEnricherSpec(loader, enricher, encounteredCatalogTypes);
     }
 
     @SuppressWarnings("unchecked")
diff --git 
a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
 
b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
index 7a891081cb..2ad73f4d2c 100644
--- 
a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
+++ 
b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
@@ -19,11 +19,15 @@
 package org.apache.brooklyn.camp.brooklyn.spi.creation;
 
 import com.google.common.annotations.Beta;
+
+import java.util.Map;
 import java.util.Set;
 
 import java.util.Stack;
 import java.util.function.Consumer;
-import java.util.function.Function;
+
+import com.google.common.collect.Iterables;
+import com.google.common.reflect.TypeToken;
 import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
@@ -35,14 +39,12 @@ import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.sensor.Enricher;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
-import org.apache.brooklyn.camp.BasicCampPlatform;
 import org.apache.brooklyn.camp.CampPlatform;
 import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
 import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
 import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslUtils;
 import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent;
 import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
-import org.apache.brooklyn.camp.brooklyn.spi.dsl.parse.DslParser;
 import org.apache.brooklyn.camp.spi.AssemblyTemplate;
 import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 import org.apache.brooklyn.config.ConfigKey;
@@ -50,12 +52,18 @@ import 
org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.entity.AbstractEntity;
 import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
+import org.apache.brooklyn.core.resolve.jackson.BeanWithTypePlanTransformer;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.core.typereg.UnsupportedTypePlanException;
 import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.core.flags.BrooklynTypeNameResolution;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.javalang.Reflections;
 import org.apache.brooklyn.util.text.Strings;
 
 import com.google.common.collect.ImmutableSet;
+import org.apache.brooklyn.util.yaml.Yamls;
 
 class CampResolver {
 
@@ -125,21 +133,7 @@ class CampResolver {
             String planYaml = 
RegisteredTypes.getImplementationDataStringForSpec(item);
             MutableSet<Object> supers = 
MutableSet.copyOf(item.getSuperTypes());
             supers.addIfNotNull(expectedType);
-            if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Policy.class)) {
-                spec = CampInternalUtils.createPolicySpec(planYaml, loader, 
encounteredTypes);
-            } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, 
Enricher.class)) {
-                spec = CampInternalUtils.createEnricherSpec(planYaml, loader, 
encounteredTypes);
-            } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, 
Location.class)) {
-                spec = CampInternalUtils.createLocationSpec(planYaml, loader, 
encounteredTypes);
-            } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, 
Application.class)) {
-                spec = createEntitySpecFromServicesBlock(mgmt, planYaml, 
loader, encounteredTypes, true);
-            } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, 
Entity.class)) {
-                spec = createEntitySpecFromServicesBlock(mgmt, planYaml, 
loader, encounteredTypes, false);
-            } else {
-                String msg = (item.getSuperTypes()==null || 
item.getSuperTypes().isEmpty()) ? "no supertypes declared" : "incompatible 
supertypes "+item.getSuperTypes();
-                String itemName = 
Strings.firstNonBlank(item.getSymbolicName(), 
BasicBrooklynCatalog.currentlyResolvingType.get(), "<unidentified>");
-                throw new IllegalStateException("Cannot create "+itemName+" as 
spec because "+msg+" ("+currentlyCreatingSpec.get()+")");
-            }
+            spec = createSpecPossiblyInferringSupers(mgmt, item, expectedType, 
loader, encounteredTypes, planYaml, supers, true);
             if (expectedType != null && 
!expectedType.isAssignableFrom(spec.getType())) {
                 throw new IllegalStateException("Creating spec from " + item + 
", got " + spec.getType() + " which is incompatible with expected " + 
expectedType);
             }
@@ -170,7 +164,61 @@ class CampResolver {
             }
         }
     }
- 
+
+    private static AbstractBrooklynObjectSpec<?, ?> 
createSpecPossiblyInferringSupers(ManagementContext mgmt, RegisteredType item, 
Class<?> expectedType, BrooklynClassLoadingContext loader, Set<String> 
encounteredTypes, String planYaml, MutableSet<Object> supers, boolean 
canInferSupers) {
+        if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Policy.class)) {
+            return CampInternalUtils.createPolicySpec(planYaml, loader, 
encounteredTypes);
+        } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Enricher.class)) 
{
+            return CampInternalUtils.createEnricherSpec(planYaml, loader, 
encounteredTypes);
+        } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Location.class)) 
{
+            return CampInternalUtils.createLocationSpec(planYaml, loader, 
encounteredTypes);
+        } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, 
Application.class)) {
+            return createEntitySpecFromServicesBlock(mgmt, planYaml, loader, 
encounteredTypes, true);
+        } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Entity.class)) {
+            return createEntitySpecFromServicesBlock(mgmt, planYaml, loader, 
encounteredTypes, false);
+        }
+
+        String msg = (item.getSuperTypes()==null || 
item.getSuperTypes().isEmpty()) ? "no supertypes declared" : "incompatible 
supertypes "+ item.getSuperTypes();
+
+        Exception error = null;
+        if (canInferSupers) {
+            try {
+                if (item.getPlan().getPlanData() instanceof String) {
+                    Object pm = 
Iterables.getOnlyElement(Yamls.parseAll((String) item.getPlan().getPlanData()));
+                    if (pm instanceof Map) {
+                        String t = new 
BrooklynYamlTypeInstantiator.Factory(loader, "camp-spec type 
inferencing").from((Map<?, ?>) pm).getTypeName().orNull();
+                        if (t != null) {
+                            Maybe<TypeToken<?>> tt = new 
BrooklynTypeNameResolution.BrooklynTypeNameResolver("camp-spec type 
inferencing", loader, true, true).findTypeToken(t);
+                            if (tt.isPresent()) {
+                                MutableSet<Object> newSupers = 
MutableSet.copyOf(supers);
+                                if (newSupers.add(tt.get().getRawType())) {
+                                    try {
+                                        return 
createSpecPossiblyInferringSupers(mgmt, item, expectedType, loader, 
encounteredTypes, planYaml, newSupers, false);
+                                    } catch (Exception e) {
+                                        error = e;
+                                        msg = "type "+t+" ("+tt.get()+") threw 
an error";
+                                    }
+                                } else {
+                                    msg += " (tried " + tt.get() + " from " + 
t + ")";
+                                }
+                            } else {
+                                msg += " (and could not load " + t + ")";
+                            }
+                        } else {
+                            msg += " (and no type specified)";
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                Exceptions.propagateIfFatal(e);
+                msg += " ("+e+")";
+            }
+        }
+
+        String itemName = Strings.firstNonBlank(item.getSymbolicName(), 
BasicBrooklynCatalog.currentlyResolvingType.get(), "<unidentified>");
+        throw new IllegalStateException("Cannot create "+itemName+" as spec 
because "+msg+" ("+currentlyCreatingSpec.get()+")", error);
+    }
+
     private static EntitySpec<?> 
createEntitySpecFromServicesBlock(ManagementContext mgmt, String plan, 
BrooklynClassLoadingContext loader, Set<String> encounteredTypes, boolean 
isApplication) {
         CampPlatform camp = 
CampInternalUtils.getCampPlatform(loader.getManagementContext());
 
diff --git 
a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
 
b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
index 4f5a90d483..1f7944100c 100644
--- 
a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
+++ 
b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@ -25,6 +25,7 @@ import java.util.*;
 
 import com.google.common.reflect.TypeToken;
 import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.typereg.RegisteredType;
@@ -59,6 +60,7 @@ import 
org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
 import org.apache.brooklyn.core.objs.AbstractConfigurationSupportInternal;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
+import org.apache.brooklyn.core.resolve.jackson.BeanWithTypePlanTransformer;
 import 
org.apache.brooklyn.core.resolve.jackson.BrooklynJacksonSerializationUtils;
 import org.apache.brooklyn.core.sensor.DependentConfiguration;
 import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
@@ -125,7 +127,11 @@ public class BrooklynDslCommon {
             @Override
             public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> type) {
                 BiFunction<ManagementContext, Object, Object> dslParse = 
BrooklynJacksonSerializationUtils.JsonDeserializerForCommonBrooklynThings.BROOKLYN_PARSE_DSL_FUNCTION;
-                if (!TypeTokens.equalsRaw(EntitySpec.class, type) || 
dslParse==null) {
+                if (!
+                        // TODO there is a JavaEntitySpecResolver but no 
analogue for adjuncts
+                        EntitySpec.class
+//                        AbstractBrooklynObjectSpec.class
+                        .isAssignableFrom(type.getRawType()) || 
dslParse==null) {
                     // only applies if a spec is wanted and dsl parse 
registered
                     return null;
                 }
@@ -139,16 +145,21 @@ public class BrooklynDslCommon {
                 if (mgmt==null) return null;
 
                 Map m = (Map) input;
-                if (!m.containsKey("type")) {
+                if 
(!(m.containsKey(BeanWithTypePlanTransformer.TYPE_SIMPLE_KEY) || 
m.containsKey(BeanWithTypePlanTransformer.TYPE_UNAMBIGUOUS_KEY))) {
                     // and map says a type
                     return null;
                 }
 
-                BrooklynClassLoadingContext loader = 
RegisteredTypes.getClassLoadingContext(mgmt, entity);
-                Object spec = DslUtils.transformSpecialFlags(mgmt, loader, 
dslParse.apply(mgmt, MutableMap.of("$brooklyn:entitySpec", input)));
-                if (spec instanceof Supplier) spec = ((Supplier)spec).get();
+                try {
+                    BrooklynClassLoadingContext loader = 
RegisteredTypes.getClassLoadingContext(mgmt, entity);
+                    Object spec = DslUtils.transformSpecialFlags(mgmt, loader, 
dslParse.apply(mgmt, MutableMap.of("$brooklyn:entitySpec", input)));
+                    if (spec instanceof Supplier) spec = ((Supplier) 
spec).get();
+
+                    return Maybe.of((T) spec);
 
-                return Maybe.of( (T) spec );
+                } catch (Exception e) {
+                    return Maybe.absent(e);
+                }
             }
         });
     }
diff --git 
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/WorkflowYamlTest.java
 
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/WorkflowYamlTest.java
index 68d0d6cff5..5a3840925c 100644
--- 
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/WorkflowYamlTest.java
+++ 
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/WorkflowYamlTest.java
@@ -76,6 +76,7 @@ import org.testng.annotations.Test;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.function.Predicate;
 
 import static 
org.apache.brooklyn.util.core.internal.ssh.ExecCmdAsserts.assertExecContains;
@@ -881,4 +882,39 @@ public class WorkflowYamlTest extends AbstractYamlTest {
         EntityAsserts.assertAttributeEqualsEventually(entity, 
Sensors.newIntegerSensor("x"), 7);
     }
 
+    @Test
+    public void testAddPolicyStep() throws Exception {
+        Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicEntity.class.getName());
+        Entity entity = Iterables.getOnlyElement(app.getChildren());
+        WorkflowExecutionContext x = WorkflowBasicTest.runWorkflow(entity, 
Strings.lines(
+                "steps:",
+                "  - type: add-policy",
+                "    blueprint:",
+                "      type: workflow-policy",
+                "      brooklyn.config:",
+                "        triggers: [ other_sensor ]",
+                "        steps: [ set-sensor integer x = 1 ]"
+        ), "add-policy");
+        x.getTask(false).get().getUnchecked();
+        EntityAsserts.assertAttributeEqualsEventually(entity, 
Sensors.newIntegerSensor("x"), 1);
+    }
+
+    @Test
+    public void testAddEntityStep() throws Exception {
+        Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicEntity.class.getName());
+        Entity entity = Iterables.getOnlyElement(app.getChildren());
+        WorkflowExecutionContext x = WorkflowBasicTest.runWorkflow(entity, 
Strings.lines(
+                "steps:",
+                "  - type: add-entity",
+                "    blueprint:",
+                "      type: " + BasicEntity.class.getName(),
+                "      name: Test"), "add-entity");
+        x.getTask(false).get().getUnchecked();
+        
Asserts.assertEquals(Iterables.getOnlyElement(entity.getChildren()).getDisplayName(),
 "Test");
+    }
+
 }
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
index f4e9619a93..42ac4e242b 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
@@ -206,6 +206,7 @@ public class EntityManagementUtils {
                 Exceptions.propagateIfFatal(e);
                 try {
                     Object yo = Iterables.getOnlyElement(Yamls.parseAll(yaml));
+                    // coercion does this at: 
org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon.registerSpecCoercionAdapter
                     spec = TypeCoercions.tryCoerce(yo, 
EntitySpec.class).orNull();
                 } catch (Exception e2) {
                     log.debug("Failed converting entity spec YAML as YAML, 
transformer error will throw, but also encountered: "+e2);
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
 
b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
index eaf88cb05f..4229a78152 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
@@ -200,7 +200,9 @@ public class RegisteredTypeLoadingContexts {
             if (best.getSpecType().isAssignableFrom(t.getSpecType())) { best = 
t; continue; }
         }
         if (best==null) {
-            log.warn("Unexpected spec supertype ("+specSuperType+"); treating 
as any "+BrooklynObject.class, new Throwable("Trace for unexpected spec 
supertype"));
+            if (!specSuperType.equals(AbstractBrooklynObjectSpec.class)) {
+                log.warn("Unexpected spec supertype (" + specSuperType + "); 
treating as any " + BrooklynObject.class, new Throwable("Trace for unexpected 
spec supertype"));
+            }
             return BrooklynObject.class;
         }
         // the spec is more specific, but we're not familiar with it here; 
return the best
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddPolicyWorkflowStep.java
 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddPolicyWorkflowStep.java
index 7ed8aa4fba..2855b0b414 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddPolicyWorkflowStep.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddPolicyWorkflowStep.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.core.workflow.steps.appmodel;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.google.common.collect.Iterables;
 import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.objs.BrooklynObject;
@@ -92,17 +93,26 @@ public class AddPolicyWorkflowStep extends 
WorkflowStepDefinition {
         EntityAdjunct inst = null;
         try {
             if (!(blueprint instanceof String)) blueprint = 
BeanWithTypeUtils.newYamlMapper(null, false, null, 
false).writeValueAsString(blueprint);
-            Object yo = Iterables.getOnlyElement(Yamls.parseAll((String) 
blueprint));
 
+            Object yo = Iterables.getOnlyElement(Yamls.parseAll((String) 
blueprint));
+            // coercion does this at: 
org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon.registerSpecCoercionAdapter
             Maybe<AbstractBrooklynObjectSpec> spec0 = 
TypeCoercions.tryCoerce(yo, AbstractBrooklynObjectSpec.class);
             if (spec0.isAbsent()) {
                 inst = TypeCoercions.tryCoerce(yo, EntityAdjunct.class)
-                        .get();  // prefer this exception
-//                        .orNull();  // or prefer original expression (line 
below)
-                if (inst==null) spec = spec0.get();  // throw original 
exception
+//                        .get();  // prefer this exception
+                        .orNull();  // or prefer original expression (line 
below)
+                if (inst == null) {
+                    // try camp spec instantiation; and prefer this error. 
this is the only way if loading a registered type of kind spec;
+                    // but it is stricter about requiring arguments in 
`brooklyn.config`
+                    spec = 
context.getManagementContext().getTypeRegistry().createSpecFromPlan(null, 
blueprint, null, AbstractBrooklynObjectSpec.class);
+
+                    // could prefer first error
+                    //spec = spec0.get();
+                }
             } else {
                 spec = spec0.get();
             }
+
         } catch (Exception e) {
             throw Exceptions.propagateAnnotated("Cannot make policy or adjunct 
from blueprint", e);
         }
@@ -123,7 +133,7 @@ public class AddPolicyWorkflowStep extends 
WorkflowStepDefinition {
             result = EntityAdjuncts.addAdjunct(entity, inst);
         }
 
-        return MutableMap.of(BrooklynObjectType.of(result).toCamelCase(), 
result);
+        return MutableMap.of(BrooklynObjectType.of(result).toCamelCase(), 
result, "result", result);
     }
 
     @Override protected Boolean isDefaultIdempotent() { return true; }
diff --git 
a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
 
b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
index 29ec876b19..464d97131e 100644
--- 
a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
+++ 
b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
@@ -60,7 +60,10 @@ public class Exceptions {
     private static boolean isBoringForMessage(Throwable t) {
         for (Class<? extends Throwable> type: 
ALWAYS_BORING_MESSAGE_THROWABLE_SUPERTYPES)
             if (type.isInstance(t)) return true;
-        if (Strings.isBlank(t.getMessage()) || (t.getCause()!=null && 
t.getMessage().equals(t.getCause().toString()))) {
+        if (Strings.isBlank(t.getMessage()) || (t.getCause()!=null && 
t.getCause()!=t &&
+                (t.getCause() instanceof PropagatedRuntimeException
+                        ? t.getMessage().equals(t.getCause().getMessage())
+                        : t.getMessage().equals(t.getCause().toString())))) {
             for (Class<? extends Throwable> type: 
BORING_IF_NO_MESSAGE_THROWABLE_SUPERTYPES)
                 if (type.isInstance(t)) return true;
         }

Reply via email to