1
votes

I am using multi node hazelcast (3.11 version) cluster. My use case is, during hazelcast startup, I want each member to load the data in the Imap. I have configured map store configuration in hazelcast.xml for each node.

I have added mapstore configuration in hazelcast.xml. This file is placed inside bin folder of each hazelcast node.

hazelcast.xml configuration for each node:

<?xml version="1.0" encoding="UTF-8"?>
<hazelcast
        xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.3.xsd"
        xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <properties>
        <property name="hazelcast.initial.min.cluster.size">2</property>
    </properties>

<management-center enabled="true">
    http://localhost:8080/hazelcast-mancenter
</management-center>

    <network>
        <port auto-increment="true">5701</port>
        <join>
            <multicast enabled="false">
                <multicast-group>224.2.2.3</multicast-group>
                <multicast-port>2434</multicast-port>
                <multicast-timeout-seconds>1</multicast-timeout-seconds>
            </multicast>
            <tcp-ip enabled="true" connection-timeout-seconds="3">
                <member>127.0.0.1:5701</member>
                <member>127.0.0.1:5702</member>
            </tcp-ip>
        </join>
        <interfaces enabled="true">
            <interface>127.0.0.1</interface>
        </interfaces>
    </network>


<map name="testmap">
    <backup-count>1</backup-count>
    <time-to-live-seconds>0</time-to-live-seconds>
    <max-idle-seconds>0</max-idle-seconds>

    <map-store enabled="true">
        <class-name>com.bm.mapstore.OnboardingMapLoader</class-name>
        <write-delay-seconds>0</write-delay-seconds>
    </map-store>
</map>

</hazelcast>

Code for class OnboardingMapLoader is part of a jar file, I have added that jar file in user-lib folder of hazelcast node, so that class is available to each node to load the data. This jar file is available to each node in the cluster.

Now when hazelcast java client, connects to hazelcast cluster and try to fetch the data from distributed IMap, I get below exception:

Caused by: java.lang.ClassNotFoundException: com.bm.mapstore.OnboardingMapLoader
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at com.hazelcast.nio.ClassLoaderUtil.tryLoadClass(ClassLoaderUtil.java:288)
    at com.hazelcast.nio.ClassLoaderUtil.newInstance0(ClassLoaderUtil.java:212)
    at com.hazelcast.nio.ClassLoaderUtil.newInstance(ClassLoaderUtil.java:193)
    at com.hazelcast.map.impl.mapstore.StoreConstructor.getStoreFromClassOrNull(StoreConstructor.java:81)
    at com.hazelcast.map.impl.mapstore.StoreConstructor.createStore(StoreConstructor.java:46)
    at com.hazelcast.map.impl.mapstore.BasicMapStoreContext.create(BasicMapStoreContext.java:124)
    at com.hazelcast.map.impl.mapstore.MapStoreContextFactory.createMapStoreContext(MapStoreContextFactory.java:48)
    at com.hazelcast.map.impl.MapContainer.<init>(MapContainer.java:155)
    at com.hazelcast.map.impl.MapServiceContextImpl$1.createNew(MapServiceContextImpl.java:194)
    at com.hazelcast.map.impl.MapServiceContextImpl$1.createNew(MapServiceContextImpl.java:190)
    at com.hazelcast.util.ConcurrencyUtil.getOrPutSynchronized(ConcurrencyUtil.java:93)
    at com.hazelcast.map.impl.MapServiceContextImpl.getMapContainer(MapServiceContextImpl.java:278)
    at com.hazelcast.map.impl.operation.MapOperationProviders.getOperationProvider(MapOperationProviders.java:47)
    at com.hazelcast.map.impl.MapServiceContextImpl.getMapOperationProvider(MapServiceContextImpl.java:747)
    at com.hazelcast.client.impl.protocol.task.map.AbstractMapPartitionMessageTask.getMapOperationProvider(AbstractMapPartitionMessageTask.java:36)
    at com.hazelcast.client.impl.protocol.task.map.MapGetMessageTask.prepareOperation(MapGetMessageTask.java:54)
    at com.hazelcast.client.impl.protocol.task.AbstractPartitionMessageTask.processMessage(AbstractPartitionMessageTask.java:62)
    at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.initializeAndProcessMessage(AbstractMessageTask.java:123)
    at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.doRun(AbstractMessageTask.java:111)
    at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.run(AbstractMessageTask.java:101)
    at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:161)
    at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:159)
    at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:127)
    at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.run(OperationThread.java:110)
Apr 19, 2019 1:51:08 PM com.hazelcast.client.connection.ClientConnectionManager

Hazelcast java client code:

import java.util.Map;

import com.hazelcast.client.HazelcastClient;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.core.HazelcastInstance;

public class AppTest {

    public static void main(String[] args) {

        ClientConfig config = new ClientConfig();
        String[] addresses = { "localhost:5701", "localhost:5702" };
        config.getNetworkConfig().addAddress(addresses);

        HazelcastInstance hazelcastInstance = HazelcastClient.newHazelcastClient(config);

          Map<String, Onboarding>  imap = hazelcastInstance
                .getMap("testmap");
        System.out.println(imap.get("6001"));

        hazelcastInstance.shutdown();
    }

}

Maploader source code:

  package com.bm.mapstore;

    import java.io.Serializable;
    import java.math.BigInteger;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;

    import org.bson.Document;
    import org.bson.codecs.configuration.CodecProvider;
    import org.bson.codecs.configuration.CodecRegistries;
    import org.bson.codecs.configuration.CodecRegistry;
    import org.bson.codecs.pojo.Convention;
    import org.bson.codecs.pojo.Conventions;
    import org.bson.codecs.pojo.PojoCodecProvider;

    import com.bm.entity.Onboarding;
    import com.hazelcast.core.MapLoader;
    import com.mongodb.BasicDBObject;
    import com.mongodb.MongoClient;
    import com.mongodb.MongoClientURI;
    import com.mongodb.client.FindIterable;
    import com.mongodb.client.MongoCollection;
    import com.mongodb.client.MongoCursor;
    import com.mongodb.client.MongoDatabase;

    public class OnboardingMapLoader implements MapLoader<String, Onboarding>, Serializable {
        private static final long serialVersionUID = 1L;
        private MongoClient mongoClient;
        private MongoDatabase db;
        private MongoCollection collection;
        private String uri = "mongodb://localhost:27017/demodb";

        public MongoClient getMongoClient() {
            return this.mongoClient;
        }

        public void setMongoClient(MongoClient mongoClient) {
            this.mongoClient = mongoClient;
        }

        public MongoDatabase getDb() {
            return this.db;
        }

        public void setDb(MongoDatabase db) {
            this.db = db;
        }

        public OnboardingMapLoader() {
            CodecRegistry pojoCodecRegistry = CodecRegistries
                    .fromRegistries(new CodecRegistry[] { MongoClient.getDefaultCodecRegistry(),
                            CodecRegistries.fromProviders(new CodecProvider[] { PojoCodecProvider.builder()
                                    .conventions(Arrays.asList(new Convention[] { Conventions.ANNOTATION_CONVENTION }))
                                    .automatic(true).build() }) });

            this.mongoClient = new MongoClient(new MongoClientURI(uri));
            this.db = this.mongoClient.getDatabase("dbvadd1").withCodecRegistry(pojoCodecRegistry);
            this.collection = this.db.getCollection("onboarding");
        }

        @Override
        public Onboarding load(String key) {
            System.out.println("---------------inside load key is -----------------" + key);
            BasicDBObject searchQuery = new BasicDBObject();
            searchQuery.put("_id", key);
            Document doc = (Document) collection.find(searchQuery).first();
            Onboarding onboarding = new Onboarding();
            onboarding.setSvcInvkrId(doc.getString("_id"));
            onboarding.setAllowMultiple(doc.getString("allowMultiple"));
            onboarding.setBid(new BigInteger(doc.getString("bid")));
            System.out.println("---------------inside load onboarding is -----------------" + onboarding);
            return onboarding;
        }

        @Override
        public Map<String, Onboarding> loadAll(Collection<String> keys) {
            Map<String, Onboarding> result = new HashMap();
            FindIterable<Document> documents = this.collection.find();
            for (MongoCursor localMongoCursor = documents.iterator(); localMongoCursor.hasNext();) {
                Document doc = (Document) localMongoCursor.next();
                Onboarding onboarding = new Onboarding();
                onboarding.setSvcInvkrId(doc.getString("_id"));
                onboarding.setAllowMultiple(doc.getString("allowMultiple"));
                onboarding.setBid(new BigInteger(doc.getString("bid")));
                result.put(onboarding.getSvcInvkrId(), onboarding);
            }
            System.out.println("---------------inside loadAll result is-----------------" + result);
            return result;
        }

        public Set<String> loadAllKeys() {
            return new HashSet<String>(Arrays.asList("6001", "6002"));
        }

    }

Please help to solve the class not found exception coming at client code.

2

2 Answers

0
votes

Have you verified that OnboardingMapLoader.class is indeed in a jar file located in ./user-lib directory?

0
votes

This exception is propagated from the server to your client, so you first you should see the logs on the server side. It seems like the class either couldn't be found at all or the server was unable to load it. There is a chance you will see an earlier exception or the exception that caused your exception.

If you see nothing and you have a piece of java code on your cluster side, try instantiating the OnboardingMapLoader yourself (new Onboarding...) and see if you don't get the same exception.

Also, if you configure HazelcastInstance programmaticaly, you can force map loading by calling hzInstance.getMap on the server, so you don't have to do in in your client (you have to use initialLoadMode to EAGER though).