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++ namespacetutorial
. 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 casetutorial.tutorial
. In the unit-tests, we use a filetest.thrift
, which declares a namespacethrift_test
. The key there would bethrift_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 useTNiceJSONProtocolFactory("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 sureNiceJSON.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.
--- ../../../../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 {