FasterXML / jackson-modules-java8

Set of support modules for Java 8 datatypes (Optionals, date/time) and features (parameter names)
Apache License 2.0
401 stars 117 forks source link

Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class' #100

Closed ergunp closed 5 years ago

ergunp commented 5 years ago

I am storing my object as json in redis cache using the GenericJackson2JsonRedisSerializer()

But my issue is when I try to update the object within the cache I get the following error

Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'
 at [Source: (byte[])"{"id":"10.36.55.1","protocolRestriction":false}"; line: 1, column: 47]

I have already tried adding the following to my object.

@JsonTypeInfo(
        use = JsonTypeInfo.Id.MINIMAL_CLASS,
        include = JsonTypeInfo.As.PROPERTY,
        property = "@class")

but with no luck.

Here is my config,

 @Bean
    fun redisCacheManager(objectMapper: ObjectMapper): CacheManager {
        objectMapper.registerModule(KotlinModule())
        objectMapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, "@class")

        val jsonSerializer = RedisSerializationContext.SerializationPair
                .fromSerializer(GenericJackson2JsonRedisSerializer(objectMapper))

        return RedisCacheManager.RedisCacheManagerBuilder
                .fromConnectionFactory(jedisConnectionFactory())
                .cacheDefaults(
                        RedisCacheConfiguration.defaultCacheConfig()
                                .entryTtl(Duration.ofMinutes(cacheTimeToLive!!))
                                .serializeValuesWith(jsonSerializer))
                .build()
    }

this is my object

@RedisHash("sessionState", timeToLive = 900) //evict after 15min
data class SessionState(@Id val id:String?,
                        val protocolRestriction: Boolean?): Serializable

Here is how i am updating my object in the cache

   @Caching(put = [CachePut("sessionStateCache", key = "#sessionState.id", unless = "#result == null")],
            evict = [CacheEvict("allSessionStateCache", allEntries = true)])
    override fun updateSessionState(sessionState: SessionState): SessionState {
        return sessionStateRepo.save(sessionState)
    }

Any help would be much appreciated.

gnumilanix commented 5 years ago

@ergunp how were you able to fix this?

ergunp commented 5 years ago

@gnumilanix I used a completely different approach as what was doing initially was wrong.

gnumilanix commented 5 years ago

I am trying to configure RedisCacheManager and having a similar issue with GenericJackson2JsonRedisSerializer. Either the one mentioned above or LinkedHashMap cannot be cast to com.x.y.z. This only happens when using @Cacheable annotation.

Are you able to configure it correctly with cache annotations? Or using RedisTemplate directly. Would you mind sharing your approach?

steimntz commented 4 years ago

I am also facing the same problem. Would you mind sharing your approach? +1

gnumilanix commented 4 years ago

After spending many days trying to find a solution, I had to finally look for an alternative. I don't remember everything but, I will try to summarize.

I use JPA interface projection, which was convenient as it mapped all sub-entities automatically. However, it returns a proxy and not actual implementation. (Which is why I ended up in this spot)

I did try to unwrap the proxy, which did give me the correct type but, I found it way to much hassle to unwrap all sub and nested objects. Which is why GenericJackson2JsonRedisSerializer would always end up setting id as a Proxy for all those sub and nested objects, instead of the actual type.

Since I didn't have to cache all these interfaces anyways, I changed the ones that I had to cache to use Class/DTO based projection instead. Of course, that results in having to map sub-entities manually. But finally, I was able to cache using JdkSerializationRedisSerializer.

I hope some other day, someone can share a better solution to this problem.