java.lang.ClassNotFoundException для загрузчика, настроенного на уровне сервера в hazelcast

#hazelcast #hazelcast-imap

#hazelcast #hazelcast-imap

Вопрос:

Я использую многоузловой кластер hazelcast (версия 3.11). Мой вариант использования заключается в том, что во время запуска hazelcast я хочу, чтобы каждый участник загружал данные в Imap. Я настроил конфигурацию хранилища карт в hazelcast.xml для каждого узла.

Я добавил конфигурацию хранилища карт в hazelcast.xml . Этот файл помещается в папку bin каждого узла hazelcast.

hazelcast.xml конфигурация для каждого узла:

 <?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>
 

Код для class OnboardingMapLoader является частью файла jar, я добавил этот файл jar в папку user-lib узла hazelcast, чтобы этот класс был доступен для каждого узла для загрузки данных. Этот файл jar доступен для каждого узла в кластере.

Теперь, когда java-клиент hazelcast подключается к кластеру hazelcast и пытается извлечь данные из распределенного IMap, я получаю исключение ниже:

 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:

 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:

   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 resu<
        }

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

    }
 

Пожалуйста, помогите решить исключение class not found, возникающее в клиентском коде.

Ответ №1:

Вы это проверили OnboardingMapLoader.class действительно ли находится в файле jar, расположенном в каталоге ./user-lib?

Комментарии:

1. Да, класс OnboardingMapLoader и все связанные с ним классы, на которые ссылается OnboardingMapLoader и сторонние jar, объединены в один файл jar.

2. Приношу свои извинения за задержку. Есть пара причин, которые могут быть причиной этого. 1) OnboardingMapLoader.class отсутствует в файле jar. Вы можете убедиться в этом, выполнив команду из командной строки: jar -tvf jarname.jar . 2) Класс не загружается из-за проблем с зависимостями. Возможно, банки mongo или bson? 3) Наконец, можете ли вы также предоставить результат журналов консоли? Более конкретно, мы повторяем результирующий ПУТЬ к классу. Если вы можете зафиксировать это и убедиться, что путь к каталогу user-lib указан правильно.

Ответ №2:

Это исключение передается с сервера на ваш клиент, поэтому сначала вы должны просмотреть журналы на стороне сервера. Похоже, что класс либо вообще не был найден, либо сервер не смог его загрузить. Существует вероятность, что вы увидите более раннее исключение или исключение, вызвавшее ваше исключение.

Если вы ничего не видите, и у вас есть фрагмент кода Java на стороне кластера, попробуйте создать экземпляр OnboardingMapLoader самостоятельно (новая загрузка …) и посмотрите, не получите ли вы такое же исключение.

Кроме того, если вы настраиваете HazelcastInstance программно, вы можете принудительно загрузить карту, вызвав hzInstance.GetMap на сервере, так что вам не нужно ничего делать в вашем клиенте (хотя вы должны использовать initialLoadMode для НЕТЕРПЕЛИВОГО).