I ran across this because I got a non-Jedis related exception between
using a Pipeline and calling Pipeline.sync(), meaning Pipeline.sync()
was never called.
Note that the "strange errors" was not a Jedis exception. In my
particular scenario, I was getting a ClassCastException:
java.lang.ClassCastException: java.lang.Long cannot be cast to
java.util.List
at
redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:
189)
at
redis.clients.jedis.Connection.getMultiBulkReply(Connection.java:182)
at redis.clients.jedis.Jedis.smembers(Jedis.java:1176)
Here's some sample code that demonstrates how I was getting a
ClassCastException:
Jedis jedis = pool.getResource();
try {
Pipeline p = jedis.pipelined();
p.sadd("some_key", userId);
p.setnx("some_key_" + userId,
Long.toString(System.currentTimeMillis()));
p.expire("some_key_" + userId, 60);
// some exception is thrown
if (true)
throw new Exception("hi there");
p.sync();
} finally {
pool.returnResource(jedis);
}
// Then, later, if we get the Jedis object the above code used:
Jedis jedis = pool.getResource();
try {
jedis.smembers("some_key"); // this will throw a
ClassCastException
} finally {
pool.returnResource(jedis);
}
From what I could tell the ClassCastException was because my first
pipeline call was to sadd, which has an integer reply, and when I
later tried to re-use the client (after returning it to the pool then
getting it back from the pool) I called smembers, which uses
getMultiBulkReply. It seems like depending upon which calls to the
Jedis object were made you may get incorrect return values instead of
an exception.
Note that I was using the default configurations on the JedisPool -
validateObject returns false when the above happens, so if you have
"test on borrow" or "test on return" set to true destroyObject will be
called.