diff --git a/README.md b/README.md index 6b639e20c..e393e6243 100644 --- a/README.md +++ b/README.md @@ -59,10 +59,10 @@ Features * Thread-safe implementation * All commands executes in an atomic way * Lua scripting -* [Spring cache](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html) integration +* [Spring cache](https://github.com/mrniko/redisson/wiki/10.-additional-features/#104-spring-cache-integration) integration * Supports [Reactive Streams](http://www.reactive-streams.org) * Supports [Redis pipelining](http://redis.io/topics/pipelining) (command batches) -* Supports [Remote services](https://github.com/mrniko/redisson/wiki/6.-distributed-objects#69-remote-service) +* Supports [Remote services](https://github.com/mrniko/redisson/wiki/9.-distributed-services/#91-remote-service) * Supports Android platform * Supports auto-reconnect * Supports failed to send command auto-retry diff --git a/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java b/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java index d459a9b07..3738c140d 100644 --- a/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java +++ b/redisson/src/main/java/org/redisson/RedissonLiveObjectService.java @@ -82,7 +82,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { return asLiveObject(proxied).isExists() ? null : proxied; } catch (Exception ex) { unregisterClass(entityClass); - throw new RuntimeException(ex); + throw ex instanceof RuntimeException ? (RuntimeException) ex : new RuntimeException(ex); } } @@ -93,7 +93,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { return asLiveObject(proxied).isExists() ? proxied : null; } catch (Exception ex) { unregisterClass(entityClass); - throw new RuntimeException(ex); + throw ex instanceof RuntimeException ? (RuntimeException) ex : new RuntimeException(ex); } } @@ -103,7 +103,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { return instantiateLiveObject(getProxyClass(entityClass), id); } catch (Exception ex) { unregisterClass(entityClass); - throw new RuntimeException(ex); + throw ex instanceof RuntimeException ? (RuntimeException) ex : new RuntimeException(ex); } } @@ -118,7 +118,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { getRIdFieldName(detachedObject.getClass()))); } catch (Exception ex) { unregisterClass(entityClass); - throw new RuntimeException(ex); + throw ex instanceof RuntimeException ? (RuntimeException) ex : new RuntimeException(ex); } } @@ -147,7 +147,7 @@ public class RedissonLiveObjectService implements RLiveObjectService { BeanCopy.beans(attachedObject, detached).declared(false, true).copy(); return detached; } catch (Exception ex) { - throw new RuntimeException(ex); + throw ex instanceof RuntimeException ? (RuntimeException) ex : new RuntimeException(ex); } } @@ -210,6 +210,9 @@ public class RedissonLiveObjectService implements RLiveObjectService { } private T instantiateLiveObject(Class proxyClass, K id) throws Exception { + if (id == null) { + throw new IllegalStateException("Non-null value is required for the field with RId annotation."); + } T instance = instantiate(proxyClass, id); asLiveObject(instance).setLiveObjectId(id); return instance; diff --git a/redisson/src/main/java/org/redisson/api/RLiveObjectService.java b/redisson/src/main/java/org/redisson/api/RLiveObjectService.java index 329956837..4f0fc1ece 100644 --- a/redisson/src/main/java/org/redisson/api/RLiveObjectService.java +++ b/redisson/src/main/java/org/redisson/api/RLiveObjectService.java @@ -197,7 +197,7 @@ public interface RLiveObjectService { /** * Pre register the class with the service, registering all the classes on * startup can speed up the instance creation. This is NOT mandatory - * since the class will also be registered lazyly when it first is used. + * since the class will also be registered lazily when it is first used. * * All classed registered with the service is stored in a class cache. * diff --git a/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java b/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java index dbaffaae0..fe10dad50 100644 --- a/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java +++ b/redisson/src/test/java/org/redisson/RedissonLiveObjectServiceTest.java @@ -327,7 +327,7 @@ public class RedissonLiveObjectServiceTest extends BaseTest { s.getOrCreate(TestREntityIdNested.class, t1); fail("Should not be here"); } catch (Exception e) { - assertEquals("Field with RId annotation cannot be a type of which class is annotated with REntity.", e.getCause().getMessage()); + assertEquals("Field with RId annotation cannot be a type of which class is annotated with REntity.", e.getMessage()); } } @@ -487,14 +487,14 @@ public class RedissonLiveObjectServiceTest extends BaseTest { service.getOrCreate(TestClass.class, new int[]{1, 2, 3, 4, 5}); fail("Should not be here"); } catch (Exception e) { - assertEquals("RId value cannot be an array.", e.getCause().getMessage()); + assertEquals("RId value cannot be an array.", e.getMessage()); } try { service.getOrCreate(TestClass.class, new byte[]{1, 2, 3, 4, 5}); fail("Should not be here"); } catch (Exception e) { - assertEquals("RId value cannot be an array.", e.getCause().getMessage()); + assertEquals("RId value cannot be an array.", e.getMessage()); } } @@ -659,7 +659,7 @@ public class RedissonLiveObjectServiceTest extends BaseTest { service.delete(TestClass.class, new ObjectId(100)); assertFalse(service.isExists(persisted)); } - + @REntity public static class TestClassID1 { @@ -673,9 +673,9 @@ public class RedissonLiveObjectServiceTest extends BaseTest { public Long getName() { return name; } - + } - + @REntity public static class TestClassID2 { @@ -689,9 +689,9 @@ public class RedissonLiveObjectServiceTest extends BaseTest { public Long getName() { return name; } - + } - + @Test public void testCreate() { RLiveObjectService service = redisson.getLiveObjectService(); @@ -703,64 +703,64 @@ public class RedissonLiveObjectServiceTest extends BaseTest { TestClassID2 tc2 = service.create(TestClassID2.class); assertEquals(new Long(1), tc2.getName()); } - + @Test public void testTransformation() { RLiveObjectService service = redisson.getLiveObjectService(); TestClass ts = service.create(TestClass.class); - + HashMap m = new HashMap(); ts.setContent(m); assertFalse(HashMap.class.isAssignableFrom(ts.getContent().getClass())); assertTrue(RMap.class.isAssignableFrom(ts.getContent().getClass())); - + HashSet s = new HashSet(); ts.setContent(s); assertFalse(HashSet.class.isAssignableFrom(ts.getContent().getClass())); assertTrue(RSet.class.isAssignableFrom(ts.getContent().getClass())); - + BitSet bs = new BitSet(); ts.setContent(bs); assertFalse(BitSet.class.isAssignableFrom(ts.getContent().getClass())); assertTrue(RBitSet.class.isAssignableFrom(ts.getContent().getClass())); - + TreeSet ss = new TreeSet(); ts.setContent(ss); assertFalse(TreeSet.class.isAssignableFrom(ts.getContent().getClass())); assertTrue(RSortedSet.class.isAssignableFrom(ts.getContent().getClass())); - + ArrayList al = new ArrayList(); ts.setContent(al); assertFalse(ArrayList.class.isAssignableFrom(ts.getContent().getClass())); assertTrue(RList.class.isAssignableFrom(ts.getContent().getClass())); - + ConcurrentHashMap chm = new ConcurrentHashMap(); ts.setContent(chm); assertFalse(ConcurrentHashMap.class.isAssignableFrom(ts.getContent().getClass())); assertTrue(RMap.class.isAssignableFrom(ts.getContent().getClass())); - + ArrayBlockingQueue abq = new ArrayBlockingQueue(10); ts.setContent(abq); assertFalse(ArrayBlockingQueue.class.isAssignableFrom(ts.getContent().getClass())); assertTrue(RBlockingQueue.class.isAssignableFrom(ts.getContent().getClass())); - + ConcurrentLinkedQueue clq = new ConcurrentLinkedQueue(); ts.setContent(clq); assertFalse(ConcurrentLinkedQueue.class.isAssignableFrom(ts.getContent().getClass())); assertTrue(RQueue.class.isAssignableFrom(ts.getContent().getClass())); - + LinkedBlockingDeque lbdq = new LinkedBlockingDeque(); ts.setContent(lbdq); assertFalse(LinkedBlockingDeque.class.isAssignableFrom(ts.getContent().getClass())); assertTrue(RBlockingDeque.class.isAssignableFrom(ts.getContent().getClass())); - + LinkedList ll = new LinkedList(); ts.setContent(ll); assertFalse(LinkedList.class.isAssignableFrom(ts.getContent().getClass())); assertTrue(RDeque.class.isAssignableFrom(ts.getContent().getClass())); - + } - + @REntity(fieldTransformation = REntity.TransformationMode.IMPLEMENTATION_BASED) public static class TestClassNoTransformation { @@ -831,58 +831,105 @@ public class RedissonLiveObjectServiceTest extends BaseTest { public void testNoTransformation() { RLiveObjectService service = redisson.getLiveObjectService(); TestClassNoTransformation ts = service.create(TestClassNoTransformation.class); - + HashMap m = new HashMap(); ts.setContent(m); assertTrue(HashMap.class.isAssignableFrom(ts.getContent().getClass())); assertFalse(RMap.class.isAssignableFrom(ts.getContent().getClass())); - + HashSet s = new HashSet(); ts.setContent(s); assertTrue(HashSet.class.isAssignableFrom(ts.getContent().getClass())); assertFalse(RSet.class.isAssignableFrom(ts.getContent().getClass())); - + BitSet bs = new BitSet(); ts.setContent(bs); assertTrue(BitSet.class.isAssignableFrom(ts.getContent().getClass())); assertFalse(RBitSet.class.isAssignableFrom(ts.getContent().getClass())); - + TreeSet ss = new TreeSet(); ts.setContent(ss); assertTrue(TreeSet.class.isAssignableFrom(ts.getContent().getClass())); assertFalse(RSortedSet.class.isAssignableFrom(ts.getContent().getClass())); - + ArrayList al = new ArrayList(); ts.setContent(al); assertTrue(ArrayList.class.isAssignableFrom(ts.getContent().getClass())); assertFalse(RList.class.isAssignableFrom(ts.getContent().getClass())); - + ConcurrentHashMap chm = new ConcurrentHashMap(); ts.setContent(chm); assertTrue(ConcurrentHashMap.class.isAssignableFrom(ts.getContent().getClass())); assertFalse(RMap.class.isAssignableFrom(ts.getContent().getClass())); - + ArrayBlockingQueue abq = new ArrayBlockingQueue(10); abq.add("111"); ts.setContent(abq); assertTrue(ArrayBlockingQueue.class.isAssignableFrom(ts.getContent().getClass())); assertFalse(RBlockingQueue.class.isAssignableFrom(ts.getContent().getClass())); - + ConcurrentLinkedQueue clq = new ConcurrentLinkedQueue(); ts.setContent(clq); assertTrue(ConcurrentLinkedQueue.class.isAssignableFrom(ts.getContent().getClass())); assertFalse(RQueue.class.isAssignableFrom(ts.getContent().getClass())); - + LinkedBlockingDeque lbdq = new LinkedBlockingDeque(); ts.setContent(lbdq); assertTrue(LinkedBlockingDeque.class.isAssignableFrom(ts.getContent().getClass())); assertFalse(RBlockingDeque.class.isAssignableFrom(ts.getContent().getClass())); - + LinkedList ll = new LinkedList(); ts.setContent(ll); assertTrue(LinkedList.class.isAssignableFrom(ts.getContent().getClass())); assertFalse(RDeque.class.isAssignableFrom(ts.getContent().getClass())); - + + } + + @REntity + public static class MyObject implements Serializable { + + @RId(generator = DistributedAtomicLongIdGenerator.class) + private Long id; + + private Long myId; + private String name; + + public MyObject() { + } + + public MyObject(Long myId) { + super(); + this.myId = myId; + } + + public Long getMyId() { + return myId; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + @Test + public void test() { + RLiveObjectService service = redisson.getLiveObjectService(); + + MyObject object = new MyObject(20L); + try { + service.attach(object); + } catch (Exception e) { + assertEquals("Non-null value is required for the field with RId annotation.", e.getMessage()); + } } - + }