0

Question: It is possible to request data in gRPC similar with a http request with params?

Details: I work on a maven java project with gRPC. Below is a simplified code of my .proto file.

syntax = "proto3"; 

service BookService{
  rpc getBooks(Empty) returns (stream Book);
  /* Other functions */
}

message Book {
  int32 id = 1;
  string title = 2;
  int32 total_pages = 3;
  string publisher = 4;
  string authors = 5;
}

message Empty {
  /* EMPTY */
}

On JavaFX Client I receive the data ( a list of books ) and print it in a ListView (image of GUI below) enter image description here

As you can see, I show only the title, but when I request the data, I receive all information.

Now I did something like this:

stub.getBooks(BookOuterClass.Empty.newBuilder().build(), new StreamObserver<BookOuterClass.Book>() {
                    @Override
                    /* Receive the stream of data from the server */
                    public void onNext(BookOuterClass.Book currentBook) {
                        publishProgress(currentBook.getTitle().toString(), loadingBooksCounter);
                        loadingBooksCounter++;
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        System.out.println("Error : " + throwable.getMessage());
                    }

                    @Override
                    public void onCompleted() {
                        controller.getBooksListViewLoadingBar().setVisible(false);
                    }
                });

Obs: publishProgress - show the data dynamically as I receive it in ListView and load a progress bar below it.

What I want to try:

  1. GetBooks with a message request like this:
    message Params {
      bool with_id = 1;
      bool with_title = 2;
      bool with_total_pages = 3;
      bool with_publisher = 4;
      bool with_authors = 5;
    }

Two problems:

  • All values will be false by default.
  • The response is still an object with all that fields, let's say I request with field with_title set true, now I got a Book with all fields (id, title, total_pages etc.), but only the title does not have a default value.
  1. Make multiple Book messages with different fields.
    That are called by different rpc fucntions, ex:
  service BookService {
    rpc getBookTitles(Empty) returns (stream BookTitle);
    rpc getBookIdTitles(Empty) returns (stream BookIdTitle);
  }

Problems:

  • For each new combination of fields another function, and most probably another message too.
  1. Make a Params message request and a Book message response which can be any Book message:
import "google/protobuf/any.proto";

service BookService {
  rpc getBooks(Params) returns (stream Book);
}

message Book {
  google.protobuf.Any book_type = 1;
}

message BookTitle {
  string title = 1;
}

message BookIdTitle {
  int32 id = 1;
  string title = 2;
}
  • Still I have a lot of messages...

So the option 3 is somewhere between opt. 1 and opt. 2.

  • Have you seen FieldMask? https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/field_mask.proto There's a util in most languages to filter a message based on the mask. You may also glance at https://stackoverflow.com/a/62939028/4690866 . – Eric Anderson Mar 30 '21 at 00:01
  • @EricAnderson I am amazed, this is very useful! I am grateful for your answer, I will do some tests with FieldMasks as soon as I can! – Mihai Lucian Rîtan Mar 30 '21 at 00:18

0 Answers0