Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consumer always catch java.lang.reflect.UndeclaredThrowableException for the exception thrown from provider #3386

Closed
2 tasks done
eachcan opened this issue Jan 30, 2019 · 6 comments
Assignees
Milestone

Comments

@eachcan
Copy link

eachcan commented Jan 30, 2019

  • I have searched the issues of this repository and believe that this is not a duplicate.
  • I have checked the FAQ of this repository and believe that this is not a duplicate. (This page is missing)

Environment

  • Dubbo version: 2.7.1-SNAPSHOT
  • Operating System version: MacOSX 10.14.1
  • Java version: 1.8.0_191

Steps to reproduce this issue

  1. Define exception class and other rpc classes
    定义异常类和其他 RPC 相关类

API Defination

public class ValidationException extends RuntimeException {
    public ValidationException(String message) {
        super(message);
    }
}
public interface MailService {
    MailResponse send(MailRequest request);
}
@Data
public class MailRequest implements Serializable {
    /**
     * 收件人邮箱地址
     */
    @NotBlank(message = "收件人不能为空")
    @Email(message = "收件人只能是一个 Email 地址")
    private String to;
}
@Data
public class MailResponse implements Serializable {
    /** 是否成功*/
    private boolean success = true;
}

Provider

@Service(version = "${service.version}",protocol = "${dubbo.protocol.id}",application = "${dubbo.application.name}",registry = "${dubbo.registry.id}",executes = 32)
public class MailServiceImpl implements MailService {
    // ...

    @Override
    public ServerResponse send(MailRequest request) {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<MailRequest>> vset = validator.validate(request);
        if (!vset.isEmpty()) {
            throw new ValidationException(vset.iterator().next().getMessage());
        }
        return new MailResponse();
    }
}

Consumer

            try {
                MailResponse response = mailService.send(request);
                System.out.println(response.isSuccess());
            } catch (Exception e) {
                e.printStackTrace();
            }

Expected Result

此处应当可捕获 ValidationException

Expect ValidationException to be caught.

Actual Result

但是我们捕获到了 UndeclaredThrowableException

java.lang.reflect.UndeclaredThrowableException
	at com.sun.proxy.$Proxy36.send(Unknown Source)
	at test.....MailRunner.lambda$runner$0(MailRunner.java:38)
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804)
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:794)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:324)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
	at test.....MailRunner.main(MailRunner.java:54)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor$ReferenceBeanInvocationHandler.invoke(ReferenceAnnotationBeanPostProcessor.java:159)
	... 8 more
Caused by: ....ValidationException: may not be empty
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at com.googlecode.jsonrpc4j.DefaultExceptionResolver.createThrowable(DefaultExceptionResolver.java:162)
	at com.googlecode.jsonrpc4j.DefaultExceptionResolver.resolveException(DefaultExceptionResolver.java:82)
	at com.googlecode.jsonrpc4j.JsonRpcClient.readResponse(JsonRpcClient.java:345)
	at com.googlecode.jsonrpc4j.JsonRpcClient.readResponse(JsonRpcClient.java:285)
	at com.googlecode.jsonrpc4j.JsonRpcHttpClient.invoke(JsonRpcHttpClient.java:161)
	at com.googlecode.jsonrpc4j.spring.JsonProxyFactoryBean.invoke(JsonProxyFactoryBean.java:136)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
	at com.sun.proxy.$Proxy35.send(Unknown Source)
	at com.alibaba.dubbo.common.bytecode.Wrapper0.invokeMethod(Wrapper0.java)
	at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:47)
	at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:76)
	at com.alibaba.dubbo.rpc.protocol.AbstractProxyProtocol$2.doInvoke(AbstractProxyProtocol.java:97)
	at com.alibaba.dubbo.rpc.protocol.AbstractInvoker.invoke(AbstractInvoker.java:155)
	at com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper.invoke(ListenerInvokerWrapper.java:77)
	at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:62)
	at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)
	at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:75)
	at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)
	at com.alibaba.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke(FutureFilter.java:54)
	at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)
	at com.alibaba.dubbo.rpc.filter.ConsumerContextFilter.invoke(ConsumerContextFilter.java:49)
	at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)
	at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:56)
	at com.alibaba.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:78)
	at com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:244)
	at com.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:75)
	at com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:52)
	at com.alibaba.dubbo.common.bytecode.proxy0.send(proxy0.java)
	... 13 more
@lqclester
Copy link

lqclester commented Jan 31, 2019

遇到相同的问题,现在只能写filter在consumer自行转换

@scm1219
Copy link

scm1219 commented Feb 13, 2019

原因是服务端抛出的异常被java的反射捕获,包装成了InvocationTargetException
然后客户端代理处理异常,发现InvocationTargetException不在接口声明的异常中,就再包装成
UndeclaredThrowableException了

比对了2.6.4和2.6.5,几乎就是重写了ReferenceAnnotationBeanPostProcessor。
评估后发现写转换工程太大了,最终决定修改ReferenceBeanInvocationHandler的invoke代码

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            try{
                 return method.invoke(bean, args);
            }catch(InvocationTargetException ite){
                 throw ite.getTargetException();
            }
        }

临时发布一个patch到本地maven仓中使用,期望未来修复吧

@mercyblitz
Copy link
Contributor

2.6.6 will be resolved, please refer the commit.

@eachcan
Copy link
Author

eachcan commented Feb 13, 2019

@mercyblitz 2.6.6 has been merged into 2.7.0, but this issue is still there.

Should I push a new commit?

@jingege
Copy link

jingege commented Mar 8, 2019

Apache dubbo 2.7.0 has the same issue.

@ikcro
Copy link

ikcro commented Mar 8, 2019

apache dubbo2.7.0 I've tried it and it still doesn't work

@kexianjun kexianjun mentioned this issue Mar 15, 2019
2 tasks
@beiwei30 beiwei30 modified the milestones: 2.6.6, 2.7.1 Mar 15, 2019
@beiwei30 beiwei30 changed the title provider 抛出的异常,consumer 捕获到的总是 java.lang.reflect.UndeclaredThrowableException consumer always catch java.lang.reflect.UndeclaredThrowableException for the exception thrown from provider Mar 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants