diff --git a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java index 6e76175c72fd4..06998cc00a32c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java @@ -335,7 +335,7 @@ public CoreMessagesProvider(Marshaller dfltMarsh, Marshaller schemaAwareMarsh, C msgIdx = 5000; // We don't use the code‑generated serializer for CompressedMessage - serialization is highly customized. factory.register(msgIdx++, CompressedMessage::new); - withNoSchema(ErrorMessage.class); + withNoSchemaResolvedClassLoader(ErrorMessage.class); withNoSchema(InetSocketAddressMessage.class); withNoSchema(InetAddressMessage.class); withNoSchema(TcpDiscoveryNode.class); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/ErrorMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/ErrorMessage.java index a147247e1998d..02bb9ec0af99a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/ErrorMessage.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/ErrorMessage.java @@ -55,24 +55,28 @@ public ErrorMessage(@Nullable Throwable err) { /** {@inheritDoc} */ @Override public void prepareMarshal(Marshaller marsh) throws IgniteCheckedException { + if (err == null) + return; + try { - if (err != null) - errBytes = U.marshal(marsh, err); + errBytes = U.marshal(marsh, err); } - catch (IgniteCheckedException e) { - IgniteCheckedException wrappedErr = new IgniteCheckedException(err.getMessage()); - - wrappedErr.setStackTrace(err.getStackTrace()); - wrappedErr.addSuppressed(e); - - errBytes = U.marshal(marsh, wrappedErr); + catch (Throwable e) { + errBytes = U.marshal(marsh, wrapError(true, e)); } } /** {@inheritDoc} */ @Override public void finishUnmarshal(Marshaller marsh, ClassLoader clsLdr) throws IgniteCheckedException { - if (errBytes != null) + if (errBytes == null) + return; + + try { err = U.unmarshal(marsh, errBytes, clsLdr); + } + catch (Throwable e) { + err = wrapError(false, e); + } } /** */ @@ -88,9 +92,26 @@ public ErrorMessage(@Nullable Throwable err) { return errorMsg == null ? null : errorMsg.error(); } - /** {@inheritDoc} */ @Override public String toString() { return S.toString(ErrorMessage.class, this); } + + /** */ + private static Throwable wrapError(boolean marshall, Throwable e) { + String errStr = "Failed to " + (marshall ? "marshall" : "unmarshall") + " an exception."; + + if (e.getCause() != null && e.getCause() != e) { + errStr += " Original cause: \"" + e.getCause().getMessage() + "\", the stack head: \"" + + e.getCause().getStackTrace()[0].toString() + "\"."; + } + + IgniteCheckedException wrappedErr = new IgniteCheckedException(errStr); + + wrappedErr.setStackTrace(e.getStackTrace()); + + wrappedErr.addSuppressed(e); + + return wrappedErr; + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDeploymentTask.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDeploymentTask.java index ede3217390b29..3c24df5dc1835 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDeploymentTask.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDeploymentTask.java @@ -383,8 +383,7 @@ private void createAndSendSingleDeploymentsMessage(ServiceDeploymentProcessId de Map results = new HashMap<>(); for (IgniteUuid srvcId : depServicesIds) { - ServiceSingleNodeDeploymentResult depRes = new ServiceSingleNodeDeploymentResult( - srvcProc.localInstancesCount(srvcId), log); + ServiceSingleNodeDeploymentResult depRes = new ServiceSingleNodeDeploymentResult(srvcProc.localInstancesCount(srvcId)); depRes.errors(errors.get(srvcId)); @@ -395,8 +394,7 @@ private void createAndSendSingleDeploymentsMessage(ServiceDeploymentProcessId de if (results.containsKey(srvcId)) return; - ServiceSingleNodeDeploymentResult depRes = new ServiceSingleNodeDeploymentResult( - srvcProc.localInstancesCount(srvcId), log); + ServiceSingleNodeDeploymentResult depRes = new ServiceSingleNodeDeploymentResult(srvcProc.localInstancesCount(srvcId)); depRes.errors(err); @@ -639,7 +637,7 @@ private Collection buildFullDeploymentsResults( if (cnt == 0 && res.errors().isEmpty()) return; - ServiceSingleNodeDeploymentResult singleDepRes = new ServiceSingleNodeDeploymentResult(cnt, log); + ServiceSingleNodeDeploymentResult singleDepRes = new ServiceSingleNodeDeploymentResult(cnt); if (!res.errors().isEmpty()) singleDepRes.errors(res.errors()); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceSingleNodeDeploymentResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceSingleNodeDeploymentResult.java index ad92ea54f8ca5..10ceefb8284aa 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceSingleNodeDeploymentResult.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceSingleNodeDeploymentResult.java @@ -18,17 +18,13 @@ package org.apache.ignite.internal.processors.service; import java.io.Serializable; -import java.util.ArrayList; import java.util.Collection; -import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.IgniteLogger; -import org.apache.ignite.internal.MarshallableMessage; +import java.util.Collections; import org.apache.ignite.internal.Order; +import org.apache.ignite.internal.managers.communication.ErrorMessage; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.S; -import org.apache.ignite.internal.util.typedef.internal.U; -import org.apache.ignite.marshaller.Marshaller; -import org.jetbrains.annotations.NotNull; +import org.apache.ignite.plugin.extensions.communication.Message; import org.jetbrains.annotations.Nullable; /** @@ -36,7 +32,7 @@ *

* Contains count of deployed service instances on single node and deployment errors if exist. */ -public class ServiceSingleNodeDeploymentResult implements MarshallableMessage, Serializable { +public class ServiceSingleNodeDeploymentResult implements Message, Serializable { /** */ private static final long serialVersionUID = 0L; @@ -45,28 +41,21 @@ public class ServiceSingleNodeDeploymentResult implements MarshallableMessage, S int cnt; /** Exceptions. */ - private @Nullable Collection errors; - - /** Serialized {@link #errors}. */ @Order(1) - @Nullable Collection errorsBytes; - - /** Logger. */ - private IgniteLogger log; + @Nullable Collection errors; /** * Empty constructor for marshalling purposes. */ public ServiceSingleNodeDeploymentResult() { + // No-op. } /** * @param cnt Count of service's instances. - * @param log Logger. */ - public ServiceSingleNodeDeploymentResult(int cnt, IgniteLogger log) { + public ServiceSingleNodeDeploymentResult(int cnt) { this.cnt = cnt; - this.log = log; } /** @@ -79,62 +68,16 @@ public int count() { /** * @return Exceptions. */ - public @NotNull Collection errors() { - return F.emptyIfNull(errors); + public Collection errors() { + return F.isEmpty(errors) ? Collections.emptyList() : F.viewReadOnly(errors, em -> ErrorMessage.error(em)); } /** * @param errors Exceptions. */ public void errors(@Nullable Collection errors) { - this.errors = errors; - } - - /** {@inheritDoc} */ - @Override public void prepareMarshal(Marshaller marsh) throws IgniteCheckedException { - if (F.isEmpty(errors)) - return; - - errorsBytes = new ArrayList<>(); - - for (Throwable th : errors) { - try { - errorsBytes.add(U.marshal(marsh, th)); - } - catch (IgniteCheckedException e) { - log.error("Failed to marshal deployment error, err=" + th, e); - - try { - byte[] arr = U.marshal( - marsh, - new IgniteCheckedException("Failed to marshal deployment error, see server logs for details, err=" + th) - ); - - errorsBytes.add(arr); - } - catch (IgniteCheckedException ex) { - log.error("Failed to attach deployment error information to deployment result message", ex); - } - } - } - } - - /** {@inheritDoc} */ - @Override public void finishUnmarshal(Marshaller marsh, ClassLoader clsLdr) throws IgniteCheckedException { - if (errorsBytes != null && errors == null) { - errors = new ArrayList<>(); - - for (byte[] arr : errorsBytes) { - try { - errors.add(U.unmarshal(marsh, arr, clsLdr)); - } - catch (IgniteCheckedException e) { - U.error(null, "Failed to unmarshal deployment error.", e); - - errors.add(new IgniteCheckedException("Failed to unmarshal deployment error, see server logs for details.")); - } - } - } + if (!F.isEmpty(errors)) + this.errors = F.viewReadOnly(errors, ErrorMessage::new); } /** {@inheritDoc} */ diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceExceptionPropagationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceExceptionPropagationTest.java index 96179238ff2f4..c3f35a7f7c194 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceExceptionPropagationTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceExceptionPropagationTest.java @@ -37,9 +37,6 @@ public class GridServiceExceptionPropagationTest extends GridCommonAbstractTest /** */ private static final String BROKEN_EX_MSG = "Exception occurred on serialization step"; - /** */ - private static final String BROKEN_EX_WRAPPER_MSG = ", see server logs for details"; - /** */ private static final String EX_MSG = "Exception message"; @@ -183,17 +180,24 @@ private void testExceptionPropagation( catch (ServiceDeploymentException ex) { assertTrue(shouldThrow); - String errMsg = ex.getSuppressed()[0].getMessage(); - if (isNodeInfoAvailableInExMsg) { - assertTrue(errMsg.contains(srv.cluster().localNode().id().toString())); - assertTrue(errMsg.contains(SERVICE_NAME)); + String locNodeId = srv.cluster().localNode().id().toString(); + + assertTrue(ex.getSuppressed()[0].getMessage().contains(locNodeId) + || ex.getSuppressed()[0].getSuppressed()[0].getMessage().contains(locNodeId)); + + assertTrue(ex.getSuppressed()[0].getMessage().contains(SERVICE_NAME) + || ex.getSuppressed()[0].getSuppressed()[0].getMessage().contains(SERVICE_NAME)); } Throwable cause = ex.getSuppressed()[0].getCause(); - if (cause == null) - assertTrue(errMsg.contains(BROKEN_EX_WRAPPER_MSG)); + if (cause == null) { + String errMsg = ex.getSuppressed()[0].getMessage(); + + assertTrue(errMsg.contains(BrokenExternalizableException.class.getSimpleName()) && + (errMsg.contains("Failed to marshall an exception") || errMsg.contains("Failed to unmarshall an exception"))); + } else assertTrue(cause.getMessage().contains(EX_MSG)); }