This is an automated email from the ASF dual-hosted git repository. jerrick pushed a commit to branch 2.6.x in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git
The following commit(s) were added to refs/heads/2.6.x by this push: new 52e9290 fix telnet invoke NPE #2218 (#2273) (#2453) 52e9290 is described below commit 52e9290d12162d1d483b21070729e7f2c6a04733 Author: Jerrick Zhu <diecui1...@gmail.com> AuthorDate: Thu Sep 6 09:57:44 2018 +0800 fix telnet invoke NPE #2218 (#2273) (#2453) --- .../protocol/dubbo/telnet/InvokeTelnetHandler.java | 13 ++++++++ .../rpc/protocol/dubbo/support/DemoService.java | 2 ++ .../protocol/dubbo/support/DemoServiceImpl.java | 5 +++ .../dubbo/telnet/InvokerTelnetHandlerTest.java | 36 ++++++++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java index 47f11f5..59733dc 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java @@ -60,6 +60,19 @@ public class InvokeTelnetHandler implements TelnetHandler { for (int i = 0; i < types.length; i++) { Class<?> type = types[i]; Object arg = args.get(i); + + if (arg == null) { + // if the type is primitive, the method to invoke will cause NullPointerException definitely + // so we can offer a specified error message to the invoker in advance and avoid unnecessary invoking + if (type.isPrimitive()) { + throw new NullPointerException(String.format( + "The type of No.%d parameter is primitive(%s), but the value passed is null.", i + 1, type.getName())); + } + + // if the type is not primitive, we choose to believe what the invoker want is a null value + continue; + } + if (ReflectUtils.isPrimitive(arg.getClass())) { if (!ReflectUtils.isPrimitive(type)) { return false; diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java index 182a1e8..93c48f5 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java @@ -57,4 +57,6 @@ public interface DemoService { NonSerialized returnNonSerialized(); + long add(int a, long b); + } \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java index 93c9764..50d98e6 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java @@ -103,4 +103,9 @@ public class DemoServiceImpl implements DemoService { public NonSerialized returnNonSerialized() { return new NonSerialized(); } + + public long add(int a, long b) { + return a + b; + } + } \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java index 04092d0..9dfc20f 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java @@ -33,6 +33,7 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -70,6 +71,41 @@ public class InvokerTelnetHandlerTest { @SuppressWarnings("unchecked") @Test + public void testInvokeByPassingNullValue() throws RemotingException { + mockInvoker = mock(Invoker.class); + given(mockInvoker.getInterface()).willReturn(DemoService.class); + given(mockInvoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:20883/demo")); + given(mockInvoker.invoke(any(Invocation.class))).willReturn(new RpcResult("ok")); + mockChannel = mock(Channel.class); + given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService"); + given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555")); + given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20883")); + DubboProtocol.getDubboProtocol().export(mockInvoker); + // pass null value to parameter of primitive type + try { + invoke.telnet(mockChannel, "DemoService.add(null, 2)"); + fail("It should cause a NullPointerException by the above code."); + } catch (NullPointerException ex) { + String message = ex.getMessage(); + assertEquals("The type of No.1 parameter is primitive(int), but the value passed is null.", message); + } + try { + invoke.telnet(mockChannel, "DemoService.add(1, null)"); + fail("It should cause a NullPointerException by the above code."); + } catch (NullPointerException ex) { + String message = ex.getMessage(); + assertEquals("The type of No.2 parameter is primitive(long), but the value passed is null.", message); + } + // pass null value to parameter of object type + try { + invoke.telnet(mockChannel, "DemoService.sayHello(null)"); + } catch (NullPointerException ex) { + fail("It shouldn't cause a NullPointerException by the above code."); + } + } + + @SuppressWarnings("unchecked") + @Test public void testInvokeAutoFindMethod() throws RemotingException { mockInvoker = mock(Invoker.class); given(mockInvoker.getInterface()).willReturn(DemoService.class);