RedissonAttachedLiveObjectService enhancement & author update

RedissonAttachedLiveObjectService now supports objects with different
codecs.

updated author tag on files created by me to match my github profile
pull/527/head
jackygurui 9 years ago
parent 6f028eb24b
commit 04ed064346

@ -26,6 +26,7 @@ env:
- REDIS_VERSION=3.2.0 REDISSON_TEST=org.redisson.RedissonAtomicDoubleTest
- REDIS_VERSION=3.2.0 REDISSON_TEST=org.redisson.RedissonAtomicLongReactiveTest
- REDIS_VERSION=3.2.0 REDISSON_TEST=org.redisson.RedissonAtomicLongTest
- REDIS_VERSION=3.2.0 REDISSON_TEST=org.redisson.RedissonAttachedLiveObjectServiceTest
- REDIS_VERSION=3.2.0 REDISSON_TEST=org.redisson.RedissonBatchTest
- REDIS_VERSION=3.2.0 REDISSON_TEST=org.redisson.RedissonBitSetReactiveTest
- REDIS_VERSION=3.2.0 REDISSON_TEST=org.redisson.RedissonBitSetTest
@ -88,6 +89,7 @@ env:
- REDIS_VERSION=3.0.7 REDISSON_TEST=org.redisson.RedissonAtomicDoubleTest
- REDIS_VERSION=3.0.7 REDISSON_TEST=org.redisson.RedissonAtomicLongReactiveTest
- REDIS_VERSION=3.0.7 REDISSON_TEST=org.redisson.RedissonAtomicLongTest
- REDIS_VERSION=3.0.7 REDISSON_TEST=org.redisson.RedissonAttachedLiveObjectServiceTest
- REDIS_VERSION=3.0.7 REDISSON_TEST=org.redisson.RedissonBatchTest
- REDIS_VERSION=3.0.7 REDISSON_TEST=org.redisson.RedissonBitSetReactiveTest
- REDIS_VERSION=3.0.7 REDISSON_TEST=org.redisson.RedissonBitSetTest
@ -149,6 +151,7 @@ env:
- REDIS_VERSION=2.8.24 REDISSON_TEST=org.redisson.RedissonAtomicDoubleTest
- REDIS_VERSION=2.8.24 REDISSON_TEST=org.redisson.RedissonAtomicLongReactiveTest
- REDIS_VERSION=2.8.24 REDISSON_TEST=org.redisson.RedissonAtomicLongTest
- REDIS_VERSION=2.8.24 REDISSON_TEST=org.redisson.RedissonAttachedLiveObjectServiceTest
- REDIS_VERSION=2.8.24 REDISSON_TEST=org.redisson.RedissonBatchTest
- REDIS_VERSION=2.8.24 REDISSON_TEST=org.redisson.RedissonBitSetReactiveTest
- REDIS_VERSION=2.8.24 REDISSON_TEST=org.redisson.RedissonBitSetTest

@ -73,6 +73,9 @@ import org.redisson.core.RSetMultimap;
import org.redisson.core.RSetMultimapCache;
import org.redisson.core.RSortedSet;
import org.redisson.core.RTopic;
import org.redisson.liveobject.CodecProvider;
import org.redisson.liveobject.DefaultCodecProvider;
import org.redisson.liveobject.RAttachedLiveObjectService;
import io.netty.util.concurrent.Future;
import io.netty.util.internal.PlatformDependent;
@ -95,7 +98,7 @@ public class Redisson implements RedissonClient {
= PlatformDependent.<Class, Class>newConcurrentHashMap();
private final Map<Class, Class> liveObjectProxyCache
= PlatformDependent.<Class, Class>newConcurrentHashMap();
private final CodecProvider liveObjectDefaultCodecProvider = new DefaultCodecProvider();
private final Config config;
private final UUID id = UUID.randomUUID();
@ -540,8 +543,13 @@ public class Redisson implements RedissonClient {
}
@Override
public RedissonAttachedLiveObjectService getAttachedLiveObjectService() {
return new RedissonAttachedLiveObjectService(this, commandExecutor, liveObjectClassCache, liveObjectProxyCache);
public RAttachedLiveObjectService getAttachedLiveObjectService() {
return new RedissonAttachedLiveObjectService(this, liveObjectClassCache, liveObjectProxyCache, liveObjectDefaultCodecProvider);
}
@Override
public RAttachedLiveObjectService getAttachedLiveObjectService(CodecProvider ProviderCodec) {
return new RedissonAttachedLiveObjectService(this, liveObjectClassCache, liveObjectProxyCache, new DefaultCodecProvider());
}
@Override

@ -1,6 +1,5 @@
package org.redisson;
import io.netty.util.internal.PlatformDependent;
import java.util.Map;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.field.FieldDescription;
@ -8,8 +7,8 @@ import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.core.RObject;
import org.redisson.liveobject.CodecProvider;
import org.redisson.liveobject.RAttachedLiveObjectService;
import org.redisson.liveobject.annotation.REntity;
import org.redisson.liveobject.annotation.RId;
@ -20,17 +19,17 @@ public class RedissonAttachedLiveObjectService implements RAttachedLiveObjectSer
private final Map<Class, Class> classCache;
private final Map<Class, Class> proxyCache;
private final RedissonClient redisson;
private final CommandAsyncExecutor commandExecutor;
public RedissonAttachedLiveObjectService(RedissonClient redisson, CommandAsyncExecutor commandExecutor, Map<Class, Class> classCache, Map<Class, Class> proxyCache) {
private final CodecProvider codecProvider;
public RedissonAttachedLiveObjectService(RedissonClient redisson, Map<Class, Class> classCache, Map<Class, Class> proxyCache, CodecProvider codecProvider) {
this.redisson = redisson;
this.commandExecutor = commandExecutor;
this.classCache = classCache;
this.proxyCache = proxyCache;
this.codecProvider = codecProvider;
}
//TODO: Support ID Generator
@Override
public <T, K> T get(Class<T> entityClass, K id, long ttl) {
@ -83,7 +82,7 @@ public class RedissonAttachedLiveObjectService implements RAttachedLiveObjectSer
.and(ElementMatchers.isGetter()
.or(ElementMatchers.isSetter()))
.and(ElementMatchers.isPublic()))
.intercept(MethodDelegation.to(new AccessorInterceptor(redisson, commandExecutor, entityClass, idFieldName)))
.intercept(MethodDelegation.to(new AccessorInterceptor(redisson, codecProvider, entityClass, idFieldName)))
.make().load(getClass().getClassLoader(),
ClassLoadingStrategy.Default.WRAPPER)
.getLoaded());
@ -104,4 +103,11 @@ public class RedissonAttachedLiveObjectService implements RAttachedLiveObjectSer
}
}
/**
* @return the codecProvider
*/
public CodecProvider getCodecProvider() {
return codecProvider;
}
}

@ -59,6 +59,8 @@ import org.redisson.core.RSetMultimap;
import org.redisson.core.RSetMultimapCache;
import org.redisson.core.RSortedSet;
import org.redisson.core.RTopic;
import org.redisson.liveobject.CodecProvider;
import org.redisson.liveobject.RAttachedLiveObjectService;
/**
* Main Redisson interface for access
@ -645,7 +647,16 @@ public interface RedissonClient {
*
* @return
*/
RedissonAttachedLiveObjectService getAttachedLiveObjectService();
RAttachedLiveObjectService getAttachedLiveObjectService();
/**
* Returns RedissonAttachedLiveObjectService which can be used to
* retrieve live REntity(s)
*
* @param codecProvider the CodecProvider to be used to create the service
* @return
*/
RAttachedLiveObjectService getAttachedLiveObjectService(CodecProvider codecProvider);
/**
* Shuts down Redisson instance <b>NOT</b> Redis server

@ -128,4 +128,9 @@ abstract class RedissonObject implements RObject {
return commandExecutor.readAsync(getName(), codec, RedisCommands.EXISTS, getName());
}
@Override
public Codec getCodec() {
return codec;
}
}

@ -5,23 +5,24 @@ import org.redisson.core.RObject;
/**
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonReference {
private String type;
private Object keyName;
private String keyName;
private String codec;
public RedissonReference() {
}
public RedissonReference(Class<? extends RObject> type, Object keyName) {
public RedissonReference(Class<? extends RObject> type, String keyName) {
this.type = type.getCanonicalName();
this.keyName = keyName;
this.codec = null;
}
public RedissonReference(Class<? extends RObject> type, Object keyName, Codec codec) {
public RedissonReference(Class<? extends RObject> type, String keyName, Codec codec) {
this.type = type.getCanonicalName();
this.keyName = keyName;
this.codec = codec.getClass().getCanonicalName();
@ -34,12 +35,15 @@ public class RedissonReference {
/**
* @return the type
*/
public Class<? extends RObject> getType() {
try {
return (Class<? extends RObject>) Class.forName(type);
} catch (ClassNotFoundException ex) {
return null;
}
public Class<? extends RObject> getType() throws Exception {
return (Class<? extends RObject>) Class.forName(type);
}
/**
* @return type name in string
*/
public String getTypeName() {
return type;
}
/**
@ -52,32 +56,38 @@ public class RedissonReference {
/**
* @return the keyName
*/
public Object getKeyName() {
public String getKeyName() {
return keyName;
}
/**
* @param keyName the keyName to set
*/
public void setKeyName(Object keyName) {
public void setKeyName(String keyName) {
this.keyName = keyName;
}
/**
* @return the codec
*/
public Codec getCodec() throws Exception {
return codec == null
public Class<? extends Codec> getCodecType() throws Exception {
return (Class<? extends Codec>) (codec == null
? null
: (Codec) Class.forName(codec).newInstance();
: Class.forName(codec));
}
/**
* @return Codec name in string
*/
public String getCodecName() {
return codec;
}
/**
* @param codec the codec to set
*/
public void setCodec(Codec codec) {
this.codec = codec.getClass().getCanonicalName();
public void setCodecType(Class<? extends Codec> codec) {
this.codec = codec.getCanonicalName();
}
}

@ -15,6 +15,8 @@
*/
package org.redisson.core;
import org.redisson.client.codec.Codec;
/**
* Base interface for all Redisson objects
*
@ -76,4 +78,10 @@ public interface RObject extends RObjectAsync {
*/
boolean isExists();
/**
* Returns the underlying Codec used by this RObject
*
* @return
*/
Codec getCodec();
}

@ -0,0 +1,23 @@
package org.redisson.liveobject;
import org.redisson.client.codec.Codec;
import org.redisson.core.RObject;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public interface CodecProvider {
Codec getCodec(Class<? extends Codec> codecClass);
Codec getCodec(Class<? extends Codec> codecClass, Class<? extends RObject> rObjectClass, String name);
Codec getCodec(Class<? extends Codec> codecClass, RObject rObject, String name);
void registerCodec(Class<? extends Codec> codecClass, Codec codec);
void registerCodec(Class<? extends Codec> codecClass, Class<? extends RObject> rObjectClass, String name, Codec codec);
void registerCodec(Class<? extends Codec> codecClass, RObject rObject, String name, Codec codec);
}

@ -0,0 +1,59 @@
package org.redisson.liveobject;
import io.netty.util.internal.PlatformDependent;
import java.util.concurrent.ConcurrentMap;
import org.redisson.client.codec.Codec;
import org.redisson.core.RObject;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class DefaultCodecProvider implements CodecProvider {
public static final ConcurrentMap<Class<? extends Codec>, Codec> codecCache = PlatformDependent.newConcurrentHashMap();
@Override
public Codec getCodec(Class<? extends Codec> codecClass) {
if (!codecCache.containsKey(codecClass)) {
try {
codecCache.putIfAbsent(codecClass, codecClass.newInstance());
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
return codecCache.get(codecClass);
}
@Override
public Codec getCodec(Class<? extends Codec> codecClass, Class<? extends RObject> rObjectClass, String name) {
if (rObjectClass.isInterface()) {
throw new IllegalArgumentException("Cannot lookup an interface class of RObject " + rObjectClass.getCanonicalName() + ". Concrete class only.");
}
return getCodec(codecClass);
}
@Override
public Codec getCodec(Class<? extends Codec> codecClass, RObject rObject, String name) {
return getCodec(codecClass, rObject.getClass(), name);
}
@Override
public void registerCodec(Class<? extends Codec> cls, Codec codec) {
codecCache.putIfAbsent(cls, codec);
}
@Override
public void registerCodec(Class<? extends Codec> codecClass, Class<? extends RObject> rObjectClass, String name, Codec codec) {
if (rObjectClass.isInterface()) {
throw new IllegalArgumentException("Cannot register an interface class of RObject " + rObjectClass.getCanonicalName() + ". Concrete class only.");
}
registerCodec(codecClass, codec);
}
@Override
public void registerCodec(Class<? extends Codec> codecClass, RObject rObject, String name, Codec codec) {
registerCodec(codecClass, rObject.getClass(), name, codec);
}
}

@ -2,7 +2,7 @@ package org.redisson.liveobject;
/**
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
*
*/
public interface RAttachedLiveObjectService extends RLiveObjectService {

@ -4,7 +4,7 @@ import io.netty.util.concurrent.Future;
/**
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
*
* @param <T> Entity type
* @param <K> Key type

@ -9,7 +9,7 @@ package org.redisson.liveobject;
* In DETACHED Mode, entity's field values are kept local and only pushed to
* Redis when update is called.
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
*
*/
public interface RLiveObjectService {

@ -4,10 +4,12 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.redisson.client.codec.Codec;
import org.redisson.codec.JsonJacksonCodec;
/**
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@ -15,7 +17,8 @@ public @interface REntity {
Class<? extends NamingScheme> namingScheme() default DefaultNamingScheme.class;
Class<? extends Codec> codec() default JsonJacksonCodec.class;
public interface NamingScheme {
public String getName(Class cls, String idFieldName, Object id);

@ -8,7 +8,7 @@ import org.redisson.liveobject.resolver.FieldValueAsIdGenerator;
/**
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})

@ -7,38 +7,41 @@ import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.implementation.bind.annotation.This;
import org.redisson.RedissonAttachedLiveObjectService;
import org.redisson.RedissonClient;
import org.redisson.RedissonMap;
import org.redisson.RedissonReference;
import org.redisson.client.RedisException;
import org.redisson.client.codec.Codec;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.core.RMap;
import org.redisson.core.RObject;
import org.redisson.liveobject.CodecProvider;
import org.redisson.liveobject.annotation.REntity;
import org.redisson.liveobject.annotation.RId;
import org.redisson.liveobject.misc.Introspectior;
/**
* This class is going to be instantiated and becomes a <b>static</b> field of the proxied
* target class. That is one instance of this class per proxied class.
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
*/
public class AccessorInterceptor {
private final RedissonClient redisson;
private final CommandAsyncExecutor commandExecutor;
private final CodecProvider codecProvider;
private final Class originalClass;
private final String idFieldName;
private final REntity.NamingScheme namingScheme;
private RMap liveMap;
public AccessorInterceptor(RedissonClient redisson, CommandAsyncExecutor commandExecutor, Class entityClass, String idFieldName) throws Exception {
private final Class<? extends Codec> codecClass;
public AccessorInterceptor(RedissonClient redisson, CodecProvider codecProvider, Class entityClass, String idFieldName) throws Exception {
this.redisson = redisson;
this.commandExecutor = commandExecutor;
this.codecProvider = codecProvider;
this.originalClass = entityClass;
this.idFieldName = idFieldName;
this.namingScheme = ((REntity) entityClass.getAnnotation(REntity.class))
.namingScheme().newInstance();
REntity anno = ((REntity) entityClass.getAnnotation(REntity.class));
this.namingScheme = anno.namingScheme().newInstance();
this.codecClass = anno.codec();
}
@RuntimeType
@ -47,10 +50,10 @@ public class AccessorInterceptor {
if (isGetter(method, idFieldName)) {
return superMethod.call();
}
initLiveMapIfRequired(getId(me));
String id = getMapKey(getId(me));
RMap liveMap = redisson.getMap(id, codecProvider.getCodec(codecClass, RedissonMap.class, id));
if (isSetter(method, idFieldName)) {
//TODO: distributed locking maybe required.
superMethod.call();
try {
liveMap.rename(getMapKey(args[0]));
} catch (RedisException e) {
@ -58,44 +61,34 @@ public class AccessorInterceptor {
throw e;
}
}
liveMap = null;
superMethod.call();
return null;
}
String fieldName = getFieldName(method);
if (isGetter(method, fieldName)) {
Object result = liveMap.get(fieldName);
if (method.getReturnType().isAnnotationPresent(REntity.class)) {
return redisson.getAttachedLiveObjectService()
return redisson.getAttachedLiveObjectService(codecProvider)
.get((Class<Object>) method.getReturnType(), result);
} else if (result instanceof RedissonReference) {
RedissonReference r = ((RedissonReference) result);
//TODO: use reflection on redisson object
return r.getType()
.getConstructor(Codec.class, CommandAsyncExecutor.class, String.class)
.newInstance(r.isDefaultCodec()
? commandExecutor.getConnectionManager().getCodec()
: r.getCodec(), commandExecutor, r.getKeyName());
return createRedissonObject((RedissonReference) result, method.getReturnType());
}
return result;
}
if (isSetter(method, fieldName)) {
if (method.getParameterTypes()[0].isAnnotationPresent(REntity.class)) {
return liveMap.fastPut(fieldName, getREntityId(args[0]));
return liveMap.put(fieldName, getREntityId(args[0]));
} else if (args[0] instanceof RObject) {
RObject ar = (RObject) args[0];
return liveMap.fastPut(fieldName, new RedissonReference((Class<RObject>) args[0].getClass(), ar.getName()));
Codec codec = ar.getCodec();
codecProvider.registerCodec(codec.getClass(), ar, fieldName, codec);
return liveMap.put(fieldName, new RedissonReference(ar.getClass(), ar.getName(), codec));
}
return liveMap.fastPut(fieldName, args[0]);
return liveMap.put(fieldName, args[0]);
}
return superMethod.call();
}
private void initLiveMapIfRequired(Object id) {
if (liveMap == null) {
liveMap = redisson.getMap(getMapKey(id));
}
}
private String getFieldName(Method method) {
return method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
}
@ -134,4 +127,23 @@ public class AccessorInterceptor {
return getFieldValue(o, idName);
}
private RObject createRedissonObject(RedissonReference rr, Class expected) throws Exception {
if (rr.getType() != null) {
for (Method method : RedissonClient.class.getDeclaredMethods()) {
if (method.getName().startsWith("get")
&& method.getReturnType().isAssignableFrom(rr.getType())
&& method.getReturnType().isAssignableFrom(expected)) {
if (rr.isDefaultCodec() && method.getParameterCount() == 1) {
return (RObject) method.invoke(redisson, rr.getKeyName());
} else if (!rr.isDefaultCodec()
&& method.getParameterCount() == 2
&& String.class.equals(method.getParameterTypes()[0])
&& Codec.class.equals(method.getParameterTypes()[1])) {
return (RObject) method.invoke(redisson, rr.getKeyName(), codecProvider.getCodec(rr.getCodecType()));
}
}
}
}
throw new ClassNotFoundException("No RObject is found to match class type of " + rr.getTypeName() + " with codec type of " + rr.getCodecName());
}
}

@ -11,7 +11,7 @@ import net.bytebuddy.matcher.ElementMatchers;
/**
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
*/
public class Introspectior {

@ -4,7 +4,7 @@ import org.redisson.liveobject.annotation.RId;
/**
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
*/
public class FieldValueAsIdGenerator implements Resolver<Object, RId, String>{

@ -4,7 +4,7 @@ import java.lang.annotation.Annotation;
/**
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
* @param <T> Field instance
* @param <A> Annotation to resolve
*/

@ -19,6 +19,10 @@ import org.redisson.client.RedisConnection;
import org.redisson.client.protocol.RedisStrictCommand;
import org.redisson.client.protocol.convertor.VoidReplayConvertor;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedisRunner {
public enum REDIS_OPTIONS {

@ -5,7 +5,7 @@ import java.util.regex.Pattern;
/**
*
* @author Jack
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedisVersion implements Comparable<RedisVersion>{

@ -4,12 +4,13 @@ import java.io.Serializable;
import static org.junit.Assert.*;
import org.junit.Test;
import org.redisson.core.RMap;
import org.redisson.liveobject.RAttachedLiveObjectService;
import org.redisson.liveobject.annotation.REntity;
import org.redisson.liveobject.annotation.RId;
/**
*
* @author ruigu
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonAttachedLiveObjectServiceTest extends BaseTest {
@ -189,8 +190,8 @@ public class RedissonAttachedLiveObjectServiceTest extends BaseTest {
}
@Test
public void test() {
RedissonAttachedLiveObjectService s = redisson.getAttachedLiveObjectService();
public void testBasics() {
RAttachedLiveObjectService s = redisson.getAttachedLiveObjectService();
TestREntity t = s.<TestREntity, String>get(TestREntity.class, "1");
assertEquals("1", t.getName());
assertTrue(!redisson.getMap(REntity.DefaultNamingScheme.INSTANCE.getName(TestREntity.class, "name", "1")).isExists());
@ -206,7 +207,7 @@ public class RedissonAttachedLiveObjectServiceTest extends BaseTest {
@Test
public void testLiveObjectWithRObject() {
RedissonAttachedLiveObjectService s = redisson.getAttachedLiveObjectService();
RAttachedLiveObjectService s = redisson.getAttachedLiveObjectService();
TestREntityWithRMap t = s.<TestREntityWithRMap, String>get(TestREntityWithRMap.class, "2");
RMap<String, String> map = redisson.<String, String>getMap("testMap");
t.setValue(map);
@ -222,7 +223,7 @@ public class RedissonAttachedLiveObjectServiceTest extends BaseTest {
@Test
public void testLiveObjectWithNestedLiveObjectAsId() {
RedissonAttachedLiveObjectService s = redisson.getAttachedLiveObjectService();
RAttachedLiveObjectService s = redisson.getAttachedLiveObjectService();
TestREntity t1 = s.<TestREntity, String>get(TestREntity.class, "1");
try {
s.<TestREntityIdNested, TestREntity>get(TestREntityIdNested.class, t1);
@ -233,7 +234,7 @@ public class RedissonAttachedLiveObjectServiceTest extends BaseTest {
@Test
public void testLiveObjectWithNestedLiveObjectAsValue() throws Exception {
RedissonAttachedLiveObjectService s = redisson.getAttachedLiveObjectService();
RAttachedLiveObjectService s = redisson.getAttachedLiveObjectService();
TestREntityWithRMap t1 = s.<TestREntityWithRMap, String>get(TestREntityWithRMap.class, "111");
TestREntityValueNested t2 = s.<TestREntityValueNested, String>get(TestREntityValueNested.class, "122");
RMap<String, String> map = redisson.<String, String>getMap("32123");

@ -1,13 +1,11 @@
package org.redisson;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonRuntimeEnvironment {
public static final boolean isTravis = "true".equalsIgnoreCase(System.getProperty("travisEnv"));

Loading…
Cancel
Save