17.3. Performing Remote Queries via the Hot Rod C++ Client
The Hot Rod C++ client allows remote querying, using Google's Protocol Buffers, once the
RemoteCacheManager
has been configured with the Protobuf marshaller.
Important
Remote Querying is a Technology Preview feature of the C++ client in JBoss Data Grid 7.0.0.
Procedure 17.2. Enable Remote Querying on the Hot Rod C++ Client
- Obtain a connection to the remote JBoss Data Grid server:
#include "addressbook.pb.h" #include "bank.pb.h" #include <infinispan/hotrod/BasicTypesProtoStreamMarshaller.h> #include <infinispan/hotrod/ProtoStreamMarshaller.h> #include "infinispan/hotrod/ConfigurationBuilder.h" #include "infinispan/hotrod/RemoteCacheManager.h" #include "infinispan/hotrod/RemoteCache.h" #include "infinispan/hotrod/Version.h" #include "infinispan/hotrod/query.pb.h" #include "infinispan/hotrod/QueryUtils.h" #include <vector> #include <tuple> #define PROTOBUF_METADATA_CACHE_NAME "___protobuf_metadata" #define ERRORS_KEY_SUFFIX ".errors" using namespace infinispan::hotrod; using namespace org::infinispan::query::remote::client; std::string read(std::string file) { std::ifstream t(file); std::stringstream buffer; buffer << t.rdbuf(); return buffer.str(); } int main(int argc, char** argv) { std::cout << "Tests for Query" << std::endl; ConfigurationBuilder builder; builder.addServer().host(argc > 1 ? argv[1] : "127.0.0.1").port(argc > 2 ? atoi(argv[2]) : 11222).protocolVersion(Configuration::PROTOCOL_VERSION_24); RemoteCacheManager cacheManager(builder.build(), false); cacheManager.start();
- Create the Protobuf metadata cache with the Protobuf Marshaller:
// This example continues the previous codeblock // Create the Protobuf Metadata cache peer with a Protobuf marshaller auto *km = new BasicTypesProtoStreamMarshaller<std::string>(); auto *vm = new BasicTypesProtoStreamMarshaller<std::string>(); auto metadataCache = cacheManager.getCache<std::string, std::string>( km, &Marshaller<std::string>::destroy, vm, &Marshaller<std::string>::destroy,PROTOBUF_METADATA_CACHE_NAME, false);
- Install the data model in the Protobuf metadata cache:
// This example continues the previous codeblock // Install the data model into the Protobuf metadata cache metadataCache.put("sample_bank_account/bank.proto", read("proto/bank.proto")); if (metadataCache.containsKey(ERRORS_KEY_SUFFIX)) { std::cerr << "fail: error in registering .proto model" << std::endl; return -1; }
- This step adds data to the cache for the purposes of this demonstration, and may be ignored when simply querying a remote cache:
// This example continues the previous codeblock // Fill the cache with the application data: two users Tom and Jerry testCache.clear(); sample_bank_account::User_Address a; sample_bank_account::User user1; user1.set_id(3); user1.set_name("Tom"); user1.set_surname("Cat"); user1.set_gender(sample_bank_account::User_Gender_MALE); sample_bank_account::User_Address * addr= user1.add_addresses(); addr->set_street("Via Roma"); addr->set_number(3); addr->set_postcode("202020"); testCache.put(3, user1); user1.set_id(4); user1.set_name("Jerry"); user1.set_surname("Mouse"); addr->set_street("Via Milano"); user1.set_gender(sample_bank_account::User_Gender_MALE); testCache.put(4, user1);
- Query the remote cache:
// This example continues the previous codeblock // Simple query to get User objects { QueryRequest qr; std::cout << "Query: from sample_bank_account.User" << std::endl; qr.set_jpqlstring("from sample_bank_account.User"); QueryResponse resp = testCache.query(qr); std::vector<sample_bank_account::User> res; unwrapResults(resp, res); for (auto i = 0; i < res.size(); i++) { std::cout << "User(id=" << res[i].id() << ",name=" << res[i].name() << ",surname=" << res[i].surname() << ")" << std::endl; } } cacheManager.stop(); return 0; }
Additional Query Examples
The following examples are included to demonstrate more complicated queries, and may be used on the same dataset found in the above procedure.
Example 17.3. Using a query with a conditional
// Simple query to get User objects with where condition { QueryRequest qr; std::cout << "from sample_bank_account.User u where u.addresses.street=\"Via Milano\"" << std::endl; qr.set_jpqlstring("from sample_bank_account.User u where u.addresses.street=\"Via Milano\""); QueryResponse resp = testCache.query(qr); std::vector<sample_bank_account::User> res; unwrapResults(resp, res); for (auto i = 0; i < res.size(); i++) { std::cout << "User(id=" << res[i].id() << ",name=" << res[i].name() << ",surname=" << res[i].surname() << ")" << std::endl; } }
Example 17.4. Using a query with a projection
// Simple query to get projection (name, surname) { QueryRequest qr; std::cout << "Query: select u.name, u.surname from sample_bank_account.User u" << std::endl; qr.set_jpqlstring( "select u.name, u.surname from sample_bank_account.User u"); QueryResponse resp = testCache.query(qr); //Typed resultset std::vector<std::tuple<std::string, std::string> > prjRes; unwrapProjection(resp, prjRes); for (auto i = 0; i < prjRes.size(); i++) { std::cout << "Name: " << std::get<0> (prjRes[i]) << " Surname: " << std::get<1> (prjRes[i]) << std::endl; } }