From 8e9a709d47fcf79379cb04fa0d98a03f5915f8b4 Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Thu, 12 Feb 2015 17:48:42 +0000 Subject: [PATCH 1/7] More tidying up of example... --- README.md | 70 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index c7c896db61d..bd0738447a8 100644 --- a/README.md +++ b/README.md @@ -118,10 +118,11 @@ familiar with protocol buffers, you can find out more in the [Protocol Buffers Developer Guide](https://developers.google.com/protocol-buffers/docs/overview). Here's our example service definition, defined using protocol buffers IDL in -[helloworld.proto](java/src/main/proto/helloworld.proto) _should we link to the version in the Java subdirectory or the one in the common protos directory?_. The `Greeting` service +[helloworld.proto](java/src/main/proto/helloworld.proto). The `Greeting` service has one method, `hello`, that lets the server receive a single `HelloRequest` message from the remote client containing the user's name, then send back -a greeting in a `HelloReply`. +a greeting in a single `HelloReply`. This is the simplest type of RPC you +can specify in gRPC - we'll look at some other types later in this document. ``` syntax = "proto3"; @@ -167,7 +168,8 @@ this up in "what is gRPC"?] the example, you can skip this step and move onto the next one where we examine the generated code.) -As this is our first time using gRPC, we need to build the protobuf plugin that generates our RPC +As this is our first time using gRPC, we need to build the protobuf plugin +that generates our RPC classes. By default `protoc` just generates code for reading and writing protocol buffers, so you need to use plugins to add additional features to generated code. As we're creating Java code, we use the gRPC Java plugin. @@ -190,17 +192,22 @@ $ protoc -I . helloworld.proto --java_out=src/main/java ``` -This generates the following classes, which contain all the generated code we need to create our example: +This generates the following classes, which contain all the generated code +we need to create our example: -- [`Helloworld.java`](java/src/main/java/ex/grpc/Helloworld.java), which has all the protocol buffer code to populate, serialize, and retrieve our `HelloRequest` and `HelloReply` message types -- [`GreetingsGrpc.java`](java/src/main/java/ex/grpc/GreetingsGrpc.java), which contains (along with some other useful code): +- [`Helloworld.java`](java/src/main/java/ex/grpc/Helloworld.java), which +has all the protocol buffer code to populate, serialize, and retrieve our +`HelloRequest` and `HelloReply` message types +- [`GreetingsGrpc.java`](java/src/main/java/ex/grpc/GreetingsGrpc.java), +which contains (along with some other useful code): - an interface for `Greetings` servers to implement ```java public static interface Greetings { public void hello(ex.grpc.Helloworld.HelloRequest request, - com.google.net.stubby.stub.StreamObserver responseObserver); + com.google.net.stubby.stub.StreamObserver + responseObserver); } ``` @@ -208,7 +215,8 @@ This generates the following classes, which contain all the generated code we ne ```java public static class GreetingsStub extends - com.google.net.stubby.stub.AbstractStub + com.google.net.stubby.stub.AbstractStub implements Greetings { ... } @@ -217,48 +225,58 @@ public static class GreetingsStub extends ### Writing a server -Now let's write some code! First we'll create a server application to implement our service. Note that we're not going to go into a lot of detail about how to create a server in this section More detailed information will be in the tutorial for your chosen language (coming soon). +Now let's write some code! First we'll create a server application to implement +our service. Note that we're not going to go into a lot of detail about how +to create a server in this section More detailed information will be in the +tutorial for your chosen language (coming soon). Our server application has two classes: -- a simple service implementation [GreetingsImpl.java](java/src/main/java/ex/grpc/GreetingsImpl.java). +- a simple service implementation +[GreetingsImpl.java](java/src/main/java/ex/grpc/GreetingsImpl.java). -- a server that hosts the service implementation and allows access over the network: [GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java). +- a server that hosts the service implementation and allows access over the +network: [GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java). #### Service implementation [GreetingsImpl.java](java/src/main/java/ex/grpc/GreetingsImpl.java) -implements the behaviour we require of our GreetingService. There are a -number of important features of gRPC being used here: +actually implements our GreetingService's required behaviour. + +As you can see, the class `GreetingsImpl` implements the interface +`GreetingsGrpc.Greetings` that we [generated](#generating) from our proto +[IDL](src/main/proto/helloworld.proto) by implementing the method `hello`: ```java public void hello(Helloworld.HelloRequest req, StreamObserver responseObserver) { - Helloworld.HelloReply reply = Helloworld.HelloReply.newBuilder().setMessage( + Helloworld.HelloReply reply = + Helloworld.HelloReply.newBuilder().setMessage( "Hello " + req.getName()).build(); responseObserver.onValue(reply); responseObserver.onCompleted(); } ``` - -- it provides a class `GreetingsImpl` that implements a generated interface `GreetingsGrpc.Greetings` -- `GreetingsGrpc.Greetings` declares the method `hello` that was declared in the proto [IDL](src/main/proto/helloworld.proto) - `hello's` signature is typesafe: - hello(Helloworld.HelloRequest req, StreamObserver responseObserver) + `hello(Helloworld.HelloRequest req, StreamObserver + responseObserver)` - `hello` takes two parameters: - `Helloworld.HelloRequest`: the request - `StreamObserver`: a response observer, an interface to be called with the response value -- to complete the call - - the return value is constructed - - the responseObserver.onValue() is called with the response - - responseObserver.onCompleted() is called to indicate that no more work will done on the RPC. + -`Helloworld.HelloRequest`: the request + -`StreamObserver`: a response observer, which is + a special interface for the server to call with its response +To return our response to the client and complete the call: +1. We construct and populate a `HelloReply` response object with our exciting +message, as specified in our interface definition. +2. We call `responseObserver.onValue()` with the `HelloReply` that we want to send back to the client. +3. Finally, we call `responseObserver.onCompleted()` to indicate that we're +finished dealing with this RPC. #### Server implementation [GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java) shows the -other main feature required to provde the gRPC service; how to allow a service -implementation to be accessed from the network. +other main feature required to provde the gRPC service; making the service +implementation available from the network. ```java private void start() throws Exception { From 2fdb96388faa6ef94fd768ba921dcf0a3ffe9a39 Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Thu, 12 Feb 2015 17:51:13 +0000 Subject: [PATCH 2/7] Style tweaks --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bd0738447a8..89e8d2942c3 100644 --- a/README.md +++ b/README.md @@ -264,11 +264,12 @@ As you can see, the class `GreetingsImpl` implements the interface -`Helloworld.HelloRequest`: the request -`StreamObserver`: a response observer, which is a special interface for the server to call with its response + To return our response to the client and complete the call: -1. We construct and populate a `HelloReply` response object with our exciting + 1. We construct and populate a `HelloReply` response object with our exciting message, as specified in our interface definition. -2. We call `responseObserver.onValue()` with the `HelloReply` that we want to send back to the client. -3. Finally, we call `responseObserver.onCompleted()` to indicate that we're + 2. We call `responseObserver.onValue()` with the `HelloReply` that we want to send back to the client. + 3. Finally, we call `responseObserver.onCompleted()` to indicate that we're finished dealing with this RPC. From 034eb2e8097262ee9a6a543f47ab9baa15a92b92 Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Fri, 13 Feb 2015 11:05:25 +0000 Subject: [PATCH 3/7] Markdown, I hate you. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 89e8d2942c3..cc0ce4943fd 100644 --- a/README.md +++ b/README.md @@ -213,14 +213,14 @@ which contains (along with some other useful code): - _stub_ classes that clients can use to talk to a `Greetings` server. - ```java +```java public static class GreetingsStub extends com.google.net.stubby.stub.AbstractStub implements Greetings { ... } - ``` +``` ### Writing a server @@ -266,6 +266,7 @@ As you can see, the class `GreetingsImpl` implements the interface a special interface for the server to call with its response To return our response to the client and complete the call: + 1. We construct and populate a `HelloReply` response object with our exciting message, as specified in our interface definition. 2. We call `responseObserver.onValue()` with the `HelloReply` that we want to send back to the client. From 31d143ce0745b485b315c56c1715dc46fe060a5e Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Fri, 13 Feb 2015 11:07:16 +0000 Subject: [PATCH 4/7] AAAAAAARRRGHHHHH --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cc0ce4943fd..16304f65eb3 100644 --- a/README.md +++ b/README.md @@ -213,14 +213,14 @@ which contains (along with some other useful code): - _stub_ classes that clients can use to talk to a `Greetings` server. -```java + ```java public static class GreetingsStub extends com.google.net.stubby.stub.AbstractStub implements Greetings { ... } -``` + ``` ### Writing a server @@ -267,10 +267,10 @@ As you can see, the class `GreetingsImpl` implements the interface To return our response to the client and complete the call: - 1. We construct and populate a `HelloReply` response object with our exciting +1. We construct and populate a `HelloReply` response object with our exciting message, as specified in our interface definition. - 2. We call `responseObserver.onValue()` with the `HelloReply` that we want to send back to the client. - 3. Finally, we call `responseObserver.onCompleted()` to indicate that we're +2. We call `responseObserver.onValue()` with the `HelloReply` that we want to send back to the client. +3. Finally, we call `responseObserver.onCompleted()` to indicate that we're finished dealing with this RPC. From 0af588a9cf75fd5769bb3bca5a978a3463f80668 Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Fri, 13 Feb 2015 15:42:03 +0000 Subject: [PATCH 5/7] More tidying up of existing text --- README.md | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 16304f65eb3..8f6fd5cc6d5 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,7 @@ which contains (along with some other useful code): } ``` - - _stub_ classes that clients can use to talk to a `Greetings` server. + - _stub_ classes that clients can use to talk to a `Greetings` server. As you can see, they also implement the `Greetings` interface. ```java public static class GreetingsStub extends @@ -236,7 +236,7 @@ Our server application has two classes: [GreetingsImpl.java](java/src/main/java/ex/grpc/GreetingsImpl.java). - a server that hosts the service implementation and allows access over the -network: [GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java). +network: [GreetingsServer.java](java/src/main/java/ex/grpc/GreetingsServer.java). #### Service implementation @@ -245,7 +245,7 @@ actually implements our GreetingService's required behaviour. As you can see, the class `GreetingsImpl` implements the interface `GreetingsGrpc.Greetings` that we [generated](#generating) from our proto -[IDL](src/main/proto/helloworld.proto) by implementing the method `hello`: +[IDL](java/src/main/proto/helloworld.proto) by implementing the method `hello`: ```java public void hello(Helloworld.HelloRequest req, @@ -276,11 +276,13 @@ finished dealing with this RPC. #### Server implementation -[GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java) shows the -other main feature required to provde the gRPC service; making the service +[GreetingsServer.java](java/src/main/java/ex/grpc/GreetingsServer.java) shows the +other main feature required to provide a gRPC service; making the service implementation available from the network. ```java + private ServerImpl server; + ... private void start() throws Exception { server = NettyServerBuilder.forPort(port) .addService(GreetingsGrpc.bindService(new GreetingsImpl())) @@ -291,9 +293,9 @@ implementation available from the network. ``` -- it provides a class `GreetingsServer` that holds a `ServerImpl` that will run the server -- in the `start` method, `GreetingServer` binds the `GreetingsService` implementation to a port and begins running it -- there is also a `stop` method that takes care of shutting down the service and cleaning up when the program exits +The `GreetingsServer` class has a `ServerImpl` member that actually runs the server. To create an appropriate `ServerImpl`, we use a special `ServerBuilder` class (in this case a `NettyServerBuilder`) in the `GreetingsServer`'s `start` method, binding the `GreetingsService` implementation that we created to a port. Then we start the server running: the server is now ready to receive requests from `Greetings` service clients on our specified port. We'll cover how all this works in a bit more detail in our language-specific documentation. + +`GreetingsServer` also has a `stop` method that takes care of shutting down the service and cleaning up when the program exits. #### Build it @@ -308,16 +310,16 @@ We'll look at using a client to access the server in the next section. ### Writing a client -Client-side gRPC is pretty simple. In this step, we'll use the generated code to write a simple client that can access the `Greetings` server we created in the previous section. You can see the complete client code in [GreetingsClient.java](src/main/java/ex/grpc/GreetingsClient.java). +Client-side gRPC is pretty simple. In this step, we'll use the generated code to write a simple client that can access the `Greetings` server we created in the [previous section](#server). You can see the complete client code in [GreetingsClient.java](java/src/main/java/ex/grpc/GreetingsClient.java). Again, we're not going to go into much detail about how to implement a client - we'll leave that for the tutorial. #### Connecting to the service -. The internet address -is configured in the client constructor. gRPC Channel is the abstraction over +First let's look at how we connect to the `Greetings` server. The internet address +is configured in the client constructor. gRPC `Channel` provides the abstraction layer over transport handling; its constructor accepts the host name and port of the -service. The channel in turn is used to construct the Stub. +service. The channel in turn is used to construct the stub instance. ```java @@ -335,11 +337,11 @@ service. The channel in turn is used to construct the Stub. #### Obtaining a greeting -The greet method uses the stub to contact the service and obtain a greeting. -It: -- constructs a request -- obtains a reply from the stub -- prints out the greeting +The `greet()` method uses the stub to contact the service and obtain a greeting. +In the method we: +- construct and fill in a `HelloRequest` to send to the stub +- get a reply from the stub +- print out the greeting ```java @@ -375,7 +377,7 @@ line. #### Build the client -This is the same as before: our client and server are part of the same maven +This is the same as building the server: our client and server are part of the same maven package so the same command builds both. ``` @@ -407,6 +409,10 @@ and in another terminal window confirm that it receives a message. $ ./run_greetings_client.sh ``` +### Adding another client + +###TODO: Section on Go client for same server + From 26e6d380abce8fd667597acb0c7f785e33beac79 Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Fri, 13 Feb 2015 15:45:10 +0000 Subject: [PATCH 6/7] Bit of tidying up... --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8f6fd5cc6d5..72a8de9eb06 100644 --- a/README.md +++ b/README.md @@ -338,10 +338,10 @@ service. The channel in turn is used to construct the stub instance. #### Obtaining a greeting The `greet()` method uses the stub to contact the service and obtain a greeting. -In the method we: -- construct and fill in a `HelloRequest` to send to the stub -- get a reply from the stub -- print out the greeting +To do this: + +1. We construct and fill in a `HelloRequest` to send to the stub. +2. We call the RPC with our request and get a `HelloReply` from the stub, from which we can get our greeting. ```java From 27da19feb43157260195732a8f63a5bc3545475b Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Fri, 13 Feb 2015 15:58:20 +0000 Subject: [PATCH 7/7] Bit more tidying up --- README.md | 57 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 72a8de9eb06..e3719357ea5 100644 --- a/README.md +++ b/README.md @@ -276,8 +276,8 @@ finished dealing with this RPC. #### Server implementation -[GreetingsServer.java](java/src/main/java/ex/grpc/GreetingsServer.java) shows the -other main feature required to provide a gRPC service; making the service +[GreetingsServer.java](java/src/main/java/ex/grpc/GreetingsServer.java) +shows the other main feature required to provide a gRPC service; making the service implementation available from the network. ```java @@ -293,9 +293,16 @@ implementation available from the network. ``` -The `GreetingsServer` class has a `ServerImpl` member that actually runs the server. To create an appropriate `ServerImpl`, we use a special `ServerBuilder` class (in this case a `NettyServerBuilder`) in the `GreetingsServer`'s `start` method, binding the `GreetingsService` implementation that we created to a port. Then we start the server running: the server is now ready to receive requests from `Greetings` service clients on our specified port. We'll cover how all this works in a bit more detail in our language-specific documentation. +The `GreetingsServer` class has a `ServerImpl` member that actually runs the +server. To create an appropriate `ServerImpl`, we use a special `ServerBuilder` +class (in this case a `NettyServerBuilder`) in the `GreetingsServer`'s `start` +method, binding the `GreetingsService` implementation that we created to a +port. Then we start the server running: the server is now ready to receive +requests from `Greetings` service clients on our specified port. We'll cover +how all this works in a bit more detail in our language-specific documentation. -`GreetingsServer` also has a `stop` method that takes care of shutting down the service and cleaning up when the program exits. +`GreetingsServer` also has a `stop` method that takes care of shutting down +the service and cleaning up when the program exits. #### Build it @@ -310,14 +317,20 @@ We'll look at using a client to access the server in the next section. ### Writing a client -Client-side gRPC is pretty simple. In this step, we'll use the generated code to write a simple client that can access the `Greetings` server we created in the [previous section](#server). You can see the complete client code in [GreetingsClient.java](java/src/main/java/ex/grpc/GreetingsClient.java). +Client-side gRPC is pretty simple. In this step, we'll use the generated code +to write a simple client that can access the `Greetings` server we created +in the [previous section](#server). You can see the complete client code in +[GreetingsClient.java](java/src/main/java/ex/grpc/GreetingsClient.java). -Again, we're not going to go into much detail about how to implement a client - we'll leave that for the tutorial. +Again, we're not going to go into much detail about how to implement a client +- we'll leave that for the tutorial. #### Connecting to the service -First let's look at how we connect to the `Greetings` server. The internet address -is configured in the client constructor. gRPC `Channel` provides the abstraction layer over +First let's look at how we connect to the `Greetings` server. The internet +address +is configured in the client constructor. gRPC `Channel` provides the +abstraction layer over transport handling; its constructor accepts the host name and port of the service. The channel in turn is used to construct the stub instance. @@ -335,20 +348,28 @@ service. The channel in turn is used to construct the stub instance. ``` +In this case, we create a blocking stub. This means that the RPC call waits +for the server to respond, and will either return a response or raise an +exception. gRPC Java has other kinds of stubs that make non-blocking calls +to the server, where the response is returned asynchronously. + #### Obtaining a greeting -The `greet()` method uses the stub to contact the service and obtain a greeting. +The `greet()` method uses the stub to contact the service and obtain +a greeting. To do this: 1. We construct and fill in a `HelloRequest` to send to the stub. -2. We call the RPC with our request and get a `HelloReply` from the stub, from which we can get our greeting. +2. We call the RPC with our request and get a `HelloReply` from the stub, +from which we can get our greeting. ```java public void greet(String name) { logger.debug("Will try to greet " + name + " ..."); try { - Helloworld.HelloRequest request = Helloworld.HelloRequest.newBuilder().setName(name).build(); + Helloworld.HelloRequest request = + Helloworld.HelloRequest.newBuilder().setName(name).build(); Helloworld.HelloReply reply = blockingStub.hello(request); logger.info("Greeting: " + reply.getMessage()); } catch (RuntimeException e) { @@ -377,22 +398,14 @@ line. #### Build the client -This is the same as building the server: our client and server are part of the same maven +This is the same as building the server: our client and server are part of +the same maven package so the same command builds both. ``` $ mvn package ``` -#### Notes - -- The client uses a blocking stub. This means that the RPC call waits for the - server to respond, and will either return a response or raise an exception. - -- gRPC Java has other kinds of stubs that make non-blocking calls to the - server, where the response is returned asynchronously. Usage of these stubs - is a more advanced topic and will be described in later steps. - ### Try it out! @@ -409,7 +422,7 @@ and in another terminal window confirm that it receives a message. $ ./run_greetings_client.sh ``` -### Adding another client +### Adding another client ###TODO: Section on Go client for same server