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
commit 2c2e905bee16922d7262cea8197b6a7ce33ef4ba Author: Alex Heneveld <[email protected]> AuthorDate: Mon Mar 20 12:00:30 2023 +0000 force the type when we are creating a bean with type; don't allow it to come back as a map --- .../camp/brooklyn/CustomTypeConfigYamlTest.java | 9 +++++--- .../resolve/jackson/AsPropertyIfAmbiguous.java | 8 +++++++- .../jackson/BeanWithTypePlanTransformer.java | 24 ++++++++++++++++++---- .../core/flags/BrooklynTypeNameResolution.java | 19 ++++++++--------- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CustomTypeConfigYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CustomTypeConfigYamlTest.java index 3cc01a30e8..b146b68bd7 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CustomTypeConfigYamlTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/CustomTypeConfigYamlTest.java @@ -18,10 +18,8 @@ */ package org.apache.brooklyn.camp.brooklyn; -import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.reflect.TypeToken; -import java.util.List; import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind; import org.apache.brooklyn.api.typereg.RegisteredType; @@ -35,13 +33,14 @@ import org.apache.brooklyn.core.typereg.BasicTypeImplementationPlan; import org.apache.brooklyn.core.typereg.JavaClassNameTypePlanTransformer; import org.apache.brooklyn.core.typereg.RegisteredTypes; import org.apache.brooklyn.test.Asserts; -import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.text.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.Test; +import java.util.List; + @Test public class CustomTypeConfigYamlTest extends AbstractYamlTest { private static final Logger log = LoggerFactory.getLogger(CustomTypeConfigYamlTest.class); @@ -288,6 +287,10 @@ public class CustomTypeConfigYamlTest extends AbstractYamlTest { " item:", " type: " + CustomTypeConfigYamlTest.TestingCustomType.class.getName(), " x: {}"); + // above should throw; if not, can investigate below +// Object tct = mgmt().getTypeRegistry().create(mgmt().getTypeRegistry().get("custom-type"), null, null); +// Asserts.assertInstanceOf(tct, TestingCustomType.class); +// Asserts.assertEquals( ((TestingCustomType)tct).x, "{}" /* ??? */); }, e -> { Asserts.expectedFailureContainsIgnoreCase(e, "bean", "custom-type", "cannot deserialize", "string", "\"x\""); return true; diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/AsPropertyIfAmbiguous.java b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/AsPropertyIfAmbiguous.java index 113b586960..94405ce681 100644 --- a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/AsPropertyIfAmbiguous.java +++ b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/AsPropertyIfAmbiguous.java @@ -39,6 +39,7 @@ import org.apache.brooklyn.api.objs.BrooklynObject; import org.apache.brooklyn.api.objs.BrooklynObjectType; import org.apache.brooklyn.api.sensor.Feed; import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry; +import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableSet; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.guava.Maybe; @@ -258,6 +259,7 @@ public class AsPropertyIfAmbiguous { tb = typeIdFindResult.tb; IOException preferredError = null; + Exception otherError = null; if (typeIdFindResult.type!=null) { boolean canTryWithoutType = !typeIdFindResult.isUnambiguous; try { @@ -279,6 +281,7 @@ public class AsPropertyIfAmbiguous { // if ambiguous then deserialize using default, below; but reset the parser first p = tb0.asParserOnFirstToken(); tb = tb0; + otherError = e; } } @@ -286,7 +289,10 @@ public class AsPropertyIfAmbiguous { return _deserializeTypedUsingDefaultImpl(p, ctxt, tb, _msgForMissingId); } catch (Exception e2) { if (preferredError!=null) throw preferredError; - throw e2; + if (otherError==null) throw e2; + throw Exceptions.propagate("Cannot deserialize instance of " + + ((_idResolver instanceof HasBaseType && ((HasBaseType) _idResolver).getBaseType()!=null) ? baseTypeName() : "any object") + + " declaring type '"+typeIdFindResult.type+"'", MutableList.of(otherError, e2)); } } diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BeanWithTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BeanWithTypePlanTransformer.java index b50e6dfc86..99d7e48c76 100644 --- a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BeanWithTypePlanTransformer.java +++ b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BeanWithTypePlanTransformer.java @@ -18,21 +18,22 @@ */ package org.apache.brooklyn.core.resolve.jackson; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.reflect.TypeToken; import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind; import org.apache.brooklyn.api.typereg.RegisteredType; import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext; import org.apache.brooklyn.core.catalog.internal.CatalogUtils; -import org.apache.brooklyn.core.mgmt.classloading.OsgiBrooklynClassLoadingContext; import org.apache.brooklyn.core.typereg.AbstractTypePlanTransformer; import org.apache.brooklyn.core.typereg.UnsupportedTypePlanException; +import org.apache.brooklyn.util.core.flags.BrooklynTypeNameResolution; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.text.Strings; import org.apache.brooklyn.util.yaml.Yamls; import java.util.Iterator; -import java.util.List; import java.util.Map; public class BeanWithTypePlanTransformer extends AbstractTypePlanTransformer { @@ -96,8 +97,23 @@ public class BeanWithTypePlanTransformer extends AbstractTypePlanTransformer { BrooklynClassLoadingContext loader = registeredTypeLoadingContext != null ? registeredTypeLoadingContext.getLoader() : null; loader = CatalogUtils.newClassLoadingContext(mgmt, registeredType, loader); - return BeanWithTypeUtils.newMapper(mgmt, true, loader, true).readValue( - BeanWithTypeUtils.newSimpleMapper().writeValueAsString(definition), Object.class); + String definitionMapSerializedAsString = BeanWithTypeUtils.newSimpleMapper().writeValueAsString(definition); + ObjectMapper mapper = BeanWithTypeUtils.newMapper(mgmt, true, loader, true); + Object result = mapper.readValue(definitionMapSerializedAsString, Object.class); + + Object typeS = definition.get("type"); + if (typeS instanceof String) { + // if size is 1, it's a weird thing like a ListExtended, so don't try to deserialize from an empty object + TypeToken<?> expectedType = new BrooklynTypeNameResolution.BrooklynTypeNameResolver("creating-bean-"+registeredType, mgmt, loader, true, true) + .getTypeToken((String) typeS); + if (!expectedType.getRawType().isInstance(result)) { + // we did not get the expected type; this should throw an error, though maybe it will work + definition.remove("type"); + definitionMapSerializedAsString = BeanWithTypeUtils.newSimpleMapper().writeValueAsString(definition); + result = mapper.readValue(definitionMapSerializedAsString, BrooklynJacksonType.asJavaType(mapper, expectedType)); + } + } + return result; } } diff --git a/core/src/main/java/org/apache/brooklyn/util/core/flags/BrooklynTypeNameResolution.java b/core/src/main/java/org/apache/brooklyn/util/core/flags/BrooklynTypeNameResolution.java index bd77e37e91..ee5568c444 100644 --- a/core/src/main/java/org/apache/brooklyn/util/core/flags/BrooklynTypeNameResolution.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/flags/BrooklynTypeNameResolution.java @@ -22,18 +22,10 @@ import com.google.common.annotations.Beta; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; import com.google.common.reflect.TypeToken; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.*; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; import org.apache.brooklyn.api.location.PortRange; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; -import org.apache.brooklyn.core.catalog.internal.CatalogUtils; import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext; -import org.apache.brooklyn.core.resolve.jackson.BrooklynJacksonSerializationUtils; import org.apache.brooklyn.core.resolve.jackson.BrooklynJacksonType; import org.apache.brooklyn.core.resolve.jackson.WrappedValue; import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts; @@ -42,7 +34,6 @@ import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.collections.MutableSet; import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.guava.TypeTokens; -import org.apache.brooklyn.util.javalang.ClassLoadingContext; import org.apache.brooklyn.util.text.Strings; import org.apache.brooklyn.util.time.Duration; import org.apache.brooklyn.util.time.Timestamp; @@ -52,6 +43,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; public class BrooklynTypeNameResolution { @@ -138,9 +135,9 @@ public class BrooklynTypeNameResolution { public BrooklynTypeNameResolver(String context, @Nullable BrooklynClassLoadingContext loader, boolean allowJavaType, boolean allowRegisteredTypes) { this(context, loader==null ? null : loader.getManagementContext(), loader, allowJavaType, allowRegisteredTypes); } - private BrooklynTypeNameResolver(String context, @Nullable ManagementContext mgmt, BrooklynClassLoadingContext loader, boolean allowJavaType, boolean allowRegisteredTypes) { + public BrooklynTypeNameResolver(String context, @Nullable ManagementContext mgmt, @Nullable BrooklynClassLoadingContext loader, boolean allowJavaType, boolean allowRegisteredTypes) { this.context = context; - this.mgmt = mgmt; + this.mgmt = mgmt!=null ? mgmt : loader!=null ? loader.getManagementContext() : null; this.loader = loader==null ? mgmt==null ? null : JavaBrooklynClassLoadingContext.create(mgmt) : loader; this.allowJavaType = allowJavaType; this.allowRegisteredTypes = allowRegisteredTypes;
