From 30f7c421dba2b00aac68ebe17b27db8c90fa6be2 Mon Sep 17 00:00:00 2001 From: Nikita Date: Thu, 29 Sep 2016 18:33:12 +0300 Subject: [PATCH] LiveObjectService can't detach content of List object #638 --- .../redisson/RedissonLiveObjectService.java | 32 ++++++++++++++- .../RedissonLiveObjectServiceTest.java | 41 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java b/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java index 0b80145fa..720ceb23e 100644 --- a/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java +++ b/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java @@ -17,7 +17,10 @@ package org.redisson; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentMap; import org.redisson.api.RLiveObject; @@ -26,16 +29,20 @@ import org.redisson.api.RObject; import org.redisson.api.RedissonClient; import org.redisson.api.annotation.REntity; import org.redisson.api.annotation.RId; +import org.redisson.client.codec.Codec; import org.redisson.liveobject.LiveObjectTemplate; import org.redisson.liveobject.core.AccessorInterceptor; import org.redisson.liveobject.core.LiveObjectInterceptor; import org.redisson.liveobject.misc.Introspectior; import org.redisson.codec.CodecProvider; import org.redisson.liveobject.provider.ResolverProvider; +import org.redisson.liveobject.resolver.NamingScheme; import org.redisson.liveobject.resolver.Resolver; +import org.redisson.misc.RedissonObjectFactory; import jodd.bean.BeanCopy; import jodd.bean.BeanUtil; +import jodd.util.ReflectUtil; import net.bytebuddy.ByteBuddy; import net.bytebuddy.description.field.FieldDescription; import net.bytebuddy.description.field.FieldList; @@ -150,13 +157,36 @@ public class RedissonLiveObjectService implements RLiveObjectService { } throw new IllegalStateException("This REntity already exists."); } + + private RMap getMap(Object proxied) { + return BeanUtil.declared.getProperty(proxied, "liveObjectLiveMap"); + } @Override + @SuppressWarnings("unchecked") public T detach(T attachedObject) { validateAttached(attachedObject); try { T detached = instantiateDetachedObject((Class) attachedObject.getClass().getSuperclass(), asLiveObject(attachedObject).getLiveObjectId()); BeanCopy.beans(attachedObject, detached).declared(false, true).copy(); + for (Entry obj : getMap(attachedObject).entrySet()) { + if (obj.getValue() instanceof RedissonList) { + List list = new ArrayList((List)obj.getValue()); + for (int i = 0; i < list.size(); i++) { + Object object = list.get(i); + if (isLiveObject(object)) { + Object detachedObject = detach(object); + list.set(i, detachedObject); + } + } + BeanUtil.declared.setProperty(detached, obj.getKey(), list); + } + if (isLiveObject(obj.getValue())) { + Object detachedObject = detach(obj.getValue()); + BeanUtil.declared.setProperty(detached, obj.getKey(), detachedObject); + } + } + return detached; } catch (Exception ex) { throw ex instanceof RuntimeException ? (RuntimeException) ex : new RuntimeException(ex); @@ -309,7 +339,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { throw new IllegalArgumentException("The object supplied is must be a RLiveObject"); } } - + private void registerClassInternal(Class entityClass) { DynamicType.Builder builder = new ByteBuddy() .subclass(entityClass); diff --git a/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java b/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java index bdecc52b8..70a0679f9 100644 --- a/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java +++ b/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java @@ -987,6 +987,47 @@ public class RedissonLiveObjectServiceTest extends BaseTest { } + @REntity + public static class ObjectWithList { + + @RId + private String id; + + private List objects; + + private SimpleObject so; + + public String getId() { + return id; + } + + public List getObjects() { + return objects; + } + + public void setSo(SimpleObject so) { + this.so = so; + } + + public SimpleObject getSo() { + return so; + } + + } + + @Test + public void testStoreInnerObject() { + ObjectWithList so = redisson.getLiveObjectService().create(ObjectWithList.class); + SimpleObject s = redisson.getLiveObjectService().create(SimpleObject.class); + so.setSo(s); + assertThat(s.getId()).isNotNull(); + so.getObjects().add(s); + + so = redisson.getLiveObjectService().detach(so); + assertThat(so.getSo().getId()).isEqualTo(s.getId()); + assertThat(so.getObjects().get(0).getId()).isEqualTo(so.getSo().getId()); + } + @Test public void testFieldWithoutIdSetter() { SimpleObject so = redisson.getLiveObjectService().create(SimpleObject.class);