Search code examples
javahazelcastpredicate

Hazelcast Predicate/ SQL query class not found


I am getting class not found exception for SQL query and Predicate search and can't figure out why.

Exception:

Method threw 'com.hazelcast.nio.serialization.HazelcastSerializationException' exception. java.lang.ClassNotFoundException: com.mypackage.TestValue

Oct 01, 2021 10:57:14 AM com.hazelcast.map.impl.query.QueryPartitionOperation
SEVERE: [192.168.99.1]:5701 [nifi] [4.2.1] java.lang.ClassNotFoundException: com.mypackage.TestValue
com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: com.mypackage.TestValue
        at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:90)
        at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:79)
        at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:44)
        at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:208)
        at com.hazelcast.query.impl.CachedQueryEntry.getValue(CachedQueryEntry.java:98)
        at com.hazelcast.query.impl.CachedQueryEntry.getTargetObject(CachedQueryEntry.java:185)
        at com.hazelcast.query.impl.QueryableEntry.extractAttributeValue(QueryableEntry.java:108)
        at com.hazelcast.query.impl.QueryableEntry.getAttributeValue(QueryableEntry.java:62)
        at com.hazelcast.query.impl.predicates.AbstractPredicate.readAttributeValue(AbstractPredicate.java:145)
        at com.hazelcast.query.impl.predicates.AbstractPredicate.apply(AbstractPredicate.java:62)
        at com.hazelcast.query.impl.predicates.AndPredicate.apply(AndPredicate.java:136)
        at com.hazelcast.map.impl.query.PartitionScanRunner$1.accept(PartitionScanRunner.java:104)
        at com.hazelcast.map.impl.query.PartitionScanRunner$1.accept(PartitionScanRunner.java:89)
        at com.hazelcast.map.impl.recordstore.DefaultRecordStore.forEach(DefaultRecordStore.java:278)
        at com.hazelcast.map.impl.recordstore.DefaultRecordStore.forEach(DefaultRecordStore.java:261)
        at com.hazelcast.map.impl.recordstore.DefaultRecordStore.forEachAfterLoad(DefaultRecordStore.java:291)
        at com.hazelcast.map.impl.query.PartitionScanRunner.run(PartitionScanRunner.java:89)
        at com.hazelcast.map.impl.query.CallerRunsPartitionScanExecutor.execute(CallerRunsPartitionScanExecutor.java:43)
        at com.hazelcast.map.impl.query.QueryRunner.runPartitionIndexOrPartitionScanQueryOnGivenOwnedPartition(QueryRunner.java:236)
        at com.hazelcast.map.impl.query.QueryPartitionOperation.runInternal(QueryPartitionOperation.java:46)
        at com.hazelcast.map.impl.operation.MapOperation.run(MapOperation.java:115)
        at com.hazelcast.spi.impl.operationservice.Operation.call(Operation.java:189)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.call(OperationRunnerImpl.java:272)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:248)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:213)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:175)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:139)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.executeRun(OperationThread.java:123)
        at com.hazelcast.internal.util.executor.HazelcastManagedThread.run(HazelcastManagedThread.java:102)
Caused by: java.lang.ClassNotFoundException: com.mypackage.TestValue
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
        at com.hazelcast.internal.nio.ClassLoaderUtil.tryLoadClass(ClassLoaderUtil.java:289)
        at com.hazelcast.internal.nio.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:249)
        at com.hazelcast.internal.nio.IOUtil$ClassLoaderAwareObjectInputStream.resolveClass(IOUtil.java:910)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1984)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1848)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2158)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1665)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:501)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:459)
        at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:86)
        ... 28 more

com.mypackage.HazelcastService:

Collection<HazelcastInstance> instances = HazelcastClient.getAllHazelcastClients();
Optional<HazelcastInstance> instance = instances.stream().findAny();
if (!instance.isPresent()) return;

IMap<String, TestValue> cacheMap = instance.get().getMap("test");
cacheMap.put("1", new TestValue(1, 1L));
cacheMap.put("2", new TestValue(2, 2L));
cacheMap.put("5", new TestValue(5, 5L));
cacheMap.put("9", new TestValue(9, 9L));

TestValue tv = cacheMap.get("1"); // works    
Collection<TestValue> values = cacheMap.values(); // works

Predicate<String, TestValue> gt = Predicates.greaterThan("testInt", 3);
Predicate<String, TestValue> lt = Predicates.lessThan("testInt", 7);
Predicate<String, TestValue> predicate = Predicates.and(gt, lt);
Collection<TestValue> testValues = cacheMap.values(predicate); // fails

SqlRow row = instance.get().getSql().execute("SELECT this FROM test WHERE testInt = 1").iterator().next(); // fails with whatever query I try

com.mypackage.TestValue class is simple pojo

public class TestValue implements Serializable {
    private static final long serialVersionUID = 333333L;
    private Integer testInt;
    private Long testLong;

    public TestValue(Integer testInt, Long testLong) {
        this.testInt = testInt;
        this.testLong = testLong;
    }

    public TestValue() {
    }

    public Integer getTestInt() {
        return testInt;
    }

    public Long getTestLong() {
        return testLong;
    }

    public void setTestInt(Integer testInt) {
        this.testInt = testInt;
    }

    public void setTestLong(Long testLong) {
        this.testLong = testLong;
    }
}

This is just local env, everything running on my machine, single Hazelcast instance. My code matches examples in official documentation.

Hazelcast version: 4.2.1

Java version: 1.8


Solution

  • You code reads as:

    Collection<HazelcastInstance> instances = HazelcastClient.getAllHazelcastClients();
    Optional<HazelcastInstance> instance = instances.stream().findAny();
    

    It means that the Hazelcast instance is a client. Hence, you must have a Hazelcast node running as a separate process.

    The problem is that your class is known on the client side, not on the server side. Since your query runs server-side, you need to put your class on the server classpath, for example, when you start it, or serialize your class in JSON so it can be queried in an agnostic way.