From 75db5eca7dbf1e58e008d27f3fece8b4854ef5f4 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 28 Sep 2016 18:40:59 +0300 Subject: [PATCH] Fixed - LiveObjectService doesn't create objects mapped to Redisson objects in runtime #637 --- .../liveobject/core/AccessorInterceptor.java | 57 +++++++++++++------ .../RedissonLiveObjectServiceTest.java | 16 ++++++ 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/redisson/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java b/redisson/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java index d56efb3c1..ad50e7cfd 100644 --- a/redisson/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java +++ b/redisson/src/main/java/org/redisson/liveobject/core/AccessorInterceptor.java @@ -17,7 +17,6 @@ package org.redisson.liveobject.core; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.AbstractMap; import java.util.Collection; import java.util.Deque; import java.util.LinkedHashMap; @@ -42,18 +41,18 @@ import org.redisson.RedissonReference; import org.redisson.RedissonSet; import org.redisson.RedissonSortedSet; import org.redisson.api.RLiveObject; -import org.redisson.client.codec.Codec; import org.redisson.api.RMap; import org.redisson.api.RObject; import org.redisson.api.RedissonClient; import org.redisson.api.annotation.REntity; +import org.redisson.api.annotation.REntity.TransformationMode; import org.redisson.api.annotation.RId; import org.redisson.api.annotation.RObjectField; -import org.redisson.api.annotation.REntity.TransformationMode; -import org.redisson.liveobject.misc.Introspectior; -import org.redisson.misc.RedissonObjectFactory; +import org.redisson.client.codec.Codec; import org.redisson.codec.CodecProvider; +import org.redisson.liveobject.misc.Introspectior; import org.redisson.liveobject.resolver.NamingScheme; +import org.redisson.misc.RedissonObjectFactory; import io.netty.util.internal.PlatformDependent; import net.bytebuddy.implementation.bind.annotation.AllArguments; @@ -75,7 +74,7 @@ public class AccessorInterceptor { private final RedissonClient redisson; private final CodecProvider codecProvider; private final ConcurrentMap namingSchemeCache = PlatformDependent.newConcurrentHashMap(); - private static final LinkedHashMap> supportedClassMapping; + private static final LinkedHashMap, Class> supportedClassMapping; public AccessorInterceptor(RedissonClient redisson) { this.redisson = redisson; @@ -83,7 +82,7 @@ public class AccessorInterceptor { } static { - supportedClassMapping = new LinkedHashMap>(); + supportedClassMapping = new LinkedHashMap, Class>(); supportedClassMapping.put(SortedSet.class, RedissonSortedSet.class); supportedClassMapping.put(Set.class, RedissonSet.class); supportedClassMapping.put(ConcurrentMap.class, RedissonMap.class); @@ -106,22 +105,48 @@ public class AccessorInterceptor { ((RLiveObject) me).setLiveObjectId(args[0]); return null; } + String fieldName = getFieldName(method); + Class idFieldType = me.getClass().getSuperclass().getDeclaredField(fieldName).getType(); + if (isGetter(method, fieldName)) { Object result = liveMap.get(fieldName); + if (result == null) { + Class mappedClass = getMappedClass(idFieldType); + if (mappedClass != null) { + Codec fieldCodec = getFieldCodec(me.getClass().getSuperclass(), mappedClass, fieldName); + NamingScheme fieldNamingScheme = getFieldNamingScheme(me.getClass().getSuperclass(), fieldName, fieldCodec); + + RObject obj = RedissonObjectFactory + .createRObject(redisson, + mappedClass, + fieldNamingScheme.getFieldReferenceName(me.getClass().getSuperclass(), + ((RLiveObject) me).getLiveObjectId(), + mappedClass, + fieldName, + null), + fieldCodec); + + codecProvider.registerCodec((Class) fieldCodec.getClass(), obj, obj.getCodec()); + liveMap.fastPut(fieldName, + new RedissonReference(obj.getClass(), obj.getName(), obj.getCodec())); + + return obj; + } + } + return result instanceof RedissonReference ? RedissonObjectFactory.fromReference(redisson, (RedissonReference) result, method.getReturnType()) : result; } if (isSetter(method, fieldName)) { - Class idFieldType = me.getClass().getSuperclass().getDeclaredField(fieldName).getType(); if (args[0] instanceof RLiveObject) { Class rEntity = args[0].getClass().getSuperclass(); REntity anno = rEntity.getAnnotation(REntity.class); NamingScheme ns = anno.namingScheme() .getDeclaredConstructor(Codec.class) .newInstance(codecProvider.getCodec(anno, (Class) rEntity)); - liveMap.put(fieldName, new RedissonReference(rEntity, + liveMap.fastPut(fieldName, new RedissonReference(rEntity, ns.getName(rEntity, idFieldType, getREntityIdFieldName(args[0]), ((RLiveObject) args[0]).getLiveObjectId()))); return me; @@ -132,7 +157,7 @@ public class AccessorInterceptor { && TransformationMode.ANNOTATION_BASED .equals(me.getClass().getSuperclass() .getAnnotation(REntity.class).fieldTransformation())) { - Class mappedClass = getMappedClass(arg); + Class mappedClass = getMappedClass(arg.getClass()); if (mappedClass != null) { Codec fieldCodec = getFieldCodec(me.getClass().getSuperclass(), mappedClass, fieldName); NamingScheme fieldNamingScheme = getFieldNamingScheme(me.getClass().getSuperclass(), fieldName, fieldCodec); @@ -141,7 +166,7 @@ public class AccessorInterceptor { .createRObject(redisson, mappedClass, fieldNamingScheme.getFieldReferenceName(me.getClass().getSuperclass(), - idFieldType, + ((RLiveObject) me).getLiveObjectId(), mappedClass, fieldName, arg), @@ -160,11 +185,11 @@ public class AccessorInterceptor { RObject ar = (RObject) arg; Codec codec = ar.getCodec(); codecProvider.registerCodec((Class) codec.getClass(), ar, codec); - liveMap.put(fieldName, + liveMap.fastPut(fieldName, new RedissonReference(ar.getClass(), ar.getName(), codec)); return me; } - liveMap.put(fieldName, args[0]); + liveMap.fastPut(fieldName, args[0]); return me; } return superMethod.call(); @@ -222,9 +247,9 @@ public class AccessorInterceptor { .getName(); } - private static Class getMappedClass(Object obj) { - for (Entry> entrySet : supportedClassMapping.entrySet()) { - if (entrySet.getKey().isInstance(obj)) { + private static Class getMappedClass(Class cls) { + for (Entry, Class> entrySet : supportedClassMapping.entrySet()) { + if (entrySet.getKey().isAssignableFrom(cls)) { return entrySet.getValue(); } } diff --git a/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java b/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java index a029c1eca..bdecc52b8 100644 --- a/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java +++ b/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java @@ -1001,6 +1001,22 @@ public class RedissonLiveObjectServiceTest extends BaseTest { assertThat(so.getValue()).isEqualTo(10L); } + @Test + public void testCreateObjectsInRuntime() { + TestREntityWithMap so = redisson.getLiveObjectService().create(TestREntityWithMap.class); + so.getValue().put("1", "2"); + + so = redisson.getLiveObjectService().detach(so); + assertThat(so.getName()).isNotNull(); + assertThat(so.getValue()).containsKey("1"); + assertThat(so.getValue()).containsValue("2"); + + so = redisson.getLiveObjectService().get(TestREntityWithMap.class, so.getName()); + assertThat(so.getName()).isNotNull(); + assertThat(so.getValue()).containsKey("1"); + assertThat(so.getValue()).containsValue("2"); + } + @Test public void testFieldAccessor() { RLiveObjectService service = redisson.getLiveObjectService();