2016-02-16 12 views
9

デッドシンプルスリフト結合の例です。 ENV:最新の倹約、サーバーなどのcpp、クライアント mytest.thriftなどのJava:スリフトJavaクライアントが適切に共用体を処理できません。

namespace java com.wilbeibi.thrift 

union Value { 
    1: i16  i16_v, 
    2: string str_v, 
} 

struct Box { 
    1: Value value; 
} 

service MyTest { 
    Box echoUnion(1: i32 number); 
} 

C++ server code:

#include "MyTest.h" 
#include <thrift/protocol/TBinaryProtocol.h> 
#include <thrift/server/TSimpleServer.h> 
#include <thrift/transport/TServerSocket.h> 
#include <thrift/transport/TBufferTransports.h> 

using namespace ::apache::thrift; 
using namespace ::apache::thrift::protocol; 
using namespace ::apache::thrift::transport; 
using namespace ::apache::thrift::server; 

using boost::shared_ptr; 

class MyTestHandler : virtual public MyTestIf { 
public: 
    MyTestHandler() { 
    // Your initialization goes here 
    } 

    void echoUnion(Box& _return, const int32_t number) { 
    // Your implementation goes here 
    printf("Into echoUnion\n"); 
    if (number % 2 == 0) { 
    Value v; 
    v.__set_i16_v(100); 
    v.__isset.i16_v = true; 
    _return.__set_value(v); 
    printf("Even number set int32\n"); 
    } else { 
    Value v; 
    v.__set_str_v("String value"); 
    v.__isset.str_v = true; 
    _return.__set_value(v); 
    printf("Odd number set string\n"); 
    } 
    printf("echoUnion\n"); 
    } 

}; 

int main(int argc, char **argv) { 
    int port = 9090; 
    shared_ptr<MyTestHandler> handler(new MyTestHandler()); 
    shared_ptr<TProcessor> processor(new MyTestProcessor(handler)); 
    shared_ptr<TServerTransport> serverTransport(new TServerSocket(port)); 
    shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); 
    shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); 

    TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); 
    printf("Server is running on %d\n", port); 
    server.serve(); 
    return 0; 
} 

java client code

どういうわけか
// some imports here 
public class Client { 
    public void startClient() { 
     TTransport transport; 
      try { 
       transport = new TSocket("localhost", 9090); 
       TProtocol protocol = new TBinaryProtocol(transport); 
       MyTest.Client client = new MyTest.Client(protocol); 
       transport.open(); 
       Box box = client.echoUnion(1);    
       System.out.println(box.toString()); 

       Box box2 = client.echoUnion(2); 
       System.out.println(box2.toString()); 

       transport.close(); 
      } catch (TTransportException e) { 
       e.printStackTrace(); 
      } catch (TException e) { 
       e.printStackTrace(); 
      } 
     } 
    public static void main(String[] args) { 
      Client client = new Client(); 
      client.startClient(); 
     } 
}  

、Javaクライアントが適切に設定された文字列を印刷することはできません。ここでの主旨に

完全なコードを(私はまた、Pythonクライアントを書いたが、それは仕事を思わ):

答えて

3

thrift file, c++ and java codeは実際にあなたが組合の種類の不正なC++コードを生成するコンパイラを引き起こすTHRIFT-1833バグを観察しています。

あなたのケースでは、サーバは両方のフィールドをユニオンタイプで書き込みますが、クライアントは常に最初の1つだけを読み込みます - i16_v(残りのバイトはまだバッファにあります)。したがって、バッファ内の予期しないデータが検出されるため、2番目の読み取りは終了しません。

unionの代わりにstructを使用して、シングルフィールドロジックを手動で維持することができます。あるいは、バグが修正されるまで、あなたは貢献するか待つことができます。

--- mytest_types.cpp 2016-02-26 20:02:57.210652969 +0300 
+++ mytest_types.cpp.old 2016-02-26 20:02:39.650652742 +0300 
@@ -80,13 +80,17 @@ 
apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 
xfer += oprot->writeStructBegin("Value"); 

- xfer += oprot->writeFieldBegin("i16_v", ::apache::thrift::protocol::T_I16, 1); 
- xfer += oprot->writeI16(this->i16_v); 
- xfer += oprot->writeFieldEnd(); 
+ if (this->__isset.i16_v) { 
+ xfer += oprot->writeFieldBegin("i16_v", ::apache::thrift::protocol::T_I16, 1); 
+ xfer += oprot->writeI16(this->i16_v); 
+ xfer += oprot->writeFieldEnd(); 
+ } 

- xfer += oprot->writeFieldBegin("str_v", ::apache::thrift::protocol::T_STRING, 2); 
- xfer += oprot->writeString(this->str_v); 
- xfer += oprot->writeFieldEnd(); 
+ if (this->__isset.str_v) { 
+ xfer += oprot->writeFieldBegin("str_v", ::apache::thrift::protocol::T_STRING, 2); 
+ xfer += oprot->writeString(this->str_v); 
+ xfer += oprot->writeFieldEnd(); 
+ } 

最後のオプションは、このような誤って生成C++ソースコードにパッチを適用しています

関連する問題