diff --git a/src/main/java/com/lambdaworks/redis/RedisAsyncConnection.java b/src/main/java/com/lambdaworks/redis/RedisAsyncConnection.java index 076359d88..3f7153c5f 100644 --- a/src/main/java/com/lambdaworks/redis/RedisAsyncConnection.java +++ b/src/main/java/com/lambdaworks/redis/RedisAsyncConnection.java @@ -2,10 +2,30 @@ package com.lambdaworks.redis; -import com.lambdaworks.codec.Base16; -import com.lambdaworks.redis.codec.RedisCodec; -import com.lambdaworks.redis.output.*; -import com.lambdaworks.redis.protocol.*; +import static com.lambdaworks.redis.protocol.CommandKeyword.AFTER; +import static com.lambdaworks.redis.protocol.CommandKeyword.AND; +import static com.lambdaworks.redis.protocol.CommandKeyword.BEFORE; +import static com.lambdaworks.redis.protocol.CommandKeyword.ENCODING; +import static com.lambdaworks.redis.protocol.CommandKeyword.FLUSH; +import static com.lambdaworks.redis.protocol.CommandKeyword.GETNAME; +import static com.lambdaworks.redis.protocol.CommandKeyword.IDLETIME; +import static com.lambdaworks.redis.protocol.CommandKeyword.KILL; +import static com.lambdaworks.redis.protocol.CommandKeyword.LEN; +import static com.lambdaworks.redis.protocol.CommandKeyword.LIMIT; +import static com.lambdaworks.redis.protocol.CommandKeyword.LIST; +import static com.lambdaworks.redis.protocol.CommandKeyword.LOAD; +import static com.lambdaworks.redis.protocol.CommandKeyword.NO; +import static com.lambdaworks.redis.protocol.CommandKeyword.NOSAVE; +import static com.lambdaworks.redis.protocol.CommandKeyword.NOT; +import static com.lambdaworks.redis.protocol.CommandKeyword.ONE; +import static com.lambdaworks.redis.protocol.CommandKeyword.OR; +import static com.lambdaworks.redis.protocol.CommandKeyword.REFCOUNT; +import static com.lambdaworks.redis.protocol.CommandKeyword.RESET; +import static com.lambdaworks.redis.protocol.CommandKeyword.RESETSTAT; +import static com.lambdaworks.redis.protocol.CommandKeyword.SETNAME; +import static com.lambdaworks.redis.protocol.CommandKeyword.WITHSCORES; +import static com.lambdaworks.redis.protocol.CommandKeyword.XOR; +import static com.lambdaworks.redis.protocol.CommandType.*; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; @@ -13,11 +33,44 @@ import io.netty.channel.ChannelInboundHandlerAdapter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.*; -import java.util.concurrent.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; -import static com.lambdaworks.redis.protocol.CommandKeyword.*; -import static com.lambdaworks.redis.protocol.CommandType.*; +import com.lambdaworks.codec.Base16; +import com.lambdaworks.redis.codec.RedisCodec; +import com.lambdaworks.redis.output.BooleanListOutput; +import com.lambdaworks.redis.output.BooleanOutput; +import com.lambdaworks.redis.output.ByteArrayOutput; +import com.lambdaworks.redis.output.DateOutput; +import com.lambdaworks.redis.output.DoubleOutput; +import com.lambdaworks.redis.output.IntegerOutput; +import com.lambdaworks.redis.output.KeyListOutput; +import com.lambdaworks.redis.output.KeyOutput; +import com.lambdaworks.redis.output.KeyValueOutput; +import com.lambdaworks.redis.output.MapKeyListOutput; +import com.lambdaworks.redis.output.MapOutput; +import com.lambdaworks.redis.output.MapValueListOutput; +import com.lambdaworks.redis.output.MapValueOutput; +import com.lambdaworks.redis.output.MultiOutput; +import com.lambdaworks.redis.output.NestedMultiOutput; +import com.lambdaworks.redis.output.ScoredValueListOutput; +import com.lambdaworks.redis.output.StatusOutput; +import com.lambdaworks.redis.output.StringListOutput; +import com.lambdaworks.redis.output.ValueListOutput; +import com.lambdaworks.redis.output.ValueOutput; +import com.lambdaworks.redis.output.ValueSetOutput; +import com.lambdaworks.redis.protocol.Command; +import com.lambdaworks.redis.protocol.CommandArgs; +import com.lambdaworks.redis.protocol.CommandOutput; +import com.lambdaworks.redis.protocol.CommandType; +import com.lambdaworks.redis.protocol.ConnectionWatchdog; /** * An asynchronous thread-safe connection to a redis server. Multiple threads may @@ -281,18 +334,18 @@ public class RedisAsyncConnection extends ChannelInboundHandlerAdapter { } public Future hdel(K key, K... fields) { - CommandArgs args = new CommandArgs(codec).addKey(key).addKeys(fields); + CommandArgs args = new CommandArgs(codec).addKey(key).addMapKeys(fields); return dispatch(HDEL, new IntegerOutput(codec), args); } public Future hexists(K key, K field) { - CommandArgs args = new CommandArgs(codec).addKey(key).addKey(field); + CommandArgs args = new CommandArgs(codec).addKey(key).addMapKey(field); return dispatch(HEXISTS, new BooleanOutput(codec), args); } public Future hget(K key, K field) { - CommandArgs args = new CommandArgs(codec).addKey(key).addKey(field); - return dispatch(HGET, new ValueOutput(codec), args); + CommandArgs args = new CommandArgs(codec).addKey(key).addMapKey(field); + return dispatch(HGET, new MapValueOutput(codec), args); } public Future hincrby(K key, K field, long amount) { @@ -309,8 +362,8 @@ public class RedisAsyncConnection extends ChannelInboundHandlerAdapter { return dispatch(HGETALL, new MapOutput(codec), key); } - public Future> hkeys(K key) { - return dispatch(HKEYS, new KeyListOutput(codec), key); + public Future> hkeys(K key) { + return dispatch(HKEYS, new MapKeyListOutput(codec), key); } public Future hlen(K key) { @@ -328,17 +381,17 @@ public class RedisAsyncConnection extends ChannelInboundHandlerAdapter { } public Future hset(K key, K field, V value) { - CommandArgs args = new CommandArgs(codec).addKey(key).addKey(field).addValue(value); + CommandArgs args = new CommandArgs(codec).addKey(key).addMapKey(field).addMapValue(value); return dispatch(HSET, new BooleanOutput(codec), args); } public Future hsetnx(K key, K field, V value) { - CommandArgs args = new CommandArgs(codec).addKey(key).addKey(field).addValue(value); + CommandArgs args = new CommandArgs(codec).addKey(key).addMapKey(field).addMapValue(value); return dispatch(HSETNX, new BooleanOutput(codec), args); } public Future> hvals(K key) { - return dispatch(HVALS, new ValueListOutput(codec), key); + return dispatch(HVALS, new MapValueListOutput(codec), key); } public Future incr(K key) { @@ -374,7 +427,7 @@ public class RedisAsyncConnection extends ChannelInboundHandlerAdapter { public Future lindex(K key, long index) { CommandArgs args = new CommandArgs(codec).addKey(key).add(index); - return dispatch(LINDEX, new ValueOutput(codec), args); + return dispatch(LINDEX, new MapValueOutput(codec), args); } public Future linsert(K key, boolean before, V pivot, V value) { @@ -388,7 +441,7 @@ public class RedisAsyncConnection extends ChannelInboundHandlerAdapter { } public Future lpop(K key) { - return dispatch(LPOP, new ValueOutput(codec), key); + return dispatch(LPOP, new MapValueOutput(codec), key); } public Future lpush(K key, V... values) { @@ -405,7 +458,7 @@ public class RedisAsyncConnection extends ChannelInboundHandlerAdapter { } public Future lrem(K key, long count, V value) { - CommandArgs args = new CommandArgs(codec).addKey(key).add(count).addValue(value); + CommandArgs args = new CommandArgs(codec).addKey(key).add(count).addMapValue(value); return dispatch(LREM, new IntegerOutput(codec), args); } @@ -531,7 +584,8 @@ public class RedisAsyncConnection extends ChannelInboundHandlerAdapter { } public Future rpush(K key, V... values) { - return dispatch(RPUSH, new IntegerOutput(codec), key, values); + CommandArgs args = new CommandArgs(codec).addKey(key).addMapValues(values); + return dispatch(RPUSH, new IntegerOutput(codec), args); } public Future rpushx(K key, V value) { @@ -539,7 +593,8 @@ public class RedisAsyncConnection extends ChannelInboundHandlerAdapter { } public Future sadd(K key, V... members) { - return dispatch(SADD, new IntegerOutput(codec), key, members); + CommandArgs args = new CommandArgs(codec).addKey(key).addMapValues(members); + return dispatch(SADD, new IntegerOutput(codec), args); } public Future save() { @@ -633,7 +688,8 @@ public class RedisAsyncConnection extends ChannelInboundHandlerAdapter { } public Future sismember(K key, V member) { - return dispatch(SISMEMBER, new BooleanOutput(codec), key, member); + CommandArgs args = new CommandArgs(codec).addKey(key).addMapValue(member); + return dispatch(SISMEMBER, new BooleanOutput(codec), args); } public Future smove(K source, K destination, V member) { @@ -705,7 +761,8 @@ public class RedisAsyncConnection extends ChannelInboundHandlerAdapter { } public Future srem(K key, V... members) { - return dispatch(SREM, new IntegerOutput(codec), key, members); + CommandArgs args = new CommandArgs(codec).addKey(key).addMapValues(members); + return dispatch(SREM, new IntegerOutput(codec), args); } public Future> sunion(K... keys) { diff --git a/src/main/java/com/lambdaworks/redis/RedisConnection.java b/src/main/java/com/lambdaworks/redis/RedisConnection.java index 434326179..e2dde3c5c 100644 --- a/src/main/java/com/lambdaworks/redis/RedisConnection.java +++ b/src/main/java/com/lambdaworks/redis/RedisConnection.java @@ -278,7 +278,7 @@ public class RedisConnection { return await(c.hgetall(key)); } - public List hkeys(K key) { + public Set hkeys(K key) { return await(c.hkeys(key)); } diff --git a/src/main/java/com/lambdaworks/redis/codec/RedisCodec.java b/src/main/java/com/lambdaworks/redis/codec/RedisCodec.java index 10ba4d6fd..970128381 100644 --- a/src/main/java/com/lambdaworks/redis/codec/RedisCodec.java +++ b/src/main/java/com/lambdaworks/redis/codec/RedisCodec.java @@ -52,4 +52,15 @@ public abstract class RedisCodec { * @return The encoded value. */ public abstract byte[] encodeValue(V value); + + + public abstract byte[] encodeMapValue(V value); + + public abstract byte[] encodeMapKey(K key); + + public abstract V decodeMapValue(ByteBuffer bytes); + + public abstract K decodeMapKey(ByteBuffer bytes); + + } diff --git a/src/main/java/com/lambdaworks/redis/codec/Utf8StringCodec.java b/src/main/java/com/lambdaworks/redis/codec/Utf8StringCodec.java index 4dc4d0ba1..527f6a631 100644 --- a/src/main/java/com/lambdaworks/redis/codec/Utf8StringCodec.java +++ b/src/main/java/com/lambdaworks/redis/codec/Utf8StringCodec.java @@ -64,4 +64,24 @@ public class Utf8StringCodec extends RedisCodec { private byte[] encode(String string) { return string.getBytes(charset); } + + @Override + public byte[] encodeMapValue(String value) { + return encodeValue(value); + } + + @Override + public byte[] encodeMapKey(String key) { + return encodeKey(key); + } + + @Override + public String decodeMapValue(ByteBuffer bytes) { + return decodeValue(bytes); + } + + @Override + public String decodeMapKey(ByteBuffer bytes) { + return decodeKey(bytes); + } } diff --git a/src/main/java/com/lambdaworks/redis/output/MapKeyListOutput.java b/src/main/java/com/lambdaworks/redis/output/MapKeyListOutput.java new file mode 100644 index 000000000..0f7ba1bcb --- /dev/null +++ b/src/main/java/com/lambdaworks/redis/output/MapKeyListOutput.java @@ -0,0 +1,29 @@ +// Copyright (C) 2011 - Will Glozer. All rights reserved. + +package com.lambdaworks.redis.output; + +import java.nio.ByteBuffer; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import com.lambdaworks.redis.codec.RedisCodec; +import com.lambdaworks.redis.protocol.CommandOutput; + +/** + * {@link List} of keys output. + * + * @param Key type. + * + * @author Will Glozer + */ +public class MapKeyListOutput extends CommandOutput> { + public MapKeyListOutput(RedisCodec codec) { + super(codec, new LinkedHashSet()); + } + + @Override + public void set(ByteBuffer bytes) { + output.add(codec.decodeMapKey(bytes)); + } +} diff --git a/src/main/java/com/lambdaworks/redis/output/MapOutput.java b/src/main/java/com/lambdaworks/redis/output/MapOutput.java index f88d09228..91425a320 100644 --- a/src/main/java/com/lambdaworks/redis/output/MapOutput.java +++ b/src/main/java/com/lambdaworks/redis/output/MapOutput.java @@ -27,11 +27,11 @@ public class MapOutput extends CommandOutput> { @Override public void set(ByteBuffer bytes) { if (key == null) { - key = codec.decodeKey(bytes); + key = codec.decodeMapKey(bytes); return; } - V value = (bytes == null) ? null : codec.decodeValue(bytes); + V value = (bytes == null) ? null : codec.decodeMapValue(bytes); output.put(key, value); key = null; } diff --git a/src/main/java/com/lambdaworks/redis/output/MapValueListOutput.java b/src/main/java/com/lambdaworks/redis/output/MapValueListOutput.java new file mode 100644 index 000000000..bbb8f26d3 --- /dev/null +++ b/src/main/java/com/lambdaworks/redis/output/MapValueListOutput.java @@ -0,0 +1,28 @@ +// Copyright (C) 2011 - Will Glozer. All rights reserved. + +package com.lambdaworks.redis.output; + +import com.lambdaworks.redis.codec.RedisCodec; +import com.lambdaworks.redis.protocol.CommandOutput; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * {@link List} of values output. + * + * @param Value type. + * + * @author Will Glozer + */ +public class MapValueListOutput extends CommandOutput> { + public MapValueListOutput(RedisCodec codec) { + super(codec, new ArrayList()); + } + + @Override + public void set(ByteBuffer bytes) { + output.add(bytes == null ? null : codec.decodeMapValue(bytes)); + } +} diff --git a/src/main/java/com/lambdaworks/redis/output/MapValueOutput.java b/src/main/java/com/lambdaworks/redis/output/MapValueOutput.java new file mode 100644 index 000000000..659a3b75c --- /dev/null +++ b/src/main/java/com/lambdaworks/redis/output/MapValueOutput.java @@ -0,0 +1,26 @@ +// Copyright (C) 2011 - Will Glozer. All rights reserved. + +package com.lambdaworks.redis.output; + +import com.lambdaworks.redis.codec.RedisCodec; +import com.lambdaworks.redis.protocol.CommandOutput; + +import java.nio.ByteBuffer; + +/** + * Value output. + * + * @param Value type. + * + * @author Will Glozer + */ +public class MapValueOutput extends CommandOutput { + public MapValueOutput(RedisCodec codec) { + super(codec, null); + } + + @Override + public void set(ByteBuffer bytes) { + output = (bytes == null) ? null : codec.decodeMapValue(bytes); + } +} diff --git a/src/main/java/com/lambdaworks/redis/output/ValueSetOutput.java b/src/main/java/com/lambdaworks/redis/output/ValueSetOutput.java index 936d2286d..d7701dc5a 100644 --- a/src/main/java/com/lambdaworks/redis/output/ValueSetOutput.java +++ b/src/main/java/com/lambdaworks/redis/output/ValueSetOutput.java @@ -23,6 +23,6 @@ public class ValueSetOutput extends CommandOutput> { @Override public void set(ByteBuffer bytes) { - output.add(bytes == null ? null : codec.decodeValue(bytes)); + output.add(bytes == null ? null : codec.decodeMapValue(bytes)); } } diff --git a/src/main/java/com/lambdaworks/redis/protocol/CommandArgs.java b/src/main/java/com/lambdaworks/redis/protocol/CommandArgs.java index 91b5750dc..a9ea062c7 100644 --- a/src/main/java/com/lambdaworks/redis/protocol/CommandArgs.java +++ b/src/main/java/com/lambdaworks/redis/protocol/CommandArgs.java @@ -36,6 +36,17 @@ public class CommandArgs { return count; } + public CommandArgs addMapKeys(K... keys) { + for (K key : keys) { + addMapKey(key); + } + return this; + } + + public CommandArgs addMapKey(K key) { + return write(codec.encodeMapKey(key)); + } + public CommandArgs addKey(K key) { return write(codec.encodeKey(key)); } @@ -47,10 +58,21 @@ public class CommandArgs { return this; } + public CommandArgs addMapValue(V value) { + return write(codec.encodeMapValue(value)); + } + public CommandArgs addValue(V value) { return write(codec.encodeValue(value)); } + public CommandArgs addMapValues(V... values) { + for (V value : values) { + addMapValue(value); + } + return this; + } + public CommandArgs addValues(V... values) { for (V value : values) { addValue(value); @@ -64,8 +86,8 @@ public class CommandArgs { } for (Map.Entry entry : map.entrySet()) { - write(codec.encodeKey(entry.getKey())); - write(codec.encodeValue(entry.getValue())); + write(codec.encodeMapKey(entry.getKey())); + write(codec.encodeMapValue(entry.getValue())); } return this; diff --git a/src/main/java/com/lambdaworks/redis/protocol/CommandHandler.java b/src/main/java/com/lambdaworks/redis/protocol/CommandHandler.java index 3051046a7..8682a18cc 100644 --- a/src/main/java/com/lambdaworks/redis/protocol/CommandHandler.java +++ b/src/main/java/com/lambdaworks/redis/protocol/CommandHandler.java @@ -44,10 +44,10 @@ public class CommandHandler extends ChannelDuplexHandler { ByteBuf input = (ByteBuf) msg; try { if (!input.isReadable()) return; - + buffer.discardReadBytes(); buffer.writeBytes(input); - + decode(ctx, buffer); } finally { input.release(); @@ -57,7 +57,6 @@ public class CommandHandler extends ChannelDuplexHandler { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { Command cmd = (Command) msg; - Channel channel = ctx.channel(); ByteBuf buf = ctx.alloc().heapBuffer(); cmd.encode(buf); ctx.write(buf, promise); diff --git a/src/main/java/org/redisson/RedissonAtomicLong.java b/src/main/java/org/redisson/RedissonAtomicLong.java index c7de2d837..9081043e9 100644 --- a/src/main/java/org/redisson/RedissonAtomicLong.java +++ b/src/main/java/org/redisson/RedissonAtomicLong.java @@ -68,7 +68,7 @@ public class RedissonAtomicLong extends RedissonObject implements RAtomicLong { conn.watch(getName()); Long value = ((Number) conn.get(getName())).longValue(); if (value != expect) { - conn.discard(); + conn.unwatch(); return false; } conn.multi(); diff --git a/src/main/java/org/redisson/RedissonCountDownLatch.java b/src/main/java/org/redisson/RedissonCountDownLatch.java index e4d620ff5..74784ae52 100644 --- a/src/main/java/org/redisson/RedissonCountDownLatch.java +++ b/src/main/java/org/redisson/RedissonCountDownLatch.java @@ -167,7 +167,7 @@ public class RedissonCountDownLatch extends RedissonObject implements RCountDown connection.watch(getName()); Long oldValue = (Long) connection.get(getName()); if (oldValue != null) { - connection.discard(); + connection.unwatch(); return false; } connection.multi(); diff --git a/src/main/java/org/redisson/RedissonList.java b/src/main/java/org/redisson/RedissonList.java index 98a2309c3..4382b841d 100644 --- a/src/main/java/org/redisson/RedissonList.java +++ b/src/main/java/org/redisson/RedissonList.java @@ -245,9 +245,16 @@ public class RedissonList extends RedissonObject implements RList { checkIndex(index); RedisConnection conn = connectionManager.connection(); try { - V prev = (V) conn.lindex(getName(), index); - conn.lset(getName(), index, element); - return prev; + while (true) { + conn.watch(getName()); + V prev = (V) conn.lindex(getName(), index); + + conn.multi(); + conn.lset(getName(), index, element); + if (conn.exec().size() == 1) { + return prev; + } + } } finally { connectionManager.release(conn); } diff --git a/src/main/java/org/redisson/RedissonMap.java b/src/main/java/org/redisson/RedissonMap.java index e0afc42da..bc0e41f80 100644 --- a/src/main/java/org/redisson/RedissonMap.java +++ b/src/main/java/org/redisson/RedissonMap.java @@ -17,7 +17,6 @@ package org.redisson; import java.util.Collection; import java.util.HashMap; -import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -138,7 +137,7 @@ public class RedissonMap extends RedissonObject implements RMap { public Set keySet() { RedisConnection connection = connectionManager.connection(); try { - return new LinkedHashSet((Collection) connection.hkeys(getName())); + return (Set) connection.hkeys(getName()); } finally { connectionManager.release(connection); } @@ -146,6 +145,7 @@ public class RedissonMap extends RedissonObject implements RMap { @Override public Collection values() { + // TODO fix Long RedisConnection connection = connectionManager.connection(); try { return (Collection) connection.hvals(getName()); @@ -176,7 +176,7 @@ public class RedissonMap extends RedissonObject implements RMap { while (true) { Boolean res = connection.hsetnx(getName(), key, value); if (!res) { - V result = get(key); + V result = (V) connection.hget(getName(), key); if (result != null) { return result; } @@ -248,6 +248,7 @@ public class RedissonMap extends RedissonObject implements RMap { while (true) { connection.watch(getName()); if (connection.hexists(getName(), key)) { + // TODO fix Long V prev = (V) connection.hget(getName(), key); connection.multi(); connection.hset(getName(), key, value); diff --git a/src/main/java/org/redisson/RedissonSortedSet.java b/src/main/java/org/redisson/RedissonSortedSet.java index 6f96db51e..0cb570ba6 100644 --- a/src/main/java/org/redisson/RedissonSortedSet.java +++ b/src/main/java/org/redisson/RedissonSortedSet.java @@ -26,8 +26,6 @@ import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.SortedSet; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; import org.redisson.connection.ConnectionManager; import org.redisson.core.RSortedSet; @@ -126,8 +124,11 @@ public class RedissonSortedSet extends RedissonObject implements RSortedSet conn = connectionManager.connection(); - conn.setnx(getCurrentVersionKey(), 0L); - connectionManager.release(conn); + try { + conn.setnx(getCurrentVersionKey(), 0L); + } finally { + connectionManager.release(conn); + } } private void loadComparator() { diff --git a/src/main/java/org/redisson/codec/JsonJacksonCodec.java b/src/main/java/org/redisson/codec/JsonJacksonCodec.java index edcd06085..546dffd1e 100644 --- a/src/main/java/org/redisson/codec/JsonJacksonCodec.java +++ b/src/main/java/org/redisson/codec/JsonJacksonCodec.java @@ -37,20 +37,18 @@ import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; public class JsonJacksonCodec implements RedissonCodec { private final ObjectMapper objectMapper = new ObjectMapper(); + private ObjectMapper mapObjectMapper = new ObjectMapper(); public JsonJacksonCodec() { - objectMapper.setSerializationInclusion(Include.NON_NULL); - objectMapper.setVisibilityChecker(objectMapper.getSerializationConfig().getDefaultVisibilityChecker() - .withFieldVisibility(JsonAutoDetect.Visibility.ANY) - .withGetterVisibility(JsonAutoDetect.Visibility.NONE) - .withSetterVisibility(JsonAutoDetect.Visibility.NONE) - .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)); - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - objectMapper.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN, true); - objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true); + createObjectMapper(objectMapper); + TypeResolverBuilder typer = new DefaultTypeResolverBuilder(DefaultTyping.NON_FINAL); + typer.init(JsonTypeInfo.Id.CLASS, null); + typer.inclusion(JsonTypeInfo.As.PROPERTY); + objectMapper.setDefaultTyping(typer); + createObjectMapper(mapObjectMapper); // type info inclusion - TypeResolverBuilder typer = new DefaultTypeResolverBuilder(DefaultTyping.NON_FINAL) { + TypeResolverBuilder mapTyper = new DefaultTypeResolverBuilder(DefaultTyping.NON_FINAL) { public boolean useForType(JavaType t) { switch (_appliesFor) { @@ -66,7 +64,7 @@ public class JsonJacksonCodec implements RedissonCodec { t = t.getContentType(); } // to fix problem with wrong long to int conversion - if (t.isPrimitive() || t.getRawClass() == Long.class) { + if (t.getRawClass() == Long.class) { return true; } return !t.isFinal(); // includes Object.class @@ -76,9 +74,21 @@ public class JsonJacksonCodec implements RedissonCodec { } } }; - typer.init(JsonTypeInfo.Id.CLASS, null); - typer.inclusion(JsonTypeInfo.As.PROPERTY); - objectMapper.setDefaultTyping(typer); + mapTyper.init(JsonTypeInfo.Id.CLASS, null); + mapTyper.inclusion(JsonTypeInfo.As.PROPERTY); + mapObjectMapper.setDefaultTyping(mapTyper); + } + + private void createObjectMapper(ObjectMapper objectMapper) { + objectMapper.setSerializationInclusion(Include.NON_NULL); + objectMapper.setVisibilityChecker(objectMapper.getSerializationConfig().getDefaultVisibilityChecker() + .withFieldVisibility(JsonAutoDetect.Visibility.ANY) + .withGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withSetterVisibility(JsonAutoDetect.Visibility.NONE) + .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN, true); + objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true); } @Override @@ -113,4 +123,32 @@ public class JsonJacksonCodec implements RedissonCodec { } } + @Override + public byte[] encodeMapValue(Object value) { + try { + return mapObjectMapper.writeValueAsBytes(value); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + @Override + public byte[] encodeMapKey(Object key) { + return encodeMapValue(key); + } + + @Override + public Object decodeMapValue(ByteBuffer bytes) { + try { + return mapObjectMapper.readValue(bytes.array(), bytes.arrayOffset() + bytes.position(), bytes.limit(), Object.class); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + @Override + public Object decodeMapKey(ByteBuffer bytes) { + return decodeMapValue(bytes); + } + } diff --git a/src/main/java/org/redisson/codec/RedisCodecWrapper.java b/src/main/java/org/redisson/codec/RedisCodecWrapper.java index 7b51e731f..d9b2ca970 100644 --- a/src/main/java/org/redisson/codec/RedisCodecWrapper.java +++ b/src/main/java/org/redisson/codec/RedisCodecWrapper.java @@ -52,6 +52,26 @@ public class RedisCodecWrapper extends RedisCodec { return redissonCodec.encodeValue(value); } + @Override + public byte[] encodeMapValue(Object value) { + return redissonCodec.encodeMapValue(value); + } + + @Override + public byte[] encodeMapKey(Object key) { + return redissonCodec.encodeMapKey(key); + } + + @Override + public Object decodeMapValue(ByteBuffer bytes) { + return redissonCodec.decodeMapValue(bytes); + } + + @Override + public Object decodeMapKey(ByteBuffer bytes) { + return redissonCodec.decodeMapKey(bytes); + } + } diff --git a/src/main/java/org/redisson/codec/RedissonCodec.java b/src/main/java/org/redisson/codec/RedissonCodec.java index 46376fec9..ee0e5433a 100644 --- a/src/main/java/org/redisson/codec/RedissonCodec.java +++ b/src/main/java/org/redisson/codec/RedissonCodec.java @@ -32,4 +32,12 @@ public interface RedissonCodec { byte[] encodeValue(Object value); + byte[] encodeMapValue(Object value); + + byte[] encodeMapKey(Object key); + + Object decodeMapValue(ByteBuffer bytes); + + Object decodeMapKey(ByteBuffer bytes); + } diff --git a/src/main/java/org/redisson/codec/SerializationCodec.java b/src/main/java/org/redisson/codec/SerializationCodec.java index 45d4aaab5..c24735a9a 100644 --- a/src/main/java/org/redisson/codec/SerializationCodec.java +++ b/src/main/java/org/redisson/codec/SerializationCodec.java @@ -66,4 +66,24 @@ public class SerializationCodec implements RedissonCodec { } } + @Override + public byte[] encodeMapValue(Object value) { + return encodeValue(value); + } + + @Override + public byte[] encodeMapKey(Object key) { + return encodeKey(key); + } + + @Override + public Object decodeMapValue(ByteBuffer bytes) { + return decodeValue(bytes); + } + + @Override + public Object decodeMapKey(ByteBuffer bytes) { + return decodeKey(bytes); + } + } diff --git a/src/test/java/org/redisson/RedissonListTest.java b/src/test/java/org/redisson/RedissonListTest.java index ae1fad469..5415ddb4a 100644 --- a/src/test/java/org/redisson/RedissonListTest.java +++ b/src/test/java/org/redisson/RedissonListTest.java @@ -13,6 +13,17 @@ import org.junit.Test; public class RedissonListTest extends BaseTest { + @Test + public void testLong() { + Redisson redisson = Redisson.create(); + List list = redisson.getList("list"); + list.add(1L); + list.add(2L); + + Assert.assertThat(list, Matchers.contains(1L, 2L)); + clear(list, redisson); + } + @Test(expected = IllegalStateException.class) public void testListIteratorSetListFail() { List list = new ArrayList(); diff --git a/src/test/java/org/redisson/RedissonSetTest.java b/src/test/java/org/redisson/RedissonSetTest.java index dfc16f181..c3ddee43b 100644 --- a/src/test/java/org/redisson/RedissonSetTest.java +++ b/src/test/java/org/redisson/RedissonSetTest.java @@ -10,6 +10,17 @@ import org.junit.Test; public class RedissonSetTest extends BaseTest { + @Test + public void testLong() { + Redisson redisson = Redisson.create(); + Set set = redisson.getSet("set"); + set.add(1L); + set.add(2L); + + Assert.assertThat(set, Matchers.containsInAnyOrder(1L, 2L)); + clear(set, redisson); + } + @Test public void testRetainAll() { Redisson redisson = Redisson.create();