Quantcast
Channel: Active questions tagged redis+java - Stack Overflow
Viewing all articles
Browse latest Browse all 2229

Redisson sometimes throw classCastException

$
0
0

I use Redisson client with Spring boot application.I also enable setEnableTransactionSupport(true) and transactionAware() for JPA transaction integration.

    @Bean    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();        redisTemplate.setKeySerializer(new StringRedisSerializer());        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());        redisTemplate.setHashKeySerializer(new StringRedisSerializer());        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());        redisTemplate.setConnectionFactory(redisConnectionFactory);        redisTemplate.setEnableTransactionSupport(true);        return redisTemplate;    }    @Primary    @Bean    public CacheManager redisCacheManager() {        return RedisCacheManager.builder(redisConnectionFactory())                .cacheDefaults(redisCacheConfig())                .withInitialCacheConfigurations(cacheKeyMap())                .transactionAware()                .build();    }

It usually looks working inside @Transactional method.Once transaction be commited, then the cache put. This is common case.

But in some case, I desired to execute cache put without redis transaction.

Like

@Transactionalpublic void temp() {    // It doesn't matter work after commit.    redisTemplate.opsForValue().set("key2", "value2");    // It should return result before commit!!     // but it's null    long result = redisTemplate.opsForValue().increment("key1", "value1");    }

Generally, RedisTemplate does not work like this way.Maybe, the first set method open the redis transaction at connection and second increment method use the same connection.

Alternatively, I have select this implementation.

@Transactionalpublic void temp() {    redisTemplate.opsForValue().set("key2", "value2");    long result = redisTemplate.getConnectionFactory().getConnection().incrBy(combinedKey.getBytes(), delta);}

The second incrBy method uses the individual connection. The method does not participate in the previous redis transaction. Now it works as I expected. The result is stored.

But, RedissonConnection often throw exception.java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Long (java.lang.String and java.lang.Long are in module java.base of loader 'bootstrap')at org.redisson.spring.data.connection.RedissonConnection.incrBy(RedissonConnection.java:583)

Maybe the problem is happening with this code.

    public Long incrBy(byte[] key, long value) {        return (Long)this.write(key, StringCodec.INSTANCE, RedisCommands.INCRBY, key, value);    }

Exceptions are occurring intermittently(not always).I expect that sequence with delta value is set based on 0 in normal case, so it should be able to be cast normally.What is the problem?

Although RedissonConnection made an exception, it was confirmed that the value was set normally in the cache.It's just that an exception occurs in the process of type casting the result value.


Viewing all articles
Browse latest Browse all 2229

Trending Articles