When Dubbo throws a custom exception: Got unchecked and undeclared exception

Reprinted: http://blog.csdn.net/xlee1905/article/details/44660449

When dubbo's service end defines a custom exception to throw, it finds that it cannot be instanceof in the Controller, and the self-defined exception class is converted into a Runtime exception. Dubbo source code:

[java]  view plain copy

  1. public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {  
  2.     try {  
  3.         Result result = invoker.invoke(invocation);  
  4.         if (result.hasException() && GenericService.class != invoker.getInterface()) {  
  5.             try {  
  6.                 Throwable exception = result.getException();  
  7.   
  8.                 // If it is a checked exception, throw it directly  
  9.                 if (! (exception instanceof RuntimeException) && (exception instanceof Exception)) {  
  10.                     return result;  
  11.                 }  
  12.                 // There is a statement in the method signature, and it is thrown directly  
  13.                 try {  
  14.                     Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes());  
  15.                     Class<?>[] exceptionClassses = method.getExceptionTypes();  
  16.                     for (Class<?> exceptionClass : exceptionClassses) {  
  17.                         if (exception.getClass().equals(exceptionClass)) {  
  18.                             return result;  
  19.                         }  
  20.                     }  
  21.                 } catch (NoSuchMethodException e) {  
  22.                     return result;  
  23.                 }  
  24.   
  25.                 // For exceptions not defined on the method signature, print the ERROR log on the server side  
  26.                 logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()  
  27.                         + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()  
  28.                         + ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), exception);  
  29.   
  30.                 // Exception class and interface class are in the same jar package, throw directly  
  31.                 String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());  
  32.                 String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());  
  33.                 if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)){  
  34.                     return result;  
  35.                 }  
  36.                 // It is an exception that comes with JDK and is thrown directly  
  37.                 String className = exception.getClass().getName();  
  38.                 if (className.startsWith("java.") || className.startsWith("javax.")) {  
  39.                     return result;  
  40.                 }  
  41.                 // It is an exception of Dubbo itself, directly thrown  
  42.                 if (exception instanceof RpcException) {  
  43.                     return result;  
  44.                 }  
  45.   
  46.                 // Otherwise, wrap it into a RuntimeException and throw it to the client  
  47.                 return new RpcResult(new RuntimeException(StringUtils.toString(exception)));  
  48.             } catch (Throwable e) {  
  49.                 logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost()  
  50.                         + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()  
  51.                         + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);  
  52.                 return result;  
  53.             }  
  54.         }  
  55.         return result;  
  56.     } catch (RuntimeException e) {  
  57.         logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()  
  58.                 + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()  
  59.                 + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);  
  60.         throw e;  
  61.     }  
  62. }  

        Therefore, if you want to throw a custom exception on the service side of dubbo, you can only declare the exception to be thrown on the interface method of the service side, or package the exception class with the interface, or implement dubbo's GenericService in the implementation class of the interface interface.

        The first option is not used, because it is more serious intrusion into the code.

        The second solution can be realized, but for the current business framework, it is impossible to make the interface class and exception class the same package.

        So in the end, I chose to let the interface implementation class implement the GenericService interface, but did not do any method body processing for the $invoke method that needs to be implemented, and discarded it directly.

        Regarding the handling of custom exception classes on the service side of dubbo, some people don't understand why dubbo needs to convert the custom exception classes to Runtime exceptions instead of directly throwing the original exception type. Or is there a friend who knows more about dubbo and has a better way to deal with custom exceptions.

reference

Dubbo producers throw custom exceptions

Guess you like

Origin blog.csdn.net/gaoshan12345678910/article/details/120956394