sergey-chugunov-1985 commented on code in PR #12555:
URL: https://github.com/apache/ignite/pull/12555#discussion_r2645482922


##########
modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDeploymentTask.java:
##########
@@ -541,6 +541,15 @@ private void completeInitiatingFuture(final Throwable err) 
{
                 }
                 catch (IgniteCheckedException e) {
                     log.error("Failed to unmarshal deployment error.", e);
+
+                    Exception ex = new IgniteCheckedException(
+                        "Failed to unmarshal deployment error! See server logs 
for details."

Review Comment:
   ```suggestion
                           "Failed to unmarshal deployment error, see server 
logs for details."
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDeploymentTask.java:
##########
@@ -685,6 +694,19 @@ private void attachDeploymentErrors(@NotNull 
ServiceSingleNodeDeploymentResult d
             }
             catch (IgniteCheckedException e) {
                 log.error("Failed to marshal deployment error, err=" + th, e);
+
+                try {
+                    Exception ex = new IgniteCheckedException(
+                        "Failed to marshal deployment error! See server logs 
for details, err=" + th

Review Comment:
   ```suggestion
                           "Failed to marshal deployment error, see server logs 
for details. Deployment error: " + th
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDeploymentTask.java:
##########
@@ -685,6 +694,19 @@ private void attachDeploymentErrors(@NotNull 
ServiceSingleNodeDeploymentResult d
             }
             catch (IgniteCheckedException e) {
                 log.error("Failed to marshal deployment error, err=" + th, e);
+
+                try {
+                    Exception ex = new IgniteCheckedException(
+                        "Failed to marshal deployment error! See server logs 
for details, err=" + th
+                    );
+
+                    byte[] arr = U.marshal(ctx, ex);
+
+                    errorsBytes.add(arr);
+                }
+                catch (IgniteCheckedException ex) {
+                    log.error("Failed to attach marshal deployment error to 
the message, err=" + th, ex);

Review Comment:
   ```suggestion
                       log.error("Failed to attach deployment error information 
to deployment result message", ex);
   ```



##########
modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceExceptionPropagationTest.java:
##########
@@ -0,0 +1,542 @@
+/*
+ * 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.processors.service;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.services.Service;
+import org.apache.ignite.services.ServiceConfiguration;
+import org.apache.ignite.services.ServiceDeploymentException;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+/** */
+public class GridServiceExceptionPropagationTest extends 
GridCommonAbstractTest {
+    /** */
+    private static final String EX_BROKEN_SER_MSG = "Exception occurred on 
serialization step";
+
+    /** */
+    private static final String RETURNED_EX_BROKEN_SER_MSG = "See server logs 
for details";
+
+    /** */
+    private static final String EX_MSG = "Exception message";
+
+    /** */
+    private static final String SERVICE_NAME = "my-service";
+
+    /** */
+    private static final ExceptionThrower SERIAL_EX = 
ExceptionThrower.serializable();
+
+    /** */
+    private static final ExceptionThrower EXT_EX = 
ExceptionThrower.externalizable(false, false);
+
+    /** */
+    private static final ExceptionThrower EX_WITH_BROKEN_SER = 
ExceptionThrower.externalizable(true, true);
+
+    /** */
+    private static final ExceptionThrower EX_WITH_BROKEN_DESER = 
ExceptionThrower.externalizable(true, false);
+
+    /** */
+    private boolean isNodeInfoAvailableInExMsg = true;
+
+    /** */
+    @Test
+    public void testServiceCancelThrowsSerializableException() throws 
Exception {
+        Service svc = new 
ServiceWithException().withCancelException(SERIAL_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, true);
+    }
+
+    /** */
+    @Test
+    public void testServiceCancelThrowsExternalizableException() throws 
Exception {
+        Service svc = new ServiceWithException().withCancelException(EXT_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, true);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceCancelThrowsExternalizableExceptionWithBrokenSerialization() throws 
Exception {
+        Service svc = new 
ServiceWithException().withCancelException(EX_WITH_BROKEN_SER);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, true);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceCancelThrowsExternalizableExceptionWithBrokenDeserialization() 
throws Exception {
+        Service svc = new 
ServiceWithException().withCancelException(EX_WITH_BROKEN_DESER);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, true);
+    }
+
+    /** */
+    @Test
+    public void testServiceInitThrowsSerializableException() throws Exception {
+        Service svc = new ServiceWithException().withInitException(SERIAL_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), true, false);
+    }
+
+    /** */
+    @Test
+    public void testServiceInitThrowsExternalizableException() throws 
Exception {
+        Service svc = new ServiceWithException().withInitException(EXT_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), true, false);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceInitThrowsExternalizableExceptionWithBrokenSerialization() throws 
Exception {
+        Service svc = new 
ServiceWithException().withInitException(EX_WITH_BROKEN_SER);
+
+        testExceptionPropagation(getServiceConfiguration(svc), true, false);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceInitThrowsExternalizableExceptionWithBrokenDeserialization() throws 
Exception {
+        Service svc = new 
ServiceWithException().withInitException(EX_WITH_BROKEN_DESER);
+
+        isNodeInfoAvailableInExMsg = false;
+
+        testExceptionPropagation(getServiceConfiguration(svc), true, false);
+
+        isNodeInfoAvailableInExMsg = true;
+    }
+
+    /** */
+    @Test
+    public void testServiceExecuteThrowsSerializableException() throws 
Exception {
+        Service svc = new 
ServiceWithException().withExecuteException(SERIAL_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, false);
+    }
+
+    /** */
+    @Test
+    public void testServiceExecuteThrowsExternalizableException() throws 
Exception {
+        Service svc = new ServiceWithException().withExecuteException(EXT_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, false);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceExecuteThrowsExternalizableExceptionWithBrokenSerialization() throws 
Exception {
+        Service svc = new 
ServiceWithException().withExecuteException(EX_WITH_BROKEN_SER);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, false);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceExecuteThrowsExternalizableExceptionWithBrokenDeserialization() 
throws Exception {
+        Service svc = new 
ServiceWithException().withExecuteException(EX_WITH_BROKEN_DESER);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, false);
+    }
+
+    /** */
+    private void testExceptionPropagation(
+        ServiceConfiguration srvcCfg,
+        boolean shouldThrow,
+        boolean withCancel
+    ) throws Exception {
+        try (IgniteEx srv = startGrid(0); IgniteEx client = 
startClientGrid(1)) {
+            try {
+                client.services().deploy(srvcCfg);
+
+                if (withCancel)
+                    client.services().cancel(SERVICE_NAME);
+
+                if (shouldThrow)
+                    fail("Exception has been expected.");
+            }
+            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));
+                }
+
+                Throwable cause = ex.getSuppressed()[0].getCause();
+
+                if (cause == null)
+                    assertTrue(errMsg.contains(RETURNED_EX_BROKEN_SER_MSG));
+                else
+                    assertTrue(cause.getMessage().contains(EX_MSG));
+            }
+            catch (Throwable e) {
+                throw new AssertionError("Unexpected exception has been 
thrown.", e);
+            }
+        }
+    }
+
+    /** */
+    private ServiceConfiguration getServiceConfiguration(Service svc) {
+        return new ServiceConfiguration()
+            .setService(svc)
+            .setName(SERVICE_NAME)
+            .setMaxPerNodeCount(1)
+            .setNodeFilter(new ClientNodeFilter());
+    }
+
+    /**
+     *
+     */
+    private static class ClientNodeFilter implements 
IgnitePredicate<ClusterNode> {
+        /** {@inheritDoc} */
+        @Override public boolean apply(ClusterNode node) {
+            return !node.isClient();
+        }
+    }
+
+    /**
+     * A simple {@link Service} implementation that intentionally throws 
exceptions during
+     * specific {@link Service} lifecycle phases for testing purposes.
+     *
+     * <p>This service can be configured to:
+     * <ul>
+     *     <li>Throw an {@link Exception} during either {@link #init()} or 
{@link #execute()}.</li>
+     *     <li>Throw a {@link RuntimeException} during {@link #cancel()}.</li>
+     * </ul>
+     */
+    private static class ServiceWithException implements Service {
+        /** */
+        private boolean throwOnCancel;
+
+        /** */
+        private boolean throwOnInit;
+
+        /** */
+        private boolean throwOnExec;
+
+        /** */
+        private ExceptionThrower exThrower;
+
+        /** {@inheritDoc} */
+        @Override public void cancel() {
+            if (throwOnCancel)
+                exThrower.throwRunnableException();
+        }
+
+        /** {@inheritDoc} */
+        @Override public void init() throws Exception {
+            if (throwOnInit)
+                exThrower.throwException();
+        }
+
+        /** {@inheritDoc} */
+        @Override public void execute() throws Exception {
+            if (throwOnExec)
+                exThrower.throwException();
+        }
+
+        /** */
+        public Service withCancelException(ExceptionThrower exThrower) {
+            this.exThrower = exThrower;
+
+            throwOnCancel = true;
+
+            return this;
+        }
+
+        /** */
+        public Service withInitException(ExceptionThrower exThrower) {
+            this.exThrower = exThrower;
+
+            throwOnInit = true;
+
+            return this;
+        }
+
+        /** */
+        public Service withExecuteException(ExceptionThrower exThrower) {
+            this.exThrower = exThrower;
+
+            throwOnExec = true;
+
+            return this;
+        }
+    }
+
+    /** */
+    private static class ExceptionThrower implements Serializable {
+        /** */
+        private final boolean isSerializable;
+
+        /** */
+        private final boolean isBroken;
+
+        /** */
+        private final boolean isSerializationBroken;
+
+        /** */
+        private ExceptionThrower(boolean isSerializable, boolean isBroken, 
boolean isSerializationBroken) {
+            this.isSerializable = isSerializable;
+            this.isBroken = isBroken;
+            this.isSerializationBroken = isSerializationBroken;
+        }
+
+        /**
+         * @return Serializable exception configuration
+         */
+        static ExceptionThrower serializable() {
+            return new ExceptionThrower(true, false, false);
+        }
+
+        /**
+         * @return Externalizable exception configuration
+         */
+        static ExceptionThrower externalizable(boolean isBroken, boolean 
isSerializationBroken) {
+            return new ExceptionThrower(false, isBroken, 
isSerializationBroken);
+        }
+
+        /** */
+        public void throwException() throws Exception {
+            if (isSerializable)
+                throw new Exception(EX_MSG);
+
+            throw new ExternalizableException(EX_MSG, isBroken, 
isSerializationBroken);
+        }
+
+        /** */
+        public void throwRunnableException() {

Review Comment:
   ```suggestion
           public void throwRuntimeException() {
   ```



##########
modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceExceptionPropagationTest.java:
##########
@@ -0,0 +1,542 @@
+/*
+ * 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.processors.service;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.services.Service;
+import org.apache.ignite.services.ServiceConfiguration;
+import org.apache.ignite.services.ServiceDeploymentException;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+/** */
+public class GridServiceExceptionPropagationTest extends 
GridCommonAbstractTest {
+    /** */
+    private static final String EX_BROKEN_SER_MSG = "Exception occurred on 
serialization step";
+
+    /** */
+    private static final String RETURNED_EX_BROKEN_SER_MSG = "See server logs 
for details";
+
+    /** */
+    private static final String EX_MSG = "Exception message";
+
+    /** */
+    private static final String SERVICE_NAME = "my-service";
+
+    /** */
+    private static final ExceptionThrower SERIAL_EX = 
ExceptionThrower.serializable();
+
+    /** */
+    private static final ExceptionThrower EXT_EX = 
ExceptionThrower.externalizable(false, false);
+
+    /** */
+    private static final ExceptionThrower EX_WITH_BROKEN_SER = 
ExceptionThrower.externalizable(true, true);
+
+    /** */
+    private static final ExceptionThrower EX_WITH_BROKEN_DESER = 
ExceptionThrower.externalizable(true, false);
+
+    /** */
+    private boolean isNodeInfoAvailableInExMsg = true;
+
+    /** */
+    @Test
+    public void testServiceCancelThrowsSerializableException() throws 
Exception {
+        Service svc = new 
ServiceWithException().withCancelException(SERIAL_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, true);
+    }
+
+    /** */
+    @Test
+    public void testServiceCancelThrowsExternalizableException() throws 
Exception {
+        Service svc = new ServiceWithException().withCancelException(EXT_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, true);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceCancelThrowsExternalizableExceptionWithBrokenSerialization() throws 
Exception {
+        Service svc = new 
ServiceWithException().withCancelException(EX_WITH_BROKEN_SER);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, true);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceCancelThrowsExternalizableExceptionWithBrokenDeserialization() 
throws Exception {
+        Service svc = new 
ServiceWithException().withCancelException(EX_WITH_BROKEN_DESER);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, true);
+    }
+
+    /** */
+    @Test
+    public void testServiceInitThrowsSerializableException() throws Exception {
+        Service svc = new ServiceWithException().withInitException(SERIAL_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), true, false);
+    }
+
+    /** */
+    @Test
+    public void testServiceInitThrowsExternalizableException() throws 
Exception {
+        Service svc = new ServiceWithException().withInitException(EXT_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), true, false);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceInitThrowsExternalizableExceptionWithBrokenSerialization() throws 
Exception {
+        Service svc = new 
ServiceWithException().withInitException(EX_WITH_BROKEN_SER);
+
+        testExceptionPropagation(getServiceConfiguration(svc), true, false);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceInitThrowsExternalizableExceptionWithBrokenDeserialization() throws 
Exception {
+        Service svc = new 
ServiceWithException().withInitException(EX_WITH_BROKEN_DESER);
+
+        isNodeInfoAvailableInExMsg = false;
+
+        testExceptionPropagation(getServiceConfiguration(svc), true, false);
+
+        isNodeInfoAvailableInExMsg = true;
+    }
+
+    /** */
+    @Test
+    public void testServiceExecuteThrowsSerializableException() throws 
Exception {
+        Service svc = new 
ServiceWithException().withExecuteException(SERIAL_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, false);
+    }
+
+    /** */
+    @Test
+    public void testServiceExecuteThrowsExternalizableException() throws 
Exception {
+        Service svc = new ServiceWithException().withExecuteException(EXT_EX);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, false);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceExecuteThrowsExternalizableExceptionWithBrokenSerialization() throws 
Exception {
+        Service svc = new 
ServiceWithException().withExecuteException(EX_WITH_BROKEN_SER);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, false);
+    }
+
+    /** */
+    @Test
+    public void 
testServiceExecuteThrowsExternalizableExceptionWithBrokenDeserialization() 
throws Exception {
+        Service svc = new 
ServiceWithException().withExecuteException(EX_WITH_BROKEN_DESER);
+
+        testExceptionPropagation(getServiceConfiguration(svc), false, false);
+    }
+
+    /** */
+    private void testExceptionPropagation(
+        ServiceConfiguration srvcCfg,
+        boolean shouldThrow,
+        boolean withCancel
+    ) throws Exception {
+        try (IgniteEx srv = startGrid(0); IgniteEx client = 
startClientGrid(1)) {
+            try {
+                client.services().deploy(srvcCfg);
+
+                if (withCancel)
+                    client.services().cancel(SERVICE_NAME);
+
+                if (shouldThrow)
+                    fail("Exception has been expected.");

Review Comment:
   ```suggestion
                       fail("An expected exception has not been thrown.");
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to