/** * ExceptionInvokerFilter * <p> * Functions: * <ol> * <li>unexpected exception will be logged in ERROR level on provider side. Unexpected exception are unchecked * exception not declared on the interface</li> * <li>Wrap the exception not introduced in API package into RuntimeException. Framework will serialize the outer exception but stringnize its cause in order to avoid of possible serialization problem on client side</li> * </ol> */ @Activate(group = Constants.PROVIDER) publicclassExceptionFilterimplementsFilter {
@Override public Result invoke(Invoker<?> invoker, Invocation invocation)throws RpcException { try { Resultresult= invoker.invoke(invocation); if (result.hasException() && GenericService.class != invoker.getInterface()) { try { Throwableexception= result.getException();
// directly throw if it's checked exception if (!(exception instanceof RuntimeException) && (exception instanceof Exception)) { return result; } // directly throw if the exception appears in the signature try { Methodmethod= invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes()); Class<?>[] exceptionClassses = method.getExceptionTypes(); for (Class<?> exceptionClass : exceptionClassses) { if (exception.getClass().equals(exceptionClass)) { return result; } } } catch (NoSuchMethodException e) { return result; }
// for the exception not found in method's signature, print ERROR message in server's log. 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);
// directly throw if exception class and interface class are in the same jar file. StringserviceFile= ReflectUtils.getCodeBase(invoker.getInterface()); StringexceptionFile= ReflectUtils.getCodeBase(exception.getClass()); if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)) { return result; } // directly throw if it's JDK exception StringclassName= exception.getClass().getName(); if (className.startsWith("java.") || className.startsWith("javax.")) { return result; } // directly throw if it's dubbo exception if (exception instanceof RpcException) { return result; }
// otherwise, wrap with RuntimeException and throw back to the client returnnewRpcResult(newRuntimeException(StringUtils.toString(exception))); } catch (Throwable e) { logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e); return result; } } return result; } catch (RuntimeException e) { logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e); throw e; } }