1. Ask questions

When dubbo throws a custom exception on the Provider side, the custom exception toString is automatically converted into a RunTimeException and placed in the MSG of the RunTimeException. As a result, we cannot get the exception or information we want when we call it.Copy the code

2. Cause analysis

Dubbo Exception handling class ExceptionFilter

@Activate( group = {"provider"} ) public class ExceptionFilter implements Filter { private final Logger logger; public ExceptionFilter() { this(LoggerFactory.getLogger(ExceptionFilter.class)); } public ExceptionFilter(Logger logger) { this.logger = logger; } public Result invoke(Invoker<? > invoker, Invocation invocation) throws RpcException { try { Result result = invoker.invoke(invocation); if (result.hasException() && GenericService.class ! = invoker.getInterface()) { try { Throwable exception = result.getException(); // If checked, throw if (! (exception instanceof RuntimeException) && exception instanceof Exception) { return result; } else {try {// declaration on method signature, Return Method Method = invoker. GetInterface () getMethod (invocation. GetMethodName (), invocation. GetParameterTypes ()); Class<? >[] exceptionClassses = method.getExceptionTypes(); Class[] arr$ = exceptionClassses; int len$ = exceptionClassses.length; for(int i$ = 0; i$ < len$; ++i$) { Class<? > exceptionClass = arr$[i$]; if (exception.getClass().equals(exceptionClass)) { return result; } } } catch (NoSuchMethodException var11) { return result; } this.logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), exception); // The exception class and interface class are in the same JAR package. Mandatory String serviceFile = reflectutils.getCodebase (invoker.getInterface()); String exceptionFile = ReflectUtils.getCodeBase(exception.getClass()); if (serviceFile ! = null && exceptionFile ! = null && ! serviceFile.equals(exceptionFile)) { String className = exception.getClass().getName(); // If it is a JDK exception, return if (! className.startsWith("java.") && ! Classname.startswith ("javax.")) {// Convert an exception to RuntimeException return (Result)(exception instanceof RpcException? result : new RpcResult(new RuntimeException(StringUtils.toString(exception)))); } else { return result; } } else { return result; } } } catch (Throwable var12) { this.logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + var12.getClass().getName() + ": " + var12.getMessage(), var12); return result; } } else { return result; } } catch (RuntimeException var13) { this.logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + var13.getClass().getName() + ": " + var13.getMessage(), var13); throw var13; }}}Copy the code

3. Solutions

So the exceptions that can be thrown directly are:

1, GenericService implementation interface 2, Checked exception 3, declaration in the method signature 4, exception class and interface class in the same JAR package 5, JDK built-in exception 6, is Dubbo itself exceptionCopy the code

Solution 2: Customize dubbo exception filter

As you can see from the ExtensionLoader class, the directory that spi loads can be seen

Create a Filter from dubbo’s directory. It is recommended to copy dubbo source directly. The directory structure

The content of the Filter replacing our custom Filter path: exception = com. Gaol. Test. Config. DubboExceptionFilter

exception=com.alibaba.dubbo.rpc.filter.ExceptionFilter
Copy the code

A custom Filter

@Log4j2 @Activate(group = {"provider"}) public class DubboExceptionFilter implements Filter { public Result invoke(Invoker<? > invoker, Invocation invocation) throws RpcException { try { Result result = invoker.invoke(invocation); if (result.hasException() && GenericService.class ! = invoker.getInterface()) { try { Throwable exception = result.getException(); if (! (exception instanceof RuntimeException) && exception instanceof Exception) { return result; } else { try { Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes()); Class<? >[] exceptionClassses = method.getExceptionTypes(); Class[] arr$ = exceptionClassses; int len$ = exceptionClassses.length; for(int i$ = 0; i$ < len$; ++i$) { Class<? > exceptionClass = arr$[i$]; if (exception.getClass().equals(exceptionClass)) { return result; } } } catch (NoSuchMethodException var11) { return result; } log.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), exception); String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface()); String exceptionFile = ReflectUtils.getCodeBase(exception.getClass()); if (serviceFile ! = null && exceptionFile ! = null && ! serviceFile.equals(exceptionFile)) { String className = exception.getClass().getName(); If (classname.startswith ("com.gaol.test.exception")){return result; } if (! className.startsWith("java.") && ! className.startsWith("javax.")) { return (Result)(exception instanceof RpcException ? result : new RpcResult(new RuntimeException(StringUtils.toString(exception)))); } else { return result; } } else { return result; } } } catch (Throwable var12) { log.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + var12.getClass().getName() + ": " + var12.getMessage(), var12); return result; } } else { return result; } } catch (RuntimeException var13) { log.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + var13.getClass().getName() + ": " + var13.getMessage(), var13); throw var13; }}}Copy the code

Progress together !!!!!!!!!