You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2021/08/14 04:20:00 UTC

[brooklyn-server] branch master updated (f72e7c2 -> 3aca989)

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

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


    from f72e7c2  Merge branch 'serializing-with-references'
     new 361d4ca  more object-reference deserialization tweaks
     new 3aca989  fix occasional race condition on teardown

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../core/mgmt/internal/LocalEntityManager.java     |  7 +++---
 .../core/resolve/jackson/BeanWithTypeUtils.java    | 27 ++++++++++++---------
 ...BrooklynRegisteredTypeJacksonSerialization.java |  5 ++--
 .../jackson/ObjectReferencingSerialization.java    | 28 ++++++++++++++++++----
 .../util/core/internal/TypeCoercionsTest.java      | 11 ++++++++-
 5 files changed, 56 insertions(+), 22 deletions(-)

[brooklyn-server] 01/02: more object-reference deserialization tweaks

Posted by he...@apache.org.
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 361d4cacaf6a9cf7fa90b659a400e1ed56c2dc4f
Author: Alex Heneveld <al...@cloudsoftcorp.com>
AuthorDate: Sat Aug 14 04:38:44 2021 +0100

    more object-reference deserialization tweaks
---
 .../core/resolve/jackson/BeanWithTypeUtils.java    | 27 ++++++++++++---------
 ...BrooklynRegisteredTypeJacksonSerialization.java |  5 ++--
 .../jackson/ObjectReferencingSerialization.java    | 28 ++++++++++++++++++----
 .../util/core/internal/TypeCoercionsTest.java      | 11 ++++++++-
 4 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BeanWithTypeUtils.java b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BeanWithTypeUtils.java
index 896d493..5cc11ef 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BeanWithTypeUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BeanWithTypeUtils.java
@@ -125,7 +125,17 @@ public class BeanWithTypeUtils {
      */
 
     public static <T> T convert(ManagementContext mgmt, Object mapOrListToSerializeThenDeserialize, TypeToken<T> type, boolean allowRegisteredTypes, BrooklynClassLoadingContext loader, boolean allowJavaTypes) throws JsonProcessingException {
-        // try with complex types are saved as objects rather than serialized
+        try {
+            return convertDeeply(mgmt, mapOrListToSerializeThenDeserialize, type, allowRegisteredTypes, loader, allowJavaTypes);
+
+        } catch (Exception e) {
+            return convertShallow(mgmt, mapOrListToSerializeThenDeserialize, type, allowRegisteredTypes, loader, allowJavaTypes);
+        }
+    }
+
+    @Beta
+    public static <T> T convertShallow(ManagementContext mgmt, Object mapOrListToSerializeThenDeserialize, TypeToken<T> type, boolean allowRegisteredTypes, BrooklynClassLoadingContext loader, boolean allowJavaTypes) throws JsonProcessingException {
+        // try with complex types are saved as objects rather than serialized, but won't work if special deserialization is wanted to apply to a map inside a complex type
         ObjectMapper mapper = YAMLMapper.builder().build();
         mapper = BeanWithTypeUtils.applyCommonMapperConfig(mapper, mgmt, allowRegisteredTypes, loader, allowJavaTypes);
         mapper = new ObjectReferencingSerialization().useAndApplytoMapper(mapper);
@@ -135,16 +145,11 @@ public class BeanWithTypeUtils {
     }
 
     @Beta
-    public static <T> T convertExtra(ManagementContext mgmt, Object mapOrListToSerializeThenDeserialize, TypeToken<T> type, boolean allowRegisteredTypes, BrooklynClassLoadingContext loader, boolean allowJavaTypes) throws JsonProcessingException {
-        try {
-            return convert(mgmt, mapOrListToSerializeThenDeserialize, type, allowRegisteredTypes, loader, allowJavaTypes);
-
-        } catch (Exception e) {
-            // try full serialization - but won't work if things being written cannot be deserialized
-            ObjectMapper m = newMapper(mgmt, allowRegisteredTypes, loader, allowJavaTypes);
-            String serialization = m.writeValueAsString(mapOrListToSerializeThenDeserialize);
-            return m.readValue(serialization, BrooklynJacksonType.asJavaType(m, type));
-        }
+    public static <T> T convertDeeply(ManagementContext mgmt, Object mapOrListToSerializeThenDeserialize, TypeToken<T> type, boolean allowRegisteredTypes, BrooklynClassLoadingContext loader, boolean allowJavaTypes) throws JsonProcessingException {
+        // try full serialization - but won't work if things being written cannot be deserialized, eg due to unknown type
+        ObjectMapper m = newMapper(mgmt, allowRegisteredTypes, loader, allowJavaTypes);
+        String serialization = m.writeValueAsString(mapOrListToSerializeThenDeserialize);
+        return m.readValue(serialization, BrooklynJacksonType.asJavaType(m, type));
     }
 
     public static <T> Maybe<T> tryConvertOrAbsentUsingContext(Maybe<Object> input, TypeToken<T> type) {
diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerialization.java b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerialization.java
index b7dbad4..5351716 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerialization.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerialization.java
@@ -228,10 +228,11 @@ public class BrooklynRegisteredTypeJacksonSerialization {
     public static ObjectMapper apply(ObjectMapper mapper, ManagementContext mgmt, boolean allowRegisteredTypes, BrooklynClassLoadingContext loader, boolean allowPojoJavaTypes) {
         // the type resolver is extended to recognise brooklyn registered type names
         // and return a subtype of jackson JavaType
-        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
-
         mapper.setDefaultTyping(new BrtTypeResolverBuilder(mgmt, allowRegisteredTypes, loader, allowPojoJavaTypes));
 
+//        // this is tempting but it breaks places where we rely on type: ... to tell us the type
+//        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
+
         SimpleModule module = new SimpleModule();
         if (allowRegisteredTypes) {
             module.setDeserializers(new RegisteredTypeDeserializers(mgmt));
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 28314a3..219e110 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
@@ -37,8 +37,10 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer;
 import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
+import com.google.common.reflect.TypeToken;
 import java.io.IOException;
 import java.io.StringReader;
+import java.lang.reflect.Type;
 import org.apache.brooklyn.core.resolve.jackson.BrooklynJacksonSerializationUtils.ConfigurableBeanDeserializerModifier;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.apache.brooklyn.util.text.Identifiers;
@@ -143,13 +145,29 @@ public class ObjectReferencingSerialization {
         @Override
         protected Object deserializeWrapper(JsonParser jp, DeserializationContext ctxt, BiFunctionThrowsIoException<JsonParser, DeserializationContext, Object> nestedDeserialize) throws IOException {
             String v = jp.getCurrentToken()== JsonToken.VALUE_STRING ? jp.getValueAsString() : null;
-            Class<?> expected = ctxt.getContextualType()==null ? null : ctxt.getContextualType().getRawClass();
-            if (expected==null) expected = Object.class;
-            if (v!=null && !String.class.equals(expected)) {
+            if (v!=null) {
+                Type expected = _valueType!=null ? _valueType : _valueClass;
+
+                // not sure if we ever need to look at contextual type
+                Type expected2 = ctxt.getContextualType()==null ? null : ctxt.getContextualType();
+                if (expected2!=null) {
+                    if (expected==null) {
+                        expected = expected2;
+                    } else {
+                        // we have two expectations
+                        LOG.debug("Object reference deserialization ambiguity, expected "+expected+" and "+expected2);
+                    }
+                }
+                if (expected==null) {
+                    expected = Object.class;
+                }
+
                 Object result = backingMap.get(v);
                 if (result!=null) {
-                    if (!expected.isInstance(result)) {
-                        return TypeCoercions.coerce(result, expected);
+                    // Because of how UntypedObjectDeserializer.deserializeWithType treats strings
+                    // we cannot trust string being expected (if we could, we could exclude backing map lookup!)
+                    if (!String.class.equals(expected)) {
+                        result = TypeCoercions.coerce(result, TypeToken.of(expected));
                     }
                     return result;
                 }
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java b/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java
index 1a81ae9..3216736 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java
@@ -19,6 +19,7 @@
 package org.apache.brooklyn.util.core.internal;
 
 import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.collections.MutableList;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
@@ -425,15 +426,23 @@ public class TypeCoercionsTest {
 
     public static class ClassWithMap {
         Map<String,Object> properties = MutableMap.of();
+        Map<String,List<MyClazz>> propsList = MutableMap.of();
     }
 
     @Test
     public void testObjectInMapCoercion() {
-        ClassWithMap r1 = TypeCoercions.coerce(MutableMap.of("properties", MutableMap.of("x", 1)), ClassWithMap.class);
+        ClassWithMap r1 =
+                TypeCoercions.coerce(MutableMap.of("properties", MutableMap.of("x", 1)), ClassWithMap.class);
         Assert.assertEquals(r1.properties.get("x"), 1);
 
         r1 = TypeCoercions.coerce(MutableMap.of("properties", MutableMap.of("x", new MyClazz())), ClassWithMap.class);
         Asserts.assertInstanceOf(r1.properties.get("x"), MyClazz.class);
+
+        r1 = TypeCoercions.coerce(MutableMap.of(
+                "properties", MutableMap.of("x", new MyClazz()),
+                "propsList", MutableMap.of("y", MutableList.of(new MyClazz()))
+                ), ClassWithMap.class);
+        Asserts.assertInstanceOf(((List)r1.propsList.get("y")).get(0), MyClazz.class);
     }
 
 }

[brooklyn-server] 02/02: fix occasional race condition on teardown

Posted by he...@apache.org.
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 3aca98993e029878efe770fbc06110820ecf68f5
Author: Alex Heneveld <al...@cloudsoftcorp.com>
AuthorDate: Sat Aug 14 05:19:44 2021 +0100

    fix occasional race condition on teardown
---
 .../org/apache/brooklyn/core/mgmt/internal/LocalEntityManager.java | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalEntityManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalEntityManager.java
index 8257c48..47936ac 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalEntityManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalEntityManager.java
@@ -845,8 +845,9 @@ public class LocalEntityManager implements EntityManagerInternal {
          * this is happening? Should abstractEntity.onManagementStopped or some such remove the entity
          * from its groups?
          */
-        
-        if (!getLastManagementTransitionMode(e.getId()).isReadOnly()) {
+
+        ManagementTransitionMode lastTM = getLastManagementTransitionMode(e.getId());
+        if (lastTM!=null && !lastTM.isReadOnly()) {
             e.clearParent();
             for (Group group : e.groups()) {
                 if (!Entities.isNoLongerManaged(group)) group.removeMember(e);
@@ -858,7 +859,7 @@ public class LocalEntityManager implements EntityManagerInternal {
                 }
             }
         } else {
-            log.debug("No relations being updated on unmanage of read only {}", e);
+            log.debug("No relations being updated on unmanage of read only {} (mode {})", e, lastTM);
         }
 
         unmanageOwnedLocations(e);