diff --git a/Step_3.md b/Step_3.md new file mode 100644 index 0000000000000000000000000000000000000000..56d6e7cfd3acaa8486cd7895acad33827676ee93 --- /dev/null +++ b/Step_3.md @@ -0,0 +1,82 @@ +# Step-3: Implement a server. + +This step extends the generated server skeleton code to write a simple server +that provides the hello service. This in introduces two new classes + +- a service implementation [GreetingsImpl.java](src/main/java/ex/grpc/GreetingsImpl.java). + +- a server that hosts the service implementation and allows to accessed over the network: [GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java). + +## Service implementation + +[GreetingsSImpl.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: + +``` + public void hello(Helloworld.HelloRequest req, + StreamObserver<Helloworld.HelloReply> responseObserver) { + 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<Helloworld.HelloReply> responseObserver) +- `hello` takes two parameters: + `Helloworld.HelloRequest`: the request + `StreamObserver<Helloworld.HelloReply>`: 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. + + +## Server implementation + +[GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java) shows the +other main feature to required to provde gRPC service; how to allow a service +implementation to be accessed from the network. + +``` + private void start() throws Exception { + server = NettyServerBuilder.forPort(port) + .addService(GreetingsGrpc.bindService(new GreetingsImpl())) + .build(); + server.startAsync(); + server.awaitRunning(5, TimeUnit.SECONDS); + } + +``` + +- 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 + +## Build it + +This is the same as before: our client and server are part of the same maven +package so the same command builds both. + +``` +$ mvn package +``` + +## Try them out + +We've added simple shell scripts to simplifying running the examples. Now +that they are built, you can run the server with. + +``` +$ ./run_greetings_server.sh +``` + +In another termainal window and confirm that it receives a message. + +``` +$ ./run_greetings_client.sh +``` diff --git a/src/main/java/ex/grpc/GreetingsImpl.java b/src/main/java/ex/grpc/GreetingsImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..005489acaa2057222452c28c1e18eac952ff0073 --- /dev/null +++ b/src/main/java/ex/grpc/GreetingsImpl.java @@ -0,0 +1,16 @@ +package ex.grpc; + +import com.google.net.stubby.stub.StreamObserver; + +public class GreetingsImpl implements GreetingsGrpc.Greetings { + + @Override + public void hello(Helloworld.HelloRequest req, + StreamObserver<Helloworld.HelloReply> responseObserver) { + Helloworld.HelloReply reply = Helloworld.HelloReply.newBuilder().setMessage( + "Hello " + req.getName()).build(); + responseObserver.onValue(reply); + responseObserver.onCompleted(); + } + +} diff --git a/src/main/java/ex/grpc/GreetingsServer.java b/src/main/java/ex/grpc/GreetingsServer.java new file mode 100644 index 0000000000000000000000000000000000000000..834ae985a441f7154b4b8c1981ae2d93c9846615 --- /dev/null +++ b/src/main/java/ex/grpc/GreetingsServer.java @@ -0,0 +1,51 @@ +package ex.grpc; + +import com.google.common.util.concurrent.MoreExecutors; +import com.google.net.stubby.ServerImpl; +import com.google.net.stubby.transport.netty.NettyServerBuilder; + +import java.util.concurrent.TimeUnit; + +/** + * Server that manages startup/shutdown of a {@code Greetings} server. + */ +public class GreetingsServer { + /* The port on which the server should run */ + private int port = 50051; + private ServerImpl server; + + private void start() throws Exception { + server = NettyServerBuilder.forPort(port) + .addService(GreetingsGrpc.bindService(new GreetingsImpl())) + .build(); + server.startAsync(); + server.awaitRunning(5, TimeUnit.SECONDS); + System.out.println("Server started on port:" + port); + } + + private void stop() throws Exception { + server.stopAsync(); + server.awaitTerminated(); + System.out.println("Server shutting down ..."); + } + + /** + * Main launches the server from the command line. + */ + public static void main(String[] args) throws Exception { + final GreetingsServer server = new GreetingsServer(); + + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + try { + System.out.println("Shutting down"); + server.stop(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + server.start(); + } +}