본문 바로가기

Programing/OpenSource

[Spring Data Redis] Pipelining 에서 ClassCastException 발생

호출하는 코드는 5.11. Pipelining 의 예제와 동일한 형태이다.

그런데 아래와 같은 Cast 예외가 발생한다.

java.lang.ClassCastException: com.sun.proxy.$Proxy163 cannot be cast to org.springframework.data.redis.connection.StringRedisConnection

StackOverflow에 유사한 질문이 있다.

https://stackoverflow.com/questions/50680948/java-lang-classcastexception-com-sun-proxy-proxy219-cannot-be-cast-to-org-spri/53665591

그런데 해결책으로 나오는 것이 딱히 맘에 들지 않는다.

인라인 구현에서 밖의 redisTemplate를 참조하고 있기 때문이다.
doInRedis안에서는 RedisConnection만 가지고 처리하는 것이 맞아보이기 때문이다.

예제는 아래와 같이 되어 있는데,

//pop a specified number of items from a queue
List<Object> results = stringRedisTemplate.executePipelined(
  new RedisCallback<Object>() {
    public Object doInRedis(RedisConnection connection) throws DataAccessException {
      StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
      for(int i=0; i< batchSize; i++) {
        stringRedisConn.rPop("myqueue");
      }
    return null;
  }
});

아래와 같이 수정을 하는 것이 바람직하다.

//pop a specified number of items from a queue
List<Object> results = redisTemplate.executePipelined(
  new RedisCallback<Object>() {
    public Object doInRedis(RedisConnection connection) throws DataAccessException {
      return connection.rPop("myqueue".getBytes());
    }
});

만약 자바8 이후라면 다음과 같이 간단하게 쓸 수 있다.

//pop a specified number of items from a queue
List<Object> results = redisTemplate.executePipelined(
  (RedisCallback<Object>) connection -> connection.rPop("myqueue".getBytes())));

레퍼런스의 batchSize를 넣으면 아래와 같이 null객체가 쌓이므로 절대로 저렇게 하면 안된다.