From 2589039030e859b4c5bcbd4095441c4622c806c2 Mon Sep 17 00:00:00 2001 From: gyowoo1113 Date: Sun, 26 Jul 2026 20:13:23 +0900 Subject: [PATCH 1/3] [ZEPPELIN-6543] Handle invokeMethod serialization failure as InterpreterRPCException --- .../RemoteInterpreterEventServer.java | 2 +- .../RemoteInterpreterEventServerTest.java | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 zeppelin-server/src/test/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServerTest.java diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServer.java index bab3ee7b2ad..e0febf76359 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServer.java @@ -440,7 +440,7 @@ public ByteBuffer invokeMethod(String intpGroupId, String invokeMethodJson) try { obj = Resource.serializeObject(ret); } catch (IOException e) { - LOGGER.error("invokeMethod failed", e); + throw new InterpreterRPCException(e.toString()); } } return obj; diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServerTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServerTest.java new file mode 100644 index 00000000000..0fe8eab3d61 --- /dev/null +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServerTest.java @@ -0,0 +1,79 @@ +package org.apache.zeppelin.interpreter; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.nio.ByteBuffer; + +import org.apache.zeppelin.conf.ZeppelinConfiguration; +import org.apache.zeppelin.interpreter.remote.InvokeResourceMethodEventMessage; +import org.apache.zeppelin.interpreter.remote.RemoteInterpreterProcess; +import org.apache.zeppelin.interpreter.thrift.InterpreterRPCException; +import org.apache.zeppelin.resource.Resource; +import org.apache.zeppelin.resource.ResourceId; +import org.junit.jupiter.api.Test; + +public class RemoteInterpreterEventServerTest { + + @Test + void invokeMethodThrowsRpcExceptionWhenSerializationFails() throws Exception { + ZeppelinConfiguration zConf = mock(ZeppelinConfiguration.class); + InterpreterSettingManager manager = mock(InterpreterSettingManager.class); + RemoteInterpreterEventServer server = new RemoteInterpreterEventServer(zConf, manager); + + ManagedInterpreterGroup interpreterGroup = mock(ManagedInterpreterGroup.class); + RemoteInterpreterProcess remoteInterpreterProcess = mock(RemoteInterpreterProcess.class); + + when(manager.getInterpreterGroupById("pool-id")) + .thenReturn(interpreterGroup); + when(interpreterGroup.getRemoteInterpreterProcess()) + .thenReturn(remoteInterpreterProcess); + when(remoteInterpreterProcess.isRunning()) + .thenReturn(true); + + ByteBuffer remoteResult = Resource.serializeObject(new SerializableOnlyOnce()); + doReturn(remoteResult) + .when(remoteInterpreterProcess) + .callRemoteFunction(any()); + + ResourceId resourceId = ResourceId.fromJson( + "{\"resourcePoolId\":\"pool-id\",\"name\":\"resource-name\",\"noteId\":\"note-id\",\"paragraphId\":\"paragraph-id\"}" + ); + + InvokeResourceMethodEventMessage message = new InvokeResourceMethodEventMessage( + resourceId + , "someMethod" + , null + , null + , null); + + InterpreterRPCException exception = assertThrows( + InterpreterRPCException.class, + () -> server.invokeMethod("caller-group-id", message.toJson())); + + assertTrue(exception.toString().contains("failed on second serialization")); + } + private static class SerializableOnlyOnce implements Serializable { + private static final long serialVersionUID = 1L; + private static final int FAILURE_SERIALIZATION_COUNT = 2; + + private int serializationCount; + + private void writeObject(ObjectOutputStream outputStream) throws IOException { + serializationCount++; + + if (serializationCount == FAILURE_SERIALIZATION_COUNT) { + throw new IOException("failed on second serialization"); + } + + outputStream.defaultWriteObject(); + } + } +} From 8e6837df47f57eb7cb140b4403f719ec88c3557a Mon Sep 17 00:00:00 2001 From: gyowoo1113 Date: Sun, 26 Jul 2026 21:08:07 +0900 Subject: [PATCH 2/3] [ZEPPELIN-6543] add License from RemoteInterpreterEventServerTest.java --- .../RemoteInterpreterEventServerTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServerTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServerTest.java index 0fe8eab3d61..ad385c612e7 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServerTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServerTest.java @@ -1,3 +1,19 @@ +/* + * 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.zeppelin.interpreter; import static org.junit.jupiter.api.Assertions.assertThrows; From 2b386cdb0d549fbb28467a094e52de9cf8580162 Mon Sep 17 00:00:00 2001 From: gyowoo1113 Date: Tue, 4 Aug 2026 20:11:17 +0900 Subject: [PATCH 3/3] [ZEPPELIN-6543] restore LOGGER.error from RemoteInterpreterEventServer.java --- .../zeppelin/interpreter/RemoteInterpreterEventServer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServer.java index e0febf76359..8cba498dac3 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/interpreter/RemoteInterpreterEventServer.java @@ -440,6 +440,7 @@ public ByteBuffer invokeMethod(String intpGroupId, String invokeMethodJson) try { obj = Resource.serializeObject(ret); } catch (IOException e) { + LOGGER.error("invokeMethod failed", e); throw new InterpreterRPCException(e.toString()); } }