Skip to content

Latest commit

 

History

History
176 lines (144 loc) · 6.25 KB

tutorial.asciidoc

File metadata and controls

176 lines (144 loc) · 6.25 KB

thrift-nicejson Tutorial

The Thrift C++ Tutorial Example

The first example will be modify the Thrift C++ tutorial example. Further below you’ll find the diffs, and below you’ll find an explanation of the steps required. You’ll also find the fully-worked-out example in src/examples/cpp.

Note
below, we’ll pretend that you’ve already installed thrift-nicejson, and are building a project separately. In src/examples/cpp, we assume it’s being built as part of the project from source (hence, via autotools). The difference is that (for instance) we assume various files are already installed).
1

Start off by making sure you can build and run the example, just so you know thrift is installed correctly and you have all your paths straight.

2

The thrift file tutorial.thrift declares a C++ namespace tutorial. The way this nicejson support works, is that a "type libary" is generated, and stored under a "key" of the form <namespace>.<file-basename>. In this case tutorial.tutorial. In the unit-tests, we use a file test.thrift, which declares a namespace thrift_test. The key there would be thrift_test.test. Make a note of the namespace that your Thrift IDL file declares — you’ll use it later.

3

Generate C++ files as usual:

thrift -r --gen cpp tutorial.thrift
4

Generate C++ typelib files (using the nicejson typelib plugin)

thrift -r --gen typelib:cpp,typelib tutorial.thrift

The latter command generates C++ typelib files into gen-cpp-typelib and binary and JSON typelib files into gen-typelib. Since tutorial.thrift uses another thrift file shared.thrift, it generates two sets of files (tutorial_* and shared_*), just as for cpp generation above.

Note
this command uses the plugin command thrift-gen-typelib which should have been built and installed by your install of this project. Again, in src/examples/cpp the assumption is that the example is being built without being installed so the invocation is run with a modified $PATH.
5

Instead of a TBinaryProtocolFactory() in CppClient.cpp and CppServer.cpp, you need to use TNiceJSONProtocolFactory("tutorial.tutorial", "Calculator"). Let’s unpack this: we’re specifying that a NiceJSON protocol be used, and supplying the typelib-name (tutorial.tutorial) and the service-name (Calculator). This will allow the runtime to lookup type metadata for the specified service in the specified typelib.

We also replaced TBufferedTransportFactory() with THttpServerTransportFactory() (in the server) and TBufferedTransport(socket) with THttpClient(socket, "localhost", "/service") (in the client) in order to use HTTP instead of raw TCP (though that works too). Later we’ll be able to use command-line tools to invoke the server via HTTP.

6

The C typelib files must be compiled, just like the C gen-cpp (and Cpp{Client,Server}.cpp). When compiling, we’ll need to make sure NiceJSON.h (which should be installed) is on the include-path.

7

When linking, we’ll need to link with libnicejson.a and a few Boost libraries (typically, boost_system, boost_filesystem, boost_thread).

8

You should be able to run these examples just like the unmodified ones. But of course, you can’t tell that they’re talking JSON-over-HTTP without (e.g.) a packet-sniffer. But you can invoke them with JSON-over-HTTP:

% POST -c 'application/x-thrift' http://localhost:9090/
Please enter content (application/x-thrift) to be POSTed:
{"body":{"num1":1,"num2":1},"name":"add","seqid":0,"type":"call"}
<EOF>

replies with

{"body":{"success":2},"name":"add","seqid":0,"type":"reply"}

And that’s really it! The detailed diffs (between the Thrift C++ Calculator example and our modified version) are below.

The Diffs (Server and Client)

--- ../../../../thrift/tutorial/cpp/CppServer.cpp       2017-11-18 16:07:35.829042647 -0800
+++ CppServer.cpp       2017-11-23 14:36:30.171197285 -0800
@@ -26,6 +26,8 @@
 #include <thrift/transport/TServerSocket.h>
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TTransportUtils.h>
+#include <thrift/transport/THttpServer.h>
+#include <thrift/transport/THttpClient.h>
 #include <thrift/TToString.h>

 #include <boost/make_shared.hpp>
@@ -34,7 +36,9 @@
 #include <stdexcept>
 #include <sstream>

-#include "../gen-cpp/Calculator.h"
+#include "TNiceJSONProtocol.h"
+#include "NiceJSON.h"
+#include "gen-cpp/Calculator.h"

 using namespace std;
 using namespace apache::thrift;
@@ -131,12 +135,14 @@
   }
 };

+const std::string kTestTypelib = "tutorial.tutorial" ;
+
 int main() {
   TThreadedServer server(
     boost::make_shared<CalculatorProcessorFactory>(boost::make_shared<CalculatorCloneFactory>()),
     boost::make_shared<TServerSocket>(9090), //port
-    boost::make_shared<TBufferedTransportFactory>(),
-    boost::make_shared<TBinaryProtocolFactory>());
+    boost::make_shared<THttpServerTransportFactory>(),
+    boost::make_shared<TNiceJSONProtocolFactory>(kTestTypelib, "Calculator"));

   /*
   // if you don't need per-connection state, do the following instead
--- ../../../../thrift/tutorial/cpp/CppClient.cpp       2017-11-18 16:07:35.829042647 -0800
+++ CppClient.cpp       2017-11-23 14:36:40.178970140 -0800
@@ -22,8 +22,12 @@
 #include <thrift/protocol/TBinaryProtocol.h>
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TTransportUtils.h>
+#include <thrift/transport/THttpServer.h>
+#include <thrift/transport/THttpClient.h>

-#include "../gen-cpp/Calculator.h"
+#include "TNiceJSONProtocol.h"
+#include "NiceJSON.h"
+#include "gen-cpp/Calculator.h"

 using namespace std;
 using namespace apache::thrift;
@@ -33,10 +37,12 @@
 using namespace tutorial;
 using namespace shared;

+const std::string kTestTypelib = "tutorial.tutorial" ;
+
 int main() {
   boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
-  boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
-  boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
+  boost::shared_ptr<TTransport> transport(new THttpClient(socket, "localhost", "/service"));
+  boost::shared_ptr<TProtocol> protocol(new TNiceJSONProtocol(kTestTypelib, "Calculator", transport));
   CalculatorClient client(protocol);

   try {