首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

thrift 0.8 java客户端无法catch错误

2012-08-11 
thrift 0.8java客户端无法catch异常问题描述:??? 当方法返回值为thrift基本类型(i64,bool...)时,客户端无

thrift 0.8 java客户端无法catch异常


问题描述:
??? 当方法返回值为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修改代码,开发代价太大。所以想请教下大牛们是如何解决这个问题的。
???
???

1 楼 zhengjie110120 2012-05-16   换成0.6.1 没有这个问题

热点排行