IGNITE-9023 LinkageError or ClassNotFoundException should not be swollen by GridDeploymentCommunication during processing deployment request - Fixes #5472.
Signed-off-by: Dmitriy Govorukhin <dmitriy.govoruk...@gmail.com> Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ee5a8f32 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ee5a8f32 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ee5a8f32 Branch: refs/heads/ignite-10044 Commit: ee5a8f321ebef44e34fb8074944a84872d932fea Parents: 929fbb5 Author: Vyacheslav Daradur <daradu...@gmail.com> Authored: Wed Dec 5 13:11:17 2018 +0300 Committer: Dmitriy Govorukhin <dmitriy.govoruk...@gmail.com> Committed: Wed Dec 5 13:11:17 2018 +0300 ---------------------------------------------------------------------- .../deployment/GridDeploymentCommunication.java | 10 +- ...mentRequestOfUnknownClassProcessingTest.java | 151 +++++++++++++++++++ .../testsuites/IgniteKernalSelfTestSuite.java | 2 + 3 files changed, 159 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/ee5a8f32/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentCommunication.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentCommunication.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentCommunication.java index fdbe9b9..d79346d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentCommunication.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentCommunication.java @@ -204,9 +204,9 @@ class GridDeploymentCommunication { // since it was already performed before (and was successful). if (!(ldr instanceof GridDeploymentClassLoader)) { // First check for @GridNotPeerDeployable annotation. - try { - String clsName = req.resourceName().replace('/', '.'); + String clsName = req.resourceName().replace('/', '.'); + try { int idx = clsName.indexOf(".class"); if (idx >= 0) @@ -228,8 +228,10 @@ class GridDeploymentCommunication { return; } } - catch (ClassNotFoundException ignore) { - // Safely ignore it here - resource wasn't a class name. + catch (LinkageError | ClassNotFoundException e) { + U.warn(log, "Failed to resolve class: " + clsName, e); + // Defined errors can be safely ignored here, because of resource which is able to be not a class name. + // Unsuccessful response will be sent below if the resource failed to be loaded. } } http://git-wip-us.apache.org/repos/asf/ignite/blob/ee5a8f32/modules/core/src/test/java/org/apache/ignite/internal/managers/deployment/DeploymentRequestOfUnknownClassProcessingTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/managers/deployment/DeploymentRequestOfUnknownClassProcessingTest.java b/modules/core/src/test/java/org/apache/ignite/internal/managers/deployment/DeploymentRequestOfUnknownClassProcessingTest.java new file mode 100644 index 0000000..f1f080b --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/managers/deployment/DeploymentRequestOfUnknownClassProcessingTest.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.managers.deployment; + +import java.net.URL; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.managers.communication.GridIoPolicy; +import org.apache.ignite.internal.managers.communication.GridMessageListener; +import org.apache.ignite.internal.util.future.GridFutureAdapter; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; +import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; +import org.apache.ignite.testframework.GridTestExternalClassLoader; +import org.apache.ignite.testframework.ListeningTestLogger; +import org.apache.ignite.testframework.LogListener; +import org.apache.ignite.testframework.config.GridTestProperties; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +import static org.apache.ignite.internal.GridTopic.TOPIC_CLASSLOAD; + +/** + * Tests the processing of deployment request with an attempt to load a class with an unknown class name. + */ +public class DeploymentRequestOfUnknownClassProcessingTest extends GridCommonAbstractTest { + /** */ + private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); + + /** */ + private static final String TEST_TOPIC_NAME = "TEST_TOPIC_NAME"; + + /** */ + private static final String UNKNOWN_CLASS_NAME = "unknown.UnknownClassName"; + + /** */ + private final ListeningTestLogger remNodeLog = new ListeningTestLogger(false, log); + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); + + cfg.setPeerClassLoadingEnabled(true); + + TcpDiscoverySpi discoSpi = new TcpDiscoverySpi(); + + discoSpi.setIpFinder(IP_FINDER); + + cfg.setDiscoverySpi(discoSpi); + + return cfg; + } + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + super.beforeTest(); + + startGrid(getConfiguration(getTestIgniteInstanceName(0))); + + IgniteConfiguration cfg = getConfiguration(getTestIgniteInstanceName(1)); + + cfg.setGridLogger(remNodeLog); + + startGrid(cfg); + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + super.afterTest(); + + stopAllGrids(); + } + + /** + * @throws Exception If failed. + */ + public void testResponseReceivingOnDeploymentRequestOfUnknownClass() throws Exception { + IgniteEx locNode = grid(0); + IgniteEx remNode = grid(1); + + // Register deployment on remote node for attemt to load class on request receiving + GridTestExternalClassLoader ldr = new GridTestExternalClassLoader(new URL[] { + new URL(GridTestProperties.getProperty("p2p.uri.cls")) + }); + + Class task = ldr.loadClass("org.apache.ignite.tests.p2p.P2PTestTaskExternalPath1"); + + GridDeployment locDep = remNode.context().deploy().deploy(task, task.getClassLoader()); + + final GridFutureAdapter<Void> testResultFut = new GridFutureAdapter<>(); + + final LogListener remNodeLogLsnr = LogListener + .matches(s -> s.startsWith("Failed to resolve class: " + UNKNOWN_CLASS_NAME)).build(); + + remNodeLog.registerListener(remNodeLogLsnr); + + locNode.context().io().addMessageListener(TEST_TOPIC_NAME, new GridMessageListener() { + @Override public void onMessage(UUID nodeId, Object msg, byte plc) { + try { + assertTrue(msg instanceof GridDeploymentResponse); + + GridDeploymentResponse resp = (GridDeploymentResponse)msg; + + assertFalse("Unexpected response result, success=" + resp.success(), resp.success()); + + String errMsg = resp.errorMessage(); + + assertNotNull("Response should contain an error message.", errMsg); + + assertTrue("Response contains unexpected error message, errorMessage=" + errMsg, + errMsg.startsWith("Requested resource not found (ignoring locally): " + UNKNOWN_CLASS_NAME)); + + testResultFut.onDone(); + } + catch (Error e) { + testResultFut.onDone(e); + } + } + }); + + GridDeploymentRequest req = new GridDeploymentRequest(TEST_TOPIC_NAME, locDep.classLoaderId(), + UNKNOWN_CLASS_NAME, false); + + req.responseTopicBytes(U.marshal(locNode.context(), req.responseTopic())); + + locNode.context().io().sendToGridTopic(remNode.localNode(), TOPIC_CLASSLOAD, req, GridIoPolicy.P2P_POOL); + + // Сhecks that the expected response has been received. + testResultFut.get(5_000, TimeUnit.MILLISECONDS); + + // Checks that error has been logged on remote node. + assertTrue(remNodeLogLsnr.check()); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/ee5a8f32/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java index ab2306e..7e0148d 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java @@ -42,6 +42,7 @@ import org.apache.ignite.internal.IgniteUpdateNotifierPerClusterSettingSelfTest; import org.apache.ignite.internal.LongJVMPauseDetectorTest; import org.apache.ignite.internal.managers.GridManagerStopSelfTest; import org.apache.ignite.internal.managers.communication.GridCommunicationSendMessageSelfTest; +import org.apache.ignite.internal.managers.deployment.DeploymentRequestOfUnknownClassProcessingTest; import org.apache.ignite.internal.managers.deployment.GridDeploymentManagerStopSelfTest; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManagerAliveCacheSelfTest; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManagerAttributesSelfTest; @@ -137,6 +138,7 @@ public class IgniteKernalSelfTestSuite extends TestSuite { suite.addTestSuite(IgniteConnectionConcurrentReserveAndRemoveTest.class); suite.addTestSuite(LongJVMPauseDetectorTest.class); suite.addTestSuite(ClusterMetricsSelfTest.class); + suite.addTestSuite(DeploymentRequestOfUnknownClassProcessingTest.class); // Managed Services. suite.addTestSuite(GridServiceProcessorSingleNodeSelfTest.class);