Search code examples
ignite

ClassNotFoundException while deploying new application version (with changed session object) in active Apache Ignite grid


We are currently integrating Apache Ignite in our application to share sessions in a cluster.

At this point we can successfully share sessions between two local tomcat instances, but there's one use case, which is not working so far.

When running the two local instances with the exact same code, it all works great. But when the Ignite logic is integrated in our production cluster, we'll encounter the following use case:

  1. Node 1 and Node 2, runs version 1 of the application
  2. At this point we'd like to deploy version 2 of the application
  3. Tomcat is stopped at Node 1, version 2 is deployed, and at the end of the deployment Tomcat at Node 1 is started again.
  4. We now have Node 1 with version 2 of the code and Node 2, still with version 1
  5. Tomcat is stopped at Node 2, version 2 is deployed, and at the end of the deployment Tomcat at Node 2 is started again.
  6. We now have Node 1 with version 2 of the code and Node 2, with version 2
  7. Deployment is finished

When reproducing this use case locally with two tomcat instances in the same grid, the Ignite web session clustering fails. What I tested, was removing one 'String property' of a class (Profile) which resided in the users session. When starting Node 1 with this changed class, I get the following exception:

Caused by: java.lang.ClassNotFoundException: 
Optimized stream class checksum mismatch 
(is same version of marshalled class present on all nodes?) [expected=4981, actual=-27920, cls=class nl.package.profile.Profile]

This will be a common/regular use case for our deployments. My question is: how to handle this use cases? Are there ways in Ignite to resolve/workaround this kind of issue?


Solution

  • In my understanding your use case perfectly fits for Ignite Binary objects [1]. This feature allows to store objects in class-free format and to modify objects structure in runtime without full cluster restart when a version of an object is changed.

    Your Person class should implement org.apache.ignite.binary.Binarylizable interface that will give you full control on serialization and deserialization logic. With this interface you can even have two nodes in the cluster that use different versions of Person class at both deserialization & serialization time by reading/writing only required fields from/to binary format.

    [1] https://apacheignite.readme.io/docs/binary-marshaller