make more context for workflow step resolution

and better errors if cannot resolve
diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/ObjectReferencingSerialization.java b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/ObjectReferencingSerialization.java
index 9d3af1c..6ad6990 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/ObjectReferencingSerialization.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/ObjectReferencingSerialization.java
@@ -180,7 +180,10 @@
                         // but so long as this deserializer is preferred which it normally is, losing the alias reference is okay.
                         Maybe resultCoerced = ((Maybe) TypeCoercions.tryCoerce(result, TypeToken.of(expected)));
                         if (resultCoerced.isAbsent()) {
-                            // not uncommon when we are trying to deserialize in a few different ways, or if we are using a string deserializer because the json input is a string
+                            // not uncommon when we are trying to deserialize in a few different ways, or if we are using a string deserializer because the json input is a string;
+                            // however it can be useful, to explain why some things aren't coercing via BeanWithTypeUtils.convert.
+                            // caller can do 'tryCoerce' to explain.
+
 //                            if (LOG.isDebugEnabled()) LOG.debug("Reference to "+result+" when deserialization could not be coerced to expected type "+expected+"; proceeding but might cause errors");
                         }
                         return resultCoerced.or(result);
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExecutionContext.java b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExecutionContext.java
index a26febb..8cffdcb 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExecutionContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExecutionContext.java
@@ -42,7 +42,6 @@
 import org.apache.brooklyn.core.resolve.jackson.JsonPassThroughDeserializer;
 import org.apache.brooklyn.core.sensor.Sensors;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
-import org.apache.brooklyn.core.workflow.steps.flow.FailWorkflowStep.WorkflowFailException;
 import org.apache.brooklyn.core.workflow.store.WorkflowRetentionAndExpiration;
 import org.apache.brooklyn.core.workflow.store.WorkflowStatePersistenceViaSensors;
 import org.apache.brooklyn.core.workflow.utils.WorkflowRetentionParser;
@@ -391,9 +390,9 @@
         return parent;
     }
 
-    public static void validateSteps(ManagementContext mgmt, List<WorkflowStepDefinition> steps, boolean alreadyValidatedIndividualSteps) {
+    public static void validateSteps(WorkflowStepResolution workflowStepResolution, List<WorkflowStepDefinition> steps, boolean alreadyValidatedIndividualSteps) {
         if (!alreadyValidatedIndividualSteps) {
-            steps.forEach(w -> w.validateStep(mgmt, null));
+            steps.forEach(w -> w.validateStep(workflowStepResolution));
         }
 
         computeStepsWithExplicitIdById(steps);
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepDefinition.java b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepDefinition.java
index 3a5ab6b..e3f17c9 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepDefinition.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepDefinition.java
@@ -43,7 +43,6 @@
 import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
@@ -322,7 +321,7 @@
     /**
      * allows subclasses to throw exception early if required fields not set
      */
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
         validateReplayableAndIdempotent();
     }
 
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepResolution.java b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepResolution.java
index 358687a..cbcff72 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepResolution.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepResolution.java
@@ -39,6 +39,7 @@
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
@@ -107,7 +108,7 @@
                 throw Exceptions.propagateAnnotated("Error in definition of step "+(i+1)+" ("+steps.get(i)+")", e);
             }
         }
-        WorkflowExecutionContext.validateSteps(mgmt(), result, true);
+        WorkflowExecutionContext.validateSteps(this, result, true);
         return result;
     }
 
@@ -128,6 +129,8 @@
         return result;
     }
 
+    static boolean inCoercionErrorBlock = false;
+
     public WorkflowStepDefinition resolveStep(Object def) {
         if (def instanceof WorkflowStepDefinition) return (WorkflowStepDefinition) def;
 
@@ -200,9 +203,26 @@
         try {
             Object def0 = defM !=null ? defM : def;
 
-            // if it's unable to convert a complex type via the above, the original type will be returned; the above doesn't fail.
-            // this is checked below so it's not a serious error, but the reason for it might be obscured.
-            Callable<Object> converter = () -> BeanWithTypeUtils.convert(mgmt(), def0, TypeToken.of(WorkflowStepDefinition.class), true, loader, true);
+            Callable<Object> converter = () -> {
+                Object result = BeanWithTypeUtils.convert(mgmt(), def0, TypeToken.of(WorkflowStepDefinition.class), true, loader, true);
+                if (!(result instanceof WorkflowStepDefinition)) {
+                    // if it's unable to convert a complex type via the above, the original type may be returned,
+                    // in particular by ObjectReferencingSerialization; so the conversion doesn't report failure,
+                    // and the actual failure is masked by ObjectReferencingSerialization
+                    if (!inCoercionErrorBlock) {
+                        inCoercionErrorBlock = true;
+                        try {
+                            return TypeCoercions.tryCoerce(def0, WorkflowStepDefinition.class).get();
+                        } finally {
+                            inCoercionErrorBlock = false;
+                        }
+                    }
+                    // prefer above to give a better error -- but need to prevent recursion (NBD not thread safe, just won't always get best error)
+                    throw new IllegalArgumentException("Cannot convert "+def0+" to workflow step; either wrong step input or insufficient context");
+                }
+
+                return result;
+            };
             Entity entity = entity();
             if (entity==null) {
                 def = converter.call();
@@ -236,7 +256,7 @@
                 defW.onError = resolveSubSteps("error handling", onError);
             }
 
-            defW.validateStep(mgmt(), null);
+            defW.validateStep(this);
 
             return defW;
         } else {
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/CustomWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/CustomWorkflowStep.java
index a7c766f..ddfc6d9 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/CustomWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/CustomWorkflowStep.java
@@ -57,7 +57,6 @@
 import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -176,12 +175,12 @@
     protected Map<String,Object> reducing;
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
 
         if (steps instanceof List) {
             if (steps.isEmpty()) throw new IllegalArgumentException("Workflow `steps` must be supplied for a custom or nested workflow");
-            new WorkflowStepResolution(mgmt, null, workflow).resolveSteps(steps, null);
+            workflowStepResolution.resolveSteps(steps, null);
         } else if (steps!=null) throw new IllegalArgumentException("Workflow `steps` must be a list");
         else if (target!=null) throw new IllegalArgumentException("Workflow cannot take a `target` without `steps`");
     }
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddEntityWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddEntityWorkflowStep.java
index 4713391..667c164 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddEntityWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddEntityWorkflowStep.java
@@ -19,7 +19,6 @@
 package org.apache.brooklyn.core.workflow.steps.appmodel;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -37,25 +36,20 @@
 import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
 import org.apache.brooklyn.core.mgmt.internal.EntityManagerInternal;
 import org.apache.brooklyn.core.resolve.jackson.BeanWithTypeUtils;
-import org.apache.brooklyn.core.resolve.jackson.JsonPassThroughDeserializer;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
+import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
 import org.apache.brooklyn.core.workflow.steps.appmodel.DeployApplicationWorkflowStep.StartMode;
-import org.apache.brooklyn.core.workflow.steps.variables.SetVariableWorkflowStep;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.task.Tasks;
-import org.apache.brooklyn.util.core.text.TemplateProcessor;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Identifiers;
-import org.apache.brooklyn.util.text.StringEscapes;
 import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
 import java.util.List;
 import java.util.Map;
 
@@ -82,9 +76,9 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
-        validateStepBlueprint(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
+        validateStepBlueprint(workflowStepResolution);
     }
 
     @Override
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 d941d8c..f27c481 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,7 +21,6 @@
 import com.google.common.collect.Iterables;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.BrooklynObjectType;
 import org.apache.brooklyn.api.objs.EntityAdjunct;
@@ -29,7 +28,6 @@
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.entity.EntityAdjuncts;
 import org.apache.brooklyn.core.resolve.jackson.BeanWithTypeUtils;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
@@ -43,8 +41,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
-
 public class AddPolicyWorkflowStep extends WorkflowStepDefinition implements HasBlueprintWorkflowStep {
 
     private static final Logger LOG = LoggerFactory.getLogger(AddPolicyWorkflowStep.class);
@@ -65,9 +61,9 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
-        validateStepBlueprint(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
+        validateStepBlueprint(workflowStepResolution);
     }
 
     @Override
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ApplyInitializerWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ApplyInitializerWorkflowStep.java
index 08845ce..6ddc9ae 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ApplyInitializerWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ApplyInitializerWorkflowStep.java
@@ -22,11 +22,9 @@
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntityInitializer;
 import org.apache.brooklyn.api.entity.EntityLocal;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.resolve.jackson.BeanWithTypeUtils;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
@@ -36,8 +34,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
-
 public class ApplyInitializerWorkflowStep extends WorkflowStepDefinition implements HasBlueprintWorkflowStep {
 
     private static final Logger LOG = LoggerFactory.getLogger(ApplyInitializerWorkflowStep.class);
@@ -57,9 +53,9 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
-        validateStepBlueprint(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
+        validateStepBlueprint(workflowStepResolution);
     }
 
     @Override
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeleteEntityWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeleteEntityWorkflowStep.java
index f1e8250..4cfb401 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeleteEntityWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeleteEntityWorkflowStep.java
@@ -19,19 +19,15 @@
 package org.apache.brooklyn.core.workflow.steps.appmodel;
 
 import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
-
 public class DeleteEntityWorkflowStep extends WorkflowStepDefinition {
 
     private static final Logger LOG = LoggerFactory.getLogger(DeleteEntityWorkflowStep.class);
@@ -46,8 +42,8 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
 
         if (!getInput().containsKey(ENTITY.getName())) throw new IllegalArgumentException("Missing required argument: "+ENTITY.getName());
     }
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeletePolicyWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeletePolicyWorkflowStep.java
index d9eb89f..bb7addd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeletePolicyWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeletePolicyWorkflowStep.java
@@ -19,12 +19,10 @@
 package org.apache.brooklyn.core.workflow.steps.appmodel;
 
 import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.objs.EntityAdjunct;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.entity.EntityAdjuncts;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
@@ -32,8 +30,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
-
 public class DeletePolicyWorkflowStep extends WorkflowStepDefinition {
 
     private static final Logger LOG = LoggerFactory.getLogger(DeletePolicyWorkflowStep.class);
@@ -49,8 +45,8 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
 
         if (!getInput().containsKey(POLICY.getName())) throw new IllegalArgumentException("Missing required argument: "+POLICY.getName());
     }
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeployApplicationWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeployApplicationWorkflowStep.java
index 94ca80e..9ff9404 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeployApplicationWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeployApplicationWorkflowStep.java
@@ -19,19 +19,16 @@
 package org.apache.brooklyn.core.workflow.steps.appmodel;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.google.common.base.Optional;
 import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
 import org.apache.brooklyn.core.resolve.jackson.BeanWithTypeUtils;
-import org.apache.brooklyn.core.resolve.jackson.JsonPassThroughDeserializer;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
+import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.text.Identifiers;
@@ -40,8 +37,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
-
 public class DeployApplicationWorkflowStep extends WorkflowStepDefinition implements HasBlueprintWorkflowStep {
 
     private static final Logger LOG = LoggerFactory.getLogger(DeployApplicationWorkflowStep.class);
@@ -69,9 +64,9 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
-        validateStepBlueprint(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
+        validateStepBlueprint(workflowStepResolution);
     }
 
     @Override
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/HasBlueprintWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/HasBlueprintWorkflowStep.java
index 4b141d5..981e852 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/HasBlueprintWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/HasBlueprintWorkflowStep.java
@@ -25,6 +25,7 @@
 import org.apache.brooklyn.core.resolve.jackson.JsonPassThroughDeserializer;
 import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
+import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
 import org.apache.brooklyn.core.workflow.steps.variables.SetVariableWorkflowStep;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.text.TemplateProcessor;
@@ -47,7 +48,7 @@
     Map<String, Object> getInput();
     Logger logger();
 
-    default void validateStepBlueprint(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
+    default void validateStepBlueprint(WorkflowStepResolution workflowStepResolution) {
         boolean hasBlueprint = getInput().containsKey(BLUEPRINT.getName());
         boolean hasType = getInput().containsKey(TYPE.getName());
         if (!hasBlueprint && !hasType) throw new IllegalArgumentException("A '"+BLUEPRINT.getName()+"' must be defined or a type supplied");
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/InvokeEffectorWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/InvokeEffectorWorkflowStep.java
index 25f1901..35fef83 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/InvokeEffectorWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/InvokeEffectorWorkflowStep.java
@@ -21,13 +21,11 @@
 import java.util.List;
 import java.util.Map;
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.google.common.collect.Iterables;
 import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.TaskAdaptable;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
@@ -41,7 +39,6 @@
 import org.apache.brooklyn.core.workflow.utils.ExpressionParser;
 import org.apache.brooklyn.core.workflow.utils.ExpressionParserImpl;
 import org.apache.brooklyn.core.workflow.utils.ExpressionParserImpl.CharactersCollectingParseMode;
-import org.apache.brooklyn.core.workflow.utils.ExpressionParserImpl.CommonParseMode;
 import org.apache.brooklyn.core.workflow.utils.ExpressionParserImpl.ParseNode;
 import org.apache.brooklyn.core.workflow.utils.ExpressionParserImpl.ParseNodeOrValue;
 import org.apache.brooklyn.core.workflow.utils.ExpressionParserImpl.ParseValue;
@@ -164,8 +161,8 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
 
         if (!getInput().containsKey(EFFECTOR.getName())) throw new IllegalArgumentException("Missing required input: "+EFFECTOR.getName());
     }
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ReparentEntityWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ReparentEntityWorkflowStep.java
index d06bb91..df7c372 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ReparentEntityWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ReparentEntityWorkflowStep.java
@@ -19,17 +19,14 @@
 package org.apache.brooklyn.core.workflow.steps.appmodel;
 
 import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
 import java.util.Objects;
 
 public class ReparentEntityWorkflowStep extends WorkflowStepDefinition {
@@ -47,8 +44,8 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
 
         if (!getInput().containsKey(CHILD.getName())) throw new IllegalArgumentException("Missing required argument: "+CHILD.getName());
         if (!getInput().containsKey(PARENT.getName())) throw new IllegalArgumentException("Missing required argument: "+PARENT.getName());
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/UpdateChildrenWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/UpdateChildrenWorkflowStep.java
index 0db1cf6..df2cd13 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/UpdateChildrenWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/UpdateChildrenWorkflowStep.java
@@ -46,7 +46,6 @@
 import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import java.util.List;
 import java.util.Map;
 import java.util.function.BiFunction;
@@ -143,9 +142,9 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
-        validateStepBlueprint(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
+        validateStepBlueprint(workflowStepResolution);
     }
 
     @Override
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/GotoWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/GotoWorkflowStep.java
index 3d22f39..4d8d807 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/GotoWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/GotoWorkflowStep.java
@@ -18,16 +18,10 @@
  */
 package org.apache.brooklyn.core.workflow.steps.flow;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowExpressionResolution;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
-
-import javax.annotation.Nullable;
+import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
 
 public class GotoWorkflowStep extends WorkflowStepDefinition {
 
@@ -42,8 +36,8 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
         if (next==null) throw new IllegalStateException("next is required for goto step");
     }
 
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/RetryWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/RetryWorkflowStep.java
index e355747..07a6353 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/RetryWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/RetryWorkflowStep.java
@@ -20,7 +20,6 @@
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.google.common.reflect.TypeToken;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.workflow.*;
@@ -37,7 +36,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
 import java.time.Instant;
 import java.util.*;
 import java.util.concurrent.TimeoutException;
@@ -214,8 +212,8 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
 
         TypeCoercions.coerce(input.get(REPLAY.getName()), REPLAY.getTypeToken());
         TypeCoercions.coerce(input.get(LIMIT.getName()), LIMIT.getTypeToken());
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/SwitchWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/SwitchWorkflowStep.java
index d1da619..42598bf 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/SwitchWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/SwitchWorkflowStep.java
@@ -19,7 +19,6 @@
 package org.apache.brooklyn.core.workflow.steps.flow;
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
@@ -35,7 +34,6 @@
 import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import java.util.List;
 import java.util.function.Function;
 
@@ -57,10 +55,10 @@
     List<Object> cases;
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
         if (cases==null) throw new IllegalStateException("No cases defined for "+Strings.firstNonBlank(getName(), "switch"));
-        List<WorkflowStepDefinition> stepsResolved = new WorkflowStepResolution(mgmt, null, workflow).resolveSubSteps(Strings.firstNonBlank(getName(), "switch"), cases);
+        List<WorkflowStepDefinition> stepsResolved = workflowStepResolution.resolveSubSteps(Strings.firstNonBlank(getName(), "switch"), cases);
         if (stepsResolved.size()>1) {
             for (int i = 0; i < stepsResolved.size()-1; i++) {
                 if (stepsResolved.get(i).getConditionRaw() == null) {
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/LoadWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/LoadWorkflowStep.java
index da68001..1ee67a6 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/LoadWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/LoadWorkflowStep.java
@@ -19,13 +19,12 @@
 package org.apache.brooklyn.core.workflow.steps.variables;
 
 import com.google.common.reflect.TypeToken;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowExpressionResolution;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
+import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.core.text.TemplateProcessor;
 import org.apache.brooklyn.util.text.ByteSizeStrings;
@@ -33,7 +32,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
 import java.nio.charset.Charset;
 
 public class LoadWorkflowStep extends WorkflowStepDefinition {
@@ -56,8 +54,8 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
 
         if (!input.containsKey(VARIABLE.getName())) {
             throw new IllegalArgumentException("Variable name is required");
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/SetVariableWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/SetVariableWorkflowStep.java
index 508d885..06ef869 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/SetVariableWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/SetVariableWorkflowStep.java
@@ -20,13 +20,12 @@
 
 import com.google.common.reflect.TypeToken;
 import freemarker.core.ParseException;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowExpressionResolution;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
+import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
 import org.apache.brooklyn.core.workflow.utils.WorkflowSettingItemsUtils;
 import org.apache.brooklyn.util.collections.*;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
@@ -43,7 +42,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nullable;
 import java.time.Instant;
 import java.util.*;
 import java.util.function.BiFunction;
@@ -83,8 +81,8 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
 
         if (input.get(VARIABLE.getName())==null) {
             throw new IllegalArgumentException("Variable name is required");
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/TransformVariableWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/TransformVariableWorkflowStep.java
index 09907ff..e46261e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/TransformVariableWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/TransformVariableWorkflowStep.java
@@ -26,21 +26,19 @@
 import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
-import javax.annotation.Nullable;
 
 import com.google.common.collect.Iterables;
 import com.google.common.reflect.TypeToken;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
-import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowExpressionResolution;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
+import org.apache.brooklyn.core.workflow.WorkflowStepResolution;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
@@ -94,8 +92,8 @@
     }
 
     @Override
-    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
-        super.validateStep(mgmt, workflow);
+    public void validateStep(WorkflowStepResolution workflowStepResolution) {
+        super.validateStep(workflowStepResolution);
         if (!input.containsKey(TRANSFORM.getName())) {
             throw new IllegalArgumentException("Transform is required");
         }
diff --git a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java
index 48d037e..6c2ac33 100644
--- a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java
+++ b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java
@@ -302,7 +302,7 @@
 
         // Expect app to be running
         URI appUri = response.getLocation();
-        waitForApplicationToBeRunning(response.getLocation());
+        waitForApplicationToBeRunning(response.getLocation());  // observed to fail here, app ERROR, 2024-02
         assertEquals(client().path(appUri).get(ApplicationSummary.class).getSpec().getName(), "simple-app-yaml");
 
         Response response2 = client().path(appUri.getPath())
@@ -721,7 +721,7 @@
         log.info("LOCATIONS: " + result);
         Assert.assertEquals(result.size(), 1);
         Map details = (Map) result.values().iterator().next();
-        assertEquals(details.get("leafEntityCount"), 2);
+        assertEquals(details.get("leafEntityCount"), 2);  // observed to fail here once, 2024-02, size 1
     }