2

Whats the difference between using Class.cast to convert an object to a certain type v/s doing the same using ObjectMapper.convertValue. I am assuming cast also internally uses jackson but I think that's not the case here.

My RedisTemplateConfig:

@Bean
public ReactiveRedisTemplate<String, Object> reactiveRedisTemplate(
    ReactiveRedisConnectionFactory factory) {
    StringRedisSerializer keySerializer = new StringRedisSerializer();
    Jackson2JsonRedisSerializer<Object> valueSerializer =
        new Jackson2JsonRedisSerializer<>(Object.class);
    RedisSerializationContext.RedisSerializationContextBuilder<String, Object> builder =
        RedisSerializationContext.newSerializationContext(keySerializer);
    RedisSerializationContext<String, Object> context =
        builder.value(valueSerializer).build();

    return new ReactiveRedisTemplate<>(factory, context);
}

SetValueInRedis:

@Override
public <T> Mono<T> setValue(String key, Object value, Class<T> clazz) {
    return reactiveValueOps.set(key, value,
            Duration.ofDays(SESSION_PERSISTENCE_DURATION))
            .map(o -> clazz.cast(value));
}

Working GetValueInRedis:

@Override
public <T> Mono<T> getValue(String key, Class<T> clazz) {
        return reactiveValueOps.get(key)
            .flatMap(val -> Mono.justOrEmpty(objectMapper.convertValue(val, clazz)));
}

Error version of Get Value:

@Override
public <T> Mono<T> getValue(String key, Class<T> clazz) {
    return reactiveValueOps.get(key)
        .flatMap(o -> Mono.justOrEmpty(clazz.cast(o)));
    }

----EDIT----

If we notice the serializer used for Redis(Jackson2JsonRedisSerializer): while saving the object to redis it works fine. But while reading(get) cast fails and objectMappper works. When I am using Jackson2JsonRedis serializer, shouldn't get command return an object which should be castable using Class.cast command itself?

abstractKarshit
  • 1,355
  • 2
  • 16
  • 34

1 Answers1

1

Class.cast and ObjectMapper.convertValue are two totally different mechanisms. Class.cast does not create new object, only returns old reference with new type. Below you can see how Class.cast is implemented:

public T cast(Object obj) {
    if (obj != null && !isInstance(obj))
        throw new ClassCastException(cannotCastMsg(obj));
    return (T) obj;
}

Jackson from other side creates new object from different hierarchy and copy internal structure. For example, can convert Map to POJO and POJO to Map using reflection. But you can not cast reference to Map on reference to POJO.

Summary: only convertValue method from these two really does conversion from one instance to new one and from one type to new one. cast only tries to change reference type to the same object.

See also:

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • If you notice the serializer used for Redis, while saving the object to redis it works fine. But while reading cast fails and object Mappper works. When I am using Jackson2JsonRedis serializer, shouldn't `get` command return an object which should be castable using Class.cast command? – abstractKarshit Mar 09 '19 at 08:51
  • Thanks. I understand why ObjectMapper convertValue works because it tries to create a new object from the passed one. But should by Redis Serializer would have done that thereby making my object castable? Or am I missing something here? – abstractKarshit Mar 09 '19 at 08:58
  • @Karshit, what `reactiveValueOps.get(key)` method returns? Why do we need `flatMap`. I have never used `Redis`, just wanted to explain what is the difference between `Class.cast` and `ObjectMapper.convertValue`. If you think you should not convert anything create new question with `redis` tag and ask why do you need to do this. Right now I do not have to much information about your project and knowledge about `Redis` to give you good answer. – Michał Ziober Mar 09 '19 at 10:35