Search code examples
springcachingignite

Ignite and Spring with multiple Class Loaders


I have a system with Spring Cache, in it there are multiple Class Loaders. Actually I use ehcache and it works fine:

@Component
public class ObjectRepository extends MongoRepository<Object> {
// -------------------------- OTHER METHODS --------------------------

    @Override
    @Cacheable(value = "object", key = "#p0+#p1.name")
    public Object get(String id, Class<? extends Object> clazz) {
        return super.get(id, clazz);
    }

    @Override
    @CacheEvict(value = "object", key = "#p0+#p1.name")
    public void remove(String id, Class<? extends Object> clazz) {
        super.remove(id, clazz);
    }

    @Override
    @CacheEvict(value = "object", key = "#p0+#p0.class.name")
    public void save(Object object) {
        super.save(object);
    }
}

I'm trying to change to ignite:

@Bean
@SuppressWarnings("unchecked")
public CacheManager cacheManager() {
    SpringCacheManager springCacheManager = new SpringCacheManager();
    IgniteConfiguration igniteConfiguration = new IgniteConfiguration();
    igniteConfiguration.setPeerClassLoadingEnabled(true);
    igniteConfiguration.setIncludeEventTypes(org.apache.ignite.events.EventType.EVTS_TASK_EXECUTION);
    springCacheManager.setConfiguration(igniteConfiguration);
    return springCacheManager;
}   

Because of multiple Class Loaders I'm getting error, when i do objectRepository.get("1", com.test.ClassInClassLoader1.class) works ok but after i do objectRepository.get("2", com.test.ClassInClassLoader2.class) and i get the error:

Caused by: class org.apache.ignite.IgniteCheckedException: Encountered incompatible class loaders for cache [class1=com.test.ClassInClassLoader2, class2=com.test.ClassInClassLoader1]
        at org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager.registerClass(GridCacheDeploymentManager.java:656)
        at org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager.registerClass(GridCacheDeploymentManager.java:601)
        at org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager.registerClass(GridCacheDeploymentManager.java:590)
        at org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager.registerClasses(GridCacheDeploymentManager.java:573)
        at org.apache.ignite.internal.processors.cache.GridCacheUtils.marshal(GridCacheUtils.java:950)
        at org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessorImpl.marshal(IgniteCacheObjectProcessorImpl.java:94)
        at org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl.marshal(CacheObjectPortableProcessorImpl.java:727)
        at org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessorImpl$UserCacheObjectImpl.prepareForCache(IgniteCacheObjectProcessorImpl.java:343)
        ... 186 more

I tryied to use DeploymentMode.ISOLATED and DeploymentMode.PRIVATE but they do not work with igniteConfiguration.setPeerClassLoadingEnabled(true), so I have to register manually all classes and i didn't find how to do it with LocalDeploymentSpi, I tried to use igniteConfiguration.getDeploymentSpi() but it's null and when I create it is like the Ignite ignores the classes in there.


Solution

  • I would not recommend to use peer class loading for the domain model classes. Instead, you should make all your classes available on classpath of all nodes and switch peer class loading off (igniteConfiguration.setPeerClassLoadingEnabled(false)).

    Also note that starting with Ignite 1.5, which is going to be released soon, cache data will be stored in binary format by default, so you will not have to deploy classes on server nodes even if peer class loading is disabled.