测试代码:
namespace java com.meituan.service
exception BugTestException{
1: required i32 code;
2: required string msg;
}
service HelloService {
i32 bugCall() throws (1: BugTestException e);
}
实现类
@Service
public class HelloServiceImpl implements HelloService.Iface {
@Override
public int bugCall() throws BugTestException, TException {
throw new BugTestException(100, "收不到就是bug");
}
}
org.apache.thrift.ProcessFunction
当 getResult 执行出现异常
public static class bugCall_result implements org.apache.thrift.TBase<bugCall_result, bugCall_result._Fields>, java.io.Serializable, Cloneable {
public int success; // required
public BugTestException e; // required
}
@Override
protected bugCall_result getResult(I iface, bugCall_args args) throws org.apache.thrift.TException {
bugCall_result result = new bugCall_result();
try {
result.success = iface.bugCall();
result.setSuccessIsSet(true);
} catch (BugTestException e) {
result.e = e;
}
return result;
}
服务端也是返回 TMessageType.REPLY
result.write(oprot) --com.meituan.service.HelloService.bugCall_result.bugCall_resultStandardScheme#write
此时 struct.success 等于默认的 0,(Class 中基本类型默认值为 0,引用类型默认值为 null)
struct.isSetSuccess() 为 false。
客户端读取操作:
com.meituan.service.HelloService.Client#recv_bugCall
org.apache.thrift.TServiceClient#receiveBase
此时读取到的 msg.type == 2,即 TMessageType.REPLY。
com.meituan.service.HelloService.bugCall_result.bugCall_resultStandardScheme#read
struct.success 读取到默认值 0,thrift 认为读取到了正确的值,所以执行 setSuccessIsSet。
故 com.meituan.service.HelloService.Client#recv_bugCall 直接返回了默认的 0,而没有抛出异常。
解决 1
public int recv_bugCall() throws BugTestException, org.apache.thrift.TException {
bugCall_result result = new bugCall_result();
receiveBase(result, "bugCall");
// 先执行异常检查
if (result.e != null) {
throw result.e;
}
if (result.isSetSuccess()) {
return result.success;
}
throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "bugCall failed: unknown result");
}
解决 2
将 getResult 用 try-catch 包装起来。
这也是 thrift 0.9 版本的解决方案。
try {
result = getResult(iface, args);
} catch(TException tex) {
LOGGER.error("Internal error processing " + getMethodName(), tex);
TApplicationException x = new TApplicationException(TApplicationException.INTERNAL_ERROR,
"Internal error processing " + getMethodName());
oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
x.write(oprot);
oprot.writeMessageEnd();
oprot.getTransport().flush();
return;
}