GenericFilter implements Filter, Filter.Listener { @Override public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException { if ((inv.getMethodName().equals($INVOKE) || inv.getMethodName().equals($INVOKE_ASYNC)) && inv.getArguments() != null && inv.getArguments().length == 3 && !GenericService.class.isAssignableFrom(invoker.getInterface())) { String name = ((String) inv.getArguments()[0]).trim(); String[] types = (String[]) inv.getArguments()[1]; Object[] args = (Object[]) inv.getArguments()[2]; try { Method method = ReflectUtils.findMethodByMethodSignature(invoker.getInterface(), name, types); Class<?>[] params = method.getParameterTypes(); if (args == null) { args = new Object[params.length]; } if(types == null) { types = new String[params.length]; } if (args.length != types.length) { throw new RpcException("GenericFilter#invoke args.length != types.length, please check your " + "params"); } String generic = inv.getAttachment(GENERIC_KEY); if (StringUtils.isBlank(generic)) { generic = RpcContext.getContext().getAttachment(GENERIC_KEY); } if (StringUtils.isEmpty(generic) || ProtocolUtils.isDefaultGenericSerialization(generic) || ProtocolUtils.isGenericReturnRawResult(generic)) { args = PojoUtils.realize(args, params, method.getGenericParameterTypes()); } else if (ProtocolUtils.isJavaGenericSerialization(generic)) { for (int i = 0; i < args.length; i++) { if (byte[].class == args[i].getClass()) { try (UnsafeByteArrayInputStream is = new UnsafeByteArrayInputStream((byte[]) args[i])) { args[i] = ExtensionLoader.getExtensionLoader(Serialization.class) .getExtension(GENERIC_SERIALIZATION_NATIVE_JAVA) .deserialize(null, is).readObject(); } catch (Exception e) { throw new RpcException("Deserialize argument [" + (i + 1) + "] failed.", e); } } else { throw new RpcException( "Generic serialization [" + GENERIC_SERIALIZATION_NATIVE_JAVA + "] only support message type " + byte[].class + " and your message type is " + args[i].getClass()); } } } else if (ProtocolUtils.isBeanGenericSerialization(generic)) { for (int i = 0; i < args.length; i++) { if (args[i] instanceof JavaBeanDescriptor) { args[i] = JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) args[i]); } else { throw new RpcException( "Generic serialization [" + GENERIC_SERIALIZATION_BEAN + "] only support message type " + JavaBeanDescriptor.class.getName() + " and your message type is " + args[i].getClass().getName()); } } } else if (ProtocolUtils.isProtobufGenericSerialization(generic)) { if (args.length == 1 && args[0] instanceof String) { try (UnsafeByteArrayInputStream is = new UnsafeByteArrayInputStream(((String) args[0]).getBytes())) { args[0] = ExtensionLoader.getExtensionLoader(Serialization.class) .getExtension(GENERIC_SERIALIZATION_PROTOBUF) .deserialize(null, is).readObject(method.getParameterTypes()[0]); } catch (Exception e) { throw new RpcException("Deserialize argument failed.", e); } } else { throw new RpcException( "Generic serialization [" + GENERIC_SERIALIZATION_PROTOBUF + "] only support one " + String.class.getName() + " argument and your message size is " + args.length + " and type is" + args[0].getClass().getName()); } } RpcInvocation rpcInvocation = new RpcInvocation(method, invoker.getInterface().getName(), invoker.getUrl().getProtocolServiceKey(), args, inv.getObjectAttachments(), inv.getAttributes()); rpcInvocation.setInvoker(inv.getInvoker()); rpcInvocation.setTargetServiceUniqueName(inv.getTargetServiceUniqueName()); return invoker.invoke(rpcInvocation); } catch (NoSuchMethodException | ClassNotFoundException e) { throw new RpcException(e.getMessage(), e); } } return invoker.invoke(inv); }  @Override Result invoke(Invoker<?> invoker, Invocation inv); @Override void onResponse(Result appResponse, Invoker<?> invoker, Invocation inv); @Override void onError(Throwable t, Invoker<?> invoker, Invocation invocation);  }
@Test public void testInvokeWithJavaException() throws Exception { Assertions.assertThrows(RpcException.class, () -> { Method genericInvoke = GenericService.class.getMethods()[0]; Map<String, Object> person = new HashMap<String, Object>(); person.put("name", "dubbo"); person.put("age", 10); RpcInvocation invocation = new RpcInvocation($INVOKE, GenericService.class.getName(), "", genericInvoke.getParameterTypes(), new Object[]{"getPerson", new String[]{Person.class.getCanonicalName()}, new Object[]{person}}); invocation.setAttachment(GENERIC_KEY, GENERIC_SERIALIZATION_NATIVE_JAVA); URL url = URL.valueOf("test: "accesslog=true&group=dubbo&version=1.1"); Invoker invoker = Mockito.mock(Invoker.class); when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse(new Person("person", 10))); when(invoker.getUrl()).thenReturn(url); when(invoker.getInterface()).thenReturn(DemoService.class); genericFilter.invoke(invoker, invocation); }); }
@Test public void testInvokeWithMethodNamtNot$Invoke() { Method genericInvoke = GenericService.class.getMethods()[0]; Map<String, Object> person = new HashMap<String, Object>(); person.put("name", "dubbo"); person.put("age", 10); RpcInvocation invocation = new RpcInvocation("sayHi", GenericService.class.getName(), "", genericInvoke.getParameterTypes() , new Object[]{"getPerson", new String[]{Person.class.getCanonicalName()}, new Object[]{person}}); URL url = URL.valueOf("test: "accesslog=true&group=dubbo&version=1.1"); Invoker invoker = Mockito.mock(Invoker.class); when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse(new Person("person", 10))); when(invoker.getUrl()).thenReturn(url); when(invoker.getInterface()).thenReturn(DemoService.class); Result result = genericFilter.invoke(invoker, invocation); Assertions.assertEquals(Person.class, result.getValue().getClass()); Assertions.assertEquals(10, ((Person) (result.getValue())).getAge()); }
@Test public void testInvokeWithMethodArgumentSizeIsNot3() { Method genericInvoke = GenericService.class.getMethods()[0]; Map<String, Object> person = new HashMap<String, Object>(); person.put("name", "dubbo"); person.put("age", 10); RpcInvocation invocation = new RpcInvocation($INVOKE, GenericService.class.getName(), "", genericInvoke.getParameterTypes() , new Object[]{"getPerson", new String[]{Person.class.getCanonicalName()}}); URL url = URL.valueOf("test: "accesslog=true&group=dubbo&version=1.1"); Invoker invoker = Mockito.mock(Invoker.class); when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse(new Person("person", 10))); when(invoker.getUrl()).thenReturn(url); when(invoker.getInterface()).thenReturn(DemoService.class); Result result = genericFilter.invoke(invoker, invocation); Assertions.assertEquals(Person.class, result.getValue().getClass()); Assertions.assertEquals(10, ((Person) (result.getValue())).getAge()); }