222

Does the rpc syntax in proto3 allow null requests or responses?

e.g. I want the equivalent of the following:

rpc Logout;
rpc Status returns (Status);
rpc Log (LogData);

Or should I just create a null type?

message Null {};

rpc Logout (Null) returns (Null);
rpc Status (Null) returns (Status);
rpc Log (LogData) returns (Null);
Dharman
  • 30,962
  • 25
  • 85
  • 135

3 Answers3

308

Kenton's comment below is sound advice:

... we as developers are really bad at guessing what we might want in the future. So I recommend being safe by always defining custom params and results types for every method, even if they are empty.


Answering my own question:

Looking through the default proto files, I came across Empty that is exactly like the Null type I suggested above :)

excerpt from that file:

// A generic empty message that you can re-use to avoid defining duplicated
// empty messages in your APIs. A typical example is to use it as the request
// or the response type of an API method. For instance:
//
//     service Foo {
//       rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
//     }
//

message Empty {

}
Ryan M
  • 18,333
  • 31
  • 67
  • 74
  • 50
    Yes. Empty is the canonical "I don't care" request or response. I will note, if you think you _may_ want arguments or return values in the future, make a new message that simply has no fields. That way you can add new fields when you need to and not break any application code. Empty is great for when you will never want arguments or return values. – Eric Anderson Aug 03 '15 at 16:38
  • 58
    @EricAnderson is mostly right, but I would argue that we as developers are _really bad_ at guessing what we might want in the future. So I recommend being safe by always defining custom params and results types for every method, even if they are empty. – Kenton Varda Aug 04 '15 at 02:56
  • 1
    "... we as developers are really bad at guessing what we might want in the future.", This would require a seperate `Empty` message for each individual function call? That's quite a sacrifice. – Robert de W Jul 14 '20 at 08:29
  • 5
    Does `returns (google.protobuf.Empty);` make the call non-blocking? – Paul Williams Feb 23 '21 at 06:14
  • 3
    The GRPC wire format supports replacing Empty with a message that has fields in a backwards compatible way, so you don't need a new empty message type for that reason. Having a separate message makes it easier on source code level. See https://stackoverflow.com/questions/50993815/is-google-protobuf-empty-dangerous-for-backwards-compatibility – Erwin Bolwidt Mar 21 '21 at 23:19
  • @PaulWilliams Have you found an answer to your question? – user2233706 Dec 19 '22 at 16:44
  • @user2233706 it does not make the call non-blocking. You can use an Async Stub to make non-blocking calls. The Blocking Stub still waits for the onCompleted() or onError(). – cmcnealy Aug 17 '23 at 21:07
134

You also can use predefined:

import "google/protobuf/empty.proto";
package MyPackage;

service MyService {
  rpc Check(google.protobuf.Empty) returns (google.protobuf.Empty) {}
}
hdnn
  • 1,807
  • 3
  • 13
  • 20
-3

you can also use another bool property inside the Reply structure. like this

message Reply {
  string result = 1;
  bool found = 2;
}

so if you dont find the result or some error happened you can return from the service class this

return new Reply()
{
   Found = false
};
dkokkinos
  • 361
  • 2
  • 9
  • 6
    GRPC status code NOT_FOUND (5) already exists for this purpose. https://grpc.github.io/grpc/core/md_doc_statuscodes.html Errors should be signalled using a grpc status. – Erwin Bolwidt Mar 21 '21 at 23:15
  • I actually think it's quite bad practice to use this, because using an explicit status code is always better than setting a boolean somewhere in a message. Nothing gaurantees you will check the boolean, but you do have a gaurantee that you will check the status code. – Bobbbay Nov 25 '21 at 18:38