Hello again! I have found one work-around, it is not very sound but seems reliable.
Before first invocation of UriDeploymentSpi-deployed Compute Job with, first run a locally-deployed job with same dependency. In this case, ServiceTopologyCallable is called outside of UriDeploymentSpi context, is deployed properly and doesn't cause problems later. Work is underway for proper fix. -- Ilya Kasnacheev 2017-10-29 14:46 GMT+03:00 Dmitriy Ivanov <daiva...@gridfore.com>: > Hi! > In our project we need to deploy custom compute tasks into cluster without > cluster restart and p2p class loading. > I try to use org.apache.ignite.spi.deployment.uri.UriDeploumentSpi for > that purpose, but I have a problem. > > I have simple Ignite Service and Ignite Compute Task which use it throught > @ServiceResource. > This ComputeTask located into .gar file which was deployed via > UriDeploumentSpi. > > If I have service implementation on each node(node singleton service) then > it works great. > But if I deploy service as a cluster singleton then task executes > correctly only on node with this service. > > On other nodes @ServiceResource returns ServiceProxy that throws exception > on service remote method invokation (lambda with service call cannot be > deployed): > > SEVERE: Failed to execute job > [jobId=68a96d76f51-7919c34c-9a48-4068-bcd6-70dad5595e86, > ses=GridJobSessionImpl [ses=GridTaskSessionImpl [taskName=task-one, > dep=GridDeployment [ts=1509275650885, depMode=SHARED, > clsLdr=GridUriDeploymentClassLoader > [urls=[file:/C:/IdeaProjects/dmp_code_deployment/test/out/ > deployment/gg.uri.deployment.tmp/428ec712-e6d0-4eab-97f9- > ce58d7b3e0f5/dirzip_task-one6814855127293591501.gar/]], > clsLdrId=7eb15d76f51-428ec712-e6d0-4eab-97f9-ce58d7b3e0f5, userVer=0, > loc=true, sampleClsName=com.gridfore.tfedyanin.deploy.Task1, > pendingUndeploy=false, undeployed=false, usage=1], > taskClsName=com.gridfore.tfedyanin.deploy.Task1, > sesId=38a96d76f51-7919c34c-9a48-4068-bcd6-70dad5595e86, > startTime=1509275650601, endTime=9223372036854775807, > taskNodeId=7919c34c-9a48-4068-bcd6-70dad5595e86, > clsLdr=GridUriDeploymentClassLoader > [urls=[file:/C:/IdeaProjects/dmp_code_deployment/test/out/ > deployment/gg.uri.deployment.tmp/428ec712-e6d0-4eab-97f9- > ce58d7b3e0f5/dirzip_task-one6814855127293591501.gar/]], closed=false, > cpSpi=null, failSpi=null, loadSpi=null, usage=1, fullSup=false, > internal=false, subjId=7919c34c-9a48-4068-bcd6-70dad5595e86, > mapFut=IgniteFuture [orig=GridFutureAdapter [ignoreInterrupts=false, > state=INIT, res=null, hash=1254296516]], execName=null], > jobId=68a96d76f51-7919c34c-9a48-4068-bcd6-70dad5595e86]] > class org.apache.ignite.IgniteDeploymentException: Failed to auto-deploy > task (was task (re|un)deployed?): class org.apache.ignite.internal. > processors.service.GridServiceProcessor$ServiceTopologyCallable > at org.apache.ignite.internal.util.IgniteUtils$8.apply( > IgniteUtils.java:833) > at org.apache.ignite.internal.util.IgniteUtils$8.apply( > IgniteUtils.java:831) > at org.apache.ignite.internal.util.IgniteUtils. > convertException(IgniteUtils.java:952) > at org.apache.ignite.internal.processors.service. > GridServiceProxy.invokeMethod(GridServiceProxy.java:208) > at org.apache.ignite.internal.processors.service.GridServiceProxy$ > ProxyInvocationHandler.invoke(GridServiceProxy.java:356) > at com.sun.proxy.$Proxy31.println(Unknown Source) > at com.gridfore.tfedyanin.deploy.Task1$MyComputeJobAdapter. > execute(Task1.java:49) > at org.apache.ignite.internal.processors.job.GridJobWorker$ > 2.call(GridJobWorker.java:566) > at org.apache.ignite.internal.util.IgniteUtils. > wrapThreadLoader(IgniteUtils.java:6608) > at org.apache.ignite.internal.processors.job.GridJobWorker. > execute0(GridJobWorker.java:560) > at org.apache.ignite.internal.processors.job.GridJobWorker. > body(GridJobWorker.java:489) > at org.apache.ignite.internal.util.worker.GridWorker.run( > GridWorker.java:110) > at org.apache.ignite.internal.processors.job.GridJobProcessor. > processJobExecuteRequest(GridJobProcessor.java:1181) > at org.apache.ignite.internal.processors.job.GridJobProcessor$ > JobExecutionListener.onMessage(GridJobProcessor.java:1908) > at org.apache.ignite.internal.managers.communication. > GridIoManager.invokeListener(GridIoManager.java:1556) > at org.apache.ignite.internal.managers.communication.GridIoManager. > processRegularMessage0(GridIoManager.java:1184) > at org.apache.ignite.internal.managers.communication. > GridIoManager.access$4200(GridIoManager.java:126) > at org.apache.ignite.internal.managers.communication.GridIoManager$9.run( > GridIoManager.java:1097) > at java.util.concurrent.ThreadPoolExecutor.runWorker( > ThreadPoolExecutor.java:1149) > at java.util.concurrent.ThreadPoolExecutor$Worker.run( > ThreadPoolExecutor.java:624) > at java.lang.Thread.run(Thread.java:748) > Caused by: class org.apache.ignite.internal.IgniteDeploymentCheckedException: > Failed to auto-deploy task (was task (re|un)deployed?): class > org.apache.ignite.internal.processors.service.GridServiceProcessor$ > ServiceTopologyCallable > at org.apache.ignite.internal.processors.task.GridTaskProcessor.startTask( > GridTaskProcessor.java:644) > at org.apache.ignite.internal.processors.task.GridTaskProcessor.execute( > GridTaskProcessor.java:448) > at org.apache.ignite.internal.processors.task.GridTaskProcessor.execute( > GridTaskProcessor.java:428) > at org.apache.ignite.internal.processors.closure.GridClosureProcessor. > callAsyncNoFailover(GridClosureProcessor.java:599) > at org.apache.ignite.internal.processors.service.GridServiceProcessor. > serviceTopology(GridServiceProcessor.java:728) > at org.apache.ignite.internal.processors.service.GridServiceProxy. > randomNodeForService(GridServiceProxy.java:274) > at org.apache.ignite.internal.processors.service.GridServiceProxy. > nodeForService(GridServiceProxy.java:260) > at org.apache.ignite.internal.processors.service. > GridServiceProxy.invokeMethod(GridServiceProxy.java:170) > ... 17 more > > > I found out that this problem is connected with > GridUriDeploymentClassLoader classloader which obtained in > GridClassLoaderCache line 76: > > private static ClassLoader detectClassLoader(Class<?> cls) { > ClassLoader ctxClsLdr = Thread.currentThread().getContextClassLoader(); > > > In code of GridDeploymentManager on line 271 there is an instance check, > but GridUriDeploymentClassLoader is not instance of > GridDeploymentClassLoader. > > if (clsLdr instanceof GridDeploymentClassLoader) { > GridDeploymentInfo ldr = (GridDeploymentInfo)clsLdr; > > Therefore check fails and another branch start execution: > > else > return locStore.explicitDeploy(cls, clsLdr); > > I think that it causes incorrect work of GridTaskProcessor code on line > 641: > > dep = ctx.deploy().deploy(cls, ldr); > > Can you help me with this problem? > Or maybe I should use another solution for code deployment? > > Your sincerely, Dmitry. > > > I create ignite configuration like this: > > IgniteConfiguration cfg = new IgniteConfiguration(); > cfg.setPeerClassLoadingEnabled(false); > UriDeploymentSpi deploymentSpi = new UriDeploymentSpi(); > deploymentSpi.setUriList(getUris()); > deploymentSpi.setTemporaryDirectoryPath("out/deployment"); > cfg.setDeploymentSpi(deploymentSpi); > > > Also I have Ignite Service TestService with one simple method "println": > > @Slf4j > public class TestServiceImpl implements Service, TestService { > private AtomicBoolean interupt = new AtomicBoolean(false); > @Override > public void println(String str) { > log.info(str); > System.err.println(str); > } > @Override > public void cancel(ServiceContext ctx) { > interupt.set(true); > } > @Override > public void init(ServiceContext ctx) throws Exception { > System.err.println("Service deployed"); > } > @Override > public void execute(ServiceContext ctx) throws Exception { > while (!interupt.get()) { > TimeUnit.SECONDS.sleep(10); > String msg = "I'm service and I'm alive"; > log.debug(msg); > System.err.println(msg); > } > } > } > > > And task which executes simple job on each cluster node: > > private static class MyComputeJobAdapter extends ComputeJobAdapter { > @ServiceResource(serviceName = TestService.name, proxyInterface = > TestService.class) > private TestService service; > @Override > public Object execute() throws IgniteException { > int i = 10; > while (i-- > 0) { > System.err.println("Service " + service); > service.println(SameFullQualifiedClass.msg); > try { > TimeUnit.SECONDS.sleep(10); > } catch (InterruptedException e) { > e.printStackTrace(); > } > } > return null; > } > } > > > I deploy TestService as a cluster singleton: > > IgniteServices svcs = ignite.services(ignite.cluster().forServers()); > svcs.deployClusterSingleton(TestService.name, new TestServiceImpl()); > > >