fix deserialization to WrappedValue with nested DSL items
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslSerializationTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslSerializationTest.java
index a71b79c..88d4ce3 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslSerializationTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslSerializationTest.java
@@ -31,12 +31,9 @@
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.DslConfigSupplier;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
-import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
import org.apache.brooklyn.core.resolve.jackson.*;
import org.apache.brooklyn.core.resolve.jackson.BrooklynJacksonSerializationUtils.ConfigurableBeanDeserializerModifier;
-import org.apache.brooklyn.core.resolve.jackson.BrooklynRegisteredTypeJacksonSerializationTest.SampleBean;
import org.apache.brooklyn.core.resolve.jackson.WrappedValuesSerializationTest.ObjectWithWrappedValueString;
-import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.core.workflow.WorkflowBasicTest;
import org.apache.brooklyn.entity.stock.BasicStartable;
import org.apache.brooklyn.test.Asserts;
@@ -301,5 +298,8 @@
check.accept(r);
r = BeanWithTypeUtils.convertShallow(mgmt(), MutableMap.of("map", MutableMap.of("a", ws)), TypeToken.of(MapX.class), true, null, true);
check.accept(r);
+
+ // see deserializeNestedDslIntoWrappedValue test in DslYamlTest
}
+
}
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java
index f4e18d6..f54a3e4 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java
@@ -15,6 +15,7 @@
*/
package org.apache.brooklyn.camp.brooklyn.spi.dsl;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import org.apache.brooklyn.api.entity.Entity;
@@ -31,6 +32,8 @@
import org.apache.brooklyn.core.entity.Dumper;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.core.resolve.jackson.BeanWithTypeUtils;
+import org.apache.brooklyn.core.resolve.jackson.WrappedValue;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.core.test.entity.TestApplication;
import org.apache.brooklyn.core.test.entity.TestEntity;
@@ -41,9 +44,12 @@
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.text.StringEscapes;
import org.testng.annotations.Test;
+import java.util.Map;
import java.util.concurrent.ExecutionException;
import static org.testng.Assert.assertEquals;
@@ -989,4 +995,25 @@
return blockingValue;
}).build()).get();
}
+
+ @Test
+ public void deserializeNestedDslIntoWrappedValue() throws Exception {
+ final Entity app = createAndStartApplication(
+ "services:",
+ "- type: " + BasicApplication.class.getName());
+ Entities.submit(app, Tasks.create("test", () -> {
+ try {
+ String literal = StringEscapes.JavaStringEscapes.wrapJavaString("$brooklyn:literal(\"foo\")");
+ WrappedValue<?> ws = BeanWithTypeUtils.newMapper(mgmt(), true, null, true).readerFor(WrappedValue.class)
+ .readValue(literal);
+ Asserts.assertEquals(ws.get(), "foo");
+
+ String dslExpressionString = "{ \"key\": " + literal + " }";
+ WrappedValue<?> wm = BeanWithTypeUtils.newMapper(mgmt(), true, null, true).readerFor(WrappedValue.class).readValue(dslExpressionString);
+ Asserts.assertEquals(((Map) wm.get()).get("key"), "foo");
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ })).get();
+ }
}
diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerialization.java b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerialization.java
index 4fe02fd..4995abc 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerialization.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerialization.java
@@ -43,6 +43,7 @@
import org.apache.brooklyn.core.resolve.jackson.BrooklynJacksonSerializationUtils.JsonDeserializerForCommonBrooklynThings;
import org.apache.brooklyn.core.resolve.jackson.BrooklynRegisteredTypeJacksonSerialization.BrooklynRegisteredTypeAndClassNameIdResolver;
import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.javalang.Reflections;
import org.slf4j.Logger;
@@ -74,6 +75,9 @@
if (JsonDeserializerForCommonBrooklynThings.BROOKLYN_PARSE_DSL_FUNCTION!=null && mgmt!= null) {
if (looksLikeDsl(v)) {
v = JsonDeserializerForCommonBrooklynThings.BROOKLYN_PARSE_DSL_FUNCTION.apply(mgmt, v);
+ } else if (looksLikeNestedDsl(v)) {
+ Object vDeep = JsonDeserializerForCommonBrooklynThings.BROOKLYN_PARSE_DSL_FUNCTION.apply(mgmt, v);
+ v = Tasks.resolving(vDeep).as(Object.class).deep();
}
}
return WrappedValue.of(v);
@@ -91,6 +95,24 @@
return false;
}
+ private boolean looksLikeNestedDsl(Object v) {
+ if (v instanceof String) {
+ return ((String)v).contains("$brooklyn:");
+ }
+ if (v instanceof Map) {
+ for (Map.Entry entry: ((Map<?, ?>) v).entrySet()) {
+ if (looksLikeNestedDsl(entry.getKey())) return true;
+ if (looksLikeNestedDsl(entry.getValue())) return true;
+ }
+ }
+ if (v instanceof Iterable) {
+ for (Object entry: (Iterable)v) {
+ if (looksLikeNestedDsl(entry)) return true;
+ }
+ }
+ return false;
+ }
+
Object deserializeWithTypeUnwrapped(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
List<Exception> exceptions = MutableList.of();
diff --git a/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerializationTest.java b/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerializationTest.java
index b28fbb2..a796b43 100644
--- a/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerializationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerializationTest.java
@@ -148,10 +148,11 @@
@Test
public void testDeserializeUnrecognizedDsl() throws Exception {
- // tests in CAMP DslDeserializationTest for processing the DSL
String dslLiteralFoo = "$brooklyn:literal(\"foo\")";
ObjectWithWrappedValueString impl = deser(json("x: " + dslLiteralFoo), ObjectWithWrappedValueString.class);
Asserts.assertNotNull(impl.x);
+ // expect the DSL NOT to be recognized by this deserializer as it is not configured with a Brooklyn mgmt context
+ // see tests in CAMP DslSerializationTest for processing the DSL, and DslYamlTest for evaluating the DSL in an entity context
Asserts.assertEquals(impl.x.get(), dslLiteralFoo);
}
}