Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.lang.ClassCastException: DTOObject cannot be cast to DTOObject

I am facing a weird issue in my application which runs on Spring Boot 1.4.0M3 which is using Spring cache implementation where provider is Redis where I receive classCastException that same object cannot be casted

I am using Mongodb as database and I have User Object which contains List of Roles object loaded lazily and Roles internally contains Permissions Object like below

@Document
@Data
public class User implements Serializable{
private String passwordResetToken;

private boolean enabled = false;

@DBRef(lazy= true)
private List<Role> roleList;
}

My Role DTO is as below

@Data
@Document
public class Role implements Serializable{
   private String roleName;
    private String description;
    @DBRef(lazy= true)
    private List<Permission> permissions;
}

Now in my spring MVC while loading all roles I am calling all permissions and since this is repetitive operation I thought of caching the result and using redis and while loading the roles value I receive below exception.

raised java.lang.ClassCastException: com.learning.securedapp.domain.Permission cannot be cast to com.learning.securedapp.domain.Permission

Help me to overcome this error.

I am attaching the source code to my project and I receive error at line 91 of RoleController.java

To Replicate in your local environment login to application and click on permissions menu and then roles menu, In Roles menu now click on any edit icon.you will receive above error.

like image 343
rajadilipkolli Avatar asked Jun 22 '16 19:06

rajadilipkolli


People also ask

How do I resolve Java Lang ClassCastException?

How to handle ClassCastException. To prevent the ClassCastException exception, one should be careful when casting objects to a specific class or interface and ensure that the target type is a child of the source type, and that the actual object is an instance of that type.

What causes Java Lang ClassCastException?

Some of the most common sources of ClassCastException in Java are: Using collections like HashMap, ArrayList and HashTable which do not use Java Generics. Using methods which were written on interfaces prior to Java 5 that use polymorphism. Not using type-safety when casting objects in Java.

What is Java Lang ClassCastException?

Class ClassCastExceptionThrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance. For example, the following code generates a ClassCastException : Object x = new Integer(0); System. out. println((String)x);

What is ClassCastException in Java with example?

ClassCast Exception in Java is one of the unchecked exceptions that occur when we try to convert one class type object into another class type. ClassCast Exception is thrown when we try to cast an object of the parent class to the child class object.


2 Answers

When you use DevTools with caching, you need to be aware of this limitation.

When the object is serialized into the cache, the application class loader is C1. Then after you change some code/configuration, devtools automatically restart the context and creates a new classloader (C2). When you hit that cache method, the cache abstraction finds an entry in the cache and it deserializes it from the store. If the cache library doesn't take the context classloader into account, that object will have the wrong classloader attached to it (which explains that weird exception A cannot be cast to A).

TL;DR do not serialize classes with devtools if the cache library doesn't use the context classloader. Or put your cache library in the application classloader:

restart.include.yourcache=/my-cache-lib-[\\w-]+\.jar
like image 152
Stephane Nicoll Avatar answered Oct 13 '22 11:10

Stephane Nicoll


This worked for me , DevTools and Redis both are working. We need to pass classLoader when creating JdkSerializationRedisSerializer and it should work

 JdkSerializationRedisSerializer redisSerializer = new JdkSerializationRedisSerializer(getClass().getClassLoader());

So my RedisCacheConfig is:

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport implements CachingConfigurer {


............................
............................


    @Bean
public RedisCacheManager redisCacheManager(LettuceConnectionFactory lettuceConnectionFactory) {
    JdkSerializationRedisSerializer redisSerializer = new JdkSerializationRedisSerializer(getClass().getClassLoader());

    RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
            .disableCachingNullValues()
            .entryTtl(Duration.ofHours(redisDataTTL))
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer));

    redisCacheConfiguration.usePrefix();

    RedisCacheManager redisCacheManager = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(lettuceConnectionFactory)
            .cacheDefaults(redisCacheConfiguration)
            .build();

    redisCacheManager.setTransactionAware(true);
    return redisCacheManager;
}

............................
............................


}

Check this spring boot issue: https://github.com/spring-projects/spring-boot/issues/9444

like image 34
Mukesh M Avatar answered Oct 13 '22 12:10

Mukesh M