无法从 IgniteCach 检索对象,抛出 ClassNotFoundException

Cannot retrieve object from IgniteCach, throws ClassNotFoundException

我正在尝试将 Ignite 添加到现有的 apache-tomcat 应用程序中,但我 运行 遇到了一个问题,试图检索我之前插入到 IgniteCache 中的数据。

下面是相关代码的模型。

public static MyClass getInstance(){
    Ignite ig = WSUtil.getIgnite();
    IgniteCache<Integer,MyClass> myCache = ig.getOrCreateCache("MyClass");
    MyClass instance = myCache.get( 0 );
    if(instance == null) {
        try{
            instance =  //IO opperations to create instance 
            myCache.put(0, instance);
        }catch(Exception e) {
            log.error("\tMessage: "+e.getMessage());
            throw e;
        }finally {
            //close IO
        }
        
    }
    return instance; 
}

第一次调用该方法成功创建并存储实例变量,第二次调用myCache.get( 0 )时出现如下错误:

javax.cache.CacheException: class org.apache.ignite.IgniteCheckedException: com.xxxx.services.MyClass
        at com.xxxx.services.misc.impl.yyyy.getInstance(yyyy.java:84)
        at com.xxxx.services.misc.impl.zzzz.getProductName(zzzz.java:324)
        at com.xxxx.services.misc.impl.cccc.getProductName(cccc.java:92)
        at com.xxxx.services.misc.impl.cccc.getProductInfo(cccc.java:752)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at com.xxxx.prime.aop.MethodCachingInterceptor.invoke(MethodCachingInterceptor.java:56)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy52.getProductInfo(Unknown Source)
        at com.xxxx.ws.ProductInfoWS.invoke(ProductInfoWS.java:60)
        at com.xxxx.ws.ProductInfoWS.invoke(ProductInfoWS.java:25)
        at com.sun.xml.ws.api.server.InstanceResolver.invokeProvider(InstanceResolver.java:256)
        at com.sun.xml.ws.server.InvokerTube.invokeProvider(InvokerTube.java:156)
        at com.sun.xml.ws.server.provider.SyncProviderInvokerTube.processRequest(SyncProviderInvokerTube.java:78)
        at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595)
        at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:554)
        at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:539)
        at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:436)
        at com.sun.xml.ws.server.WSEndpointImpl.process(WSEndpointImpl.java:243)
        at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:444)
        at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:244)
        at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:135)
        at com.sun.xml.ws.transport.http.servlet.WSServletDelegate.doGet(WSServletDelegate.java:129)
        at com.sun.xml.ws.transport.http.servlet.WSServlet.doGet(WSServlet.java:82)
        at java.lang.Thread.run(Thread.java:748)
Caused by: class org.apache.ignite.IgniteCheckedException: com.xxxx.services.MyClass
        ... 60 more
Caused by: class org.apache.ignite.binary.BinaryInvalidTypeException: com.xxxx.services.MyClass
        ... 1 more
Caused by: java.lang.ClassNotFoundException: com.xxxx.services.MyClass
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        ... 29 more

我已经尝试在我的工作站上使用一个简单的 Person 对象 运行 Ignite 服务器来做一些类似的事情,没有任何问题。

public static void main (String[] args) throws IgniteException{
        //preparing igniteconfig
        IgniteConfiguration cfg = new IgniteConfiguration();
        cfg.setClientMode(true);
        cfg.setPeerClassLoadingEnabled(true);
        TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder();
        ipFinder.setAddresses(Collections.singletonList("127.0.0.1:47500..47509"));
        cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(ipFinder));
        Ignite ignite = Ignition.start(cfg);
        
        IgniteCache <Integer, Person> personCache = ignite.getOrCreateCache("personCache");
        Person p = new Person("Billy","Jean");
        personCache.put(0, p);
        
        Person p2 = personCache.get(0);
        
        System.out.println("p: " + p.toString());
        System.out.println("p2: " + p2.toString());
        
        System.out.println(">> task exectued, check output");
        ignite.close();
}

Ignite 和您的代码很可能是从两个不同的类加载器加载的(正如您所指出的),例如,Apache Ignite 可能是从公共库目录加载的,而用户代码可能是从特定的类加载器加载的网络应用程序目录。在这种情况下,Apache Ignite 可能看不到您的库。

您可以尝试将 IgniteConfiguration.classLoader 属性 设置为例如getClass().getClassLoader() 在启动 Ignite 节点之前。