问题描述:
当方法返回值为thrift基本类型(i64,bool...)时,客户端无法捕捉异常。
ps.当方法返回值为用户定义的类型时,不会出现该问题。
注意 thrift 版本0.8
跟踪thrift代码发现,问题出现的原因:
step 1: 服务端,写数据
(基本类型) 不会先判断返回值是否为空,基本类型也无法判断是否为空
oprot.writeStructBegin(STRUCT_DESC);
oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
oprot.writeI64(struct.success);
oprot.writeFieldEnd();
(用户定义类型) 会先判断返回值是否为空
if (struct.success != null) {
oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
{
oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
for (Province _iter3 : struct.success)
{
_iter3.write(oprot);
}
oprot.writeListEnd();
}
oprot.writeFieldEnd();
}
}
step 2: 客户端读数据
(基本类型) 服务端写数据时,一定会写入返回值的TField,所以读到的第一个TFIELD 一定会进入case0. 其中执行了 struct.setSuccessIsSet(true); 方法标示 返回值已写入
switch (schemeField.id) {
case 0: // SUCCESS
if (schemeField.type == TType.I64) {
struct.success = iprot.readI64();
struct.setSuccessIsSet(true);
}
else {
TProtocolUtil.skip(iprot, schemeField.type);
}
break;
case 1: // USER_EXCEPTION
//................
default:
TProtocolUtil.skip(iprot, schemeField.type);
}
(用户定义类型) 服务端写数据时,经过判断未写入返回值TField, 因此直接进入case 1
switch (schemeField.id) {
case 0: // SUCCESS
// ................
break;
case 1: // COMMON_EXCEPTION
// .................
}
step 3: 客户端处理返回结果 执行recv_****方法时
if (result.isSetSuccess()) {
return result.success;
}
if (result.commonException != null) {
throw result.commonException;
}
(基本类型) 由于基本类型在step2中执行了setSuccessIsSet(true);
因此第一个if总是为真,在这步方法已经返回。
不能够进入第二个if.捕捉异常
(用户定义类型) 用户类型。如果产生异常则跳过第一个if,能够在第二个if块中捕捉到异常
我想到的解决方法:
方法1. 更改step1
oprot.writeStructBegin(STRUCT_DESC);
oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
oprot.writeI64(struct.success);
oprot.writeFieldEnd();
更改为
oprot.writeStructBegin(STRUCT_DESC);
if (this.isSetSuccess()) {
oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
oprot.writeI64(struct.success);
oprot.writeFieldEnd();
}
方法2. 更改step3
将recv_****方法中
if (result.isSetSuccess()) {
return result.success;
}
if (result.commonException != null) {
throw result.commonException;
}
更改顺序变为
if (result.commonException != null) {
throw result.commonException;
}
if (result.isSetSuccess()) {
return result.success;
}
问题得到解决
但是由于 这样需要为每个生成的Iface修改代码,开发代价太大。所以想请教下大牛们是如何解决这个问题的。
分享到:
相关推荐
Thrift Java 服务器 客户端通信,网上看到的,觉得不错就分享出来供大家一起共同分享学习。
一个简单的demo,关于使用thrift进行跨语言服务间的通信
Thrift RPC客户端的服务化框架代码,
Thrift下java服务器与客户端开发指南[归纳].pdf
Thrift下java服务器与客户端开发指南.pdf
Thrift下java服务器与客户端开发指引.pdf
Thrift下java服务器与客户端开发指南.doc
Apache Thrift Java实战源码,包含了客户端和服务端源码,客户端和服务端是分开的,如果需要放到一个工程,直接把Client.java文件复制到服务端运行即可。
Thrift下java服务器与客户端开发指南文.pdf
Thrift下java服务器与客户端开发指南实用.pdf
Thrift下java服务器与客户端开发指南[借鉴].pdf
一个java和python的thrift例子,其中java作为服务端,python作为客户端
Nifty是facebook公司开源的,基于netty的thrift服务端和客户端实现。 然后使用此包就可以快速发布出基于netty的高效的服务端和客户端代码。 示例: public void startServer() { // Create the handler ...
Thrift下java服务器与客户端开发指南【精选文档】.doc
thrift java build jar
Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。接下来通过本文给大家介绍Java thrift服务器和客户端创建实例代码,需要的朋友参考下吧
thrift安装包以及JAVA的一个测试项目