I’m trying to deploy a new application in which we use Ignite as
compute grid and send them broadcast messages from different client
nodes. The problem is that we are storing a helper class in the
workers/servers localMap while using SHARED deployment mode with the
peer class loader. According to the documentation: “classes from
different master nodes with the same user version will share the same
class loader on worker nodes” but in reality every master node has a
different classloader in the worker node. I have a small minimal
example that reproduces the issue.
public class Client {
public static void main(String []args) throws InterruptedException {
IgniteConfiguration config = new IgniteConfiguration();
IgniteDiscoverySpi discoverySpi = new TcpDiscoverySpi()
.setIpFinder(new
TcpDiscoveryVmIpFinder().setAddresses(List.of(“localhost:47500..47509”)))
.setJoinTimeout(600_000);
config.setPeerClassLoadingEnabled(true);
config.setDiscoverySpi(discoverySpi);
config.setDeploymentMode(DeploymentMode.SHARED);
config.setClientMode(true);
Ignite ignite = Ignition.start(config);
for (int i = 0; i < 10; i++) {
ignite.compute().broadcast(new LocalMapUser());
Thread.sleep(5_000);
}
Ignition.stopAll(true);
}
public static class LocalMapUser implements IgniteRunnable {
@IgniteInstanceResource
public transient Ignite ignite;
@Override
public void run() {
System.out.println(“ - Before - “);
A a;
try {
a = (A)
ignite.cluster().nodeLocalMap().computeIfAbsent(“a”, k -> new A());
} catch (ClassCastException e) {
System.err.println(“ClassCastException: “ + e.getMessage());
a = new A();
ignite.cluster().nodeLocalMap().put(“a”, a);
}
a.doSomething();
System.out.println(“ - After - “);
}
}
public static class A {
private int cache = 0;
void doSomething() {
cache++;
System.out.println(“Hello World: “ + cache);
}
}
}
public class Server {
public static void main(String []args) {
IgniteConfiguration config = new IgniteConfiguration();
IgniteDiscoverySpi discoverySpi = new TcpDiscoverySpi()
.setIpFinder(new
TcpDiscoveryVmIpFinder().setAddresses(List.of(“localhost:47500..47509”)))
.setJoinTimeout(600_000);
config.setPeerClassLoadingEnabled(true);
config.setDiscoverySpi(discoverySpi);
config.setDeploymentMode(DeploymentMode.SHARED);
config.setClientMode(false);
Ignition.start(config);
}
}
Of course this two classes must be executed from different classpaths
to reproduce the issue. In this example if just one client/master node
runs everything works as expected, but as soon as I have two
client/master nodes running at the same time (with the broadcast
interleaved) the will both start trashing hitting the
ClassCastException in every execution, showing the message:
ClassCastException: class Client$A cannot be cast to class Client$A
(Client$A is in unnamed module of loader
org.apache.ignite.internal.managers.deployment.GridDeploymentClassLoader
@71732d48; Client$A is in unnamed module of loader
org.apache.ignite.internal.managers.deployment.GridDeploymentClassLoader
@2f6ed6ac)
For some reason they have different classloaders. Am I missing something?
Ignite version: 2.7.6
Java version: OpenJDK 11.0.9