diff --git a/examples/README.md b/examples/README.md index 138a4d9587..1044889b31 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,16 +1,20 @@ grpc Examples ============================================== -In order to run the examples simply execute one of the gradle tasks `routeGuideServer` or -`routeGuideClient`. +In order to run the examples simply execute one of the gradle tasks `routeGuideServer`, +`routeGuideClient`, `helloWorldServer`, or `helloWorldClient`. -Assuming you are in the grpc-java root folder you would first start the server by running +For example, say you want to play around with the route guide examples. First you want to start +the server and then have the client connect to it and let the good times roll. + +Assuming you are in the grpc-java root folder you would first start the route guide server +by running ``` $ ./gradlew :grpc-examples:routeGuideServer ``` -and in a different terminal window then run the client by typing +and in a different terminal window then run the route guide client by typing ``` $ ./gradlew :grpc-examples:routeGuideClient diff --git a/examples/build.gradle b/examples/build.gradle index 07eeac8891..87c722e2a7 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -34,3 +34,15 @@ task routeGuideClient(type: JavaExec) { description = "Executes the route guide client." classpath = sourceSets.main.runtimeClasspath } + +task helloWorldServer(type: JavaExec) { + main = "io.grpc.examples.HelloWorldServer" + description = "Executes the hello world server." + classpath = sourceSets.main.runtimeClasspath +} + +task helloWorldClient(type: JavaExec) { + main = "io.grpc.examples.HelloWorldClient" + description = "Executes the hello world client." + classpath = sourceSets.main.runtimeClasspath +} \ No newline at end of file diff --git a/examples/src/main/java/io/grpc/examples/HelloWorldClient.java b/examples/src/main/java/io/grpc/examples/HelloWorldClient.java new file mode 100644 index 0000000000..a887801284 --- /dev/null +++ b/examples/src/main/java/io/grpc/examples/HelloWorldClient.java @@ -0,0 +1,58 @@ +package io.grpc.examples; + +import io.grpc.ChannelImpl; +import io.grpc.examples.Helloworld.HelloReply; +import io.grpc.examples.Helloworld.HelloRequest; +import io.grpc.transport.netty.NegotiationType; +import io.grpc.transport.netty.NettyChannelBuilder; + +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A simple client that requests a greeting from the {@link HelloWorldServer}. + */ +public class HelloWorldClient { + private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName()); + + private final ChannelImpl channel; + private final GreeterGrpc.GreeterBlockingStub blockingStub; + + public HelloWorldClient(String host, int port) { + channel = + NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT) + .build(); + blockingStub = GreeterGrpc.newBlockingStub(channel); + } + + public void shutdown() throws InterruptedException { + channel.shutdown().awaitTerminated(5, TimeUnit.SECONDS); + } + + public void greet(String name) { + try { + logger.info("Will try to greet " + name + " ..."); + HelloRequest req = HelloRequest.newBuilder().setName(name).build(); + HelloReply reply = blockingStub.sayHello(req); + logger.info("Greeting: " + reply.getMessage()); + } catch (RuntimeException e) { + logger.log(Level.WARNING, "RPC failed", e); + return; + } + } + + public static void main(String[] args) throws Exception { + HelloWorldClient client = new HelloWorldClient("localhost", 50051); + try { + /* Access a service running on the local machine on port 50051 */ + String user = "world"; + if (args.length > 0) { + user = args[0]; /* Use the arg as the name to greet if provided */ + } + client.greet(user); + } finally { + client.shutdown(); + } + } +} diff --git a/examples/src/main/java/io/grpc/examples/HelloWorldServer.java b/examples/src/main/java/io/grpc/examples/HelloWorldServer.java new file mode 100644 index 0000000000..68d8f9ecce --- /dev/null +++ b/examples/src/main/java/io/grpc/examples/HelloWorldServer.java @@ -0,0 +1,60 @@ +package io.grpc.examples; + +import io.grpc.ServerImpl; +import io.grpc.examples.Helloworld.HelloReply; +import io.grpc.examples.Helloworld.HelloRequest; +import io.grpc.stub.StreamObserver; +import io.grpc.transport.netty.NettyServerBuilder; + +import java.util.logging.Logger; + +/** + * Server that manages startup/shutdown of a {@code Greeter} server. + */ +public class HelloWorldServer { + private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName()); + + /* 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(GreeterGrpc.bindService(new GreeterImpl())) + .build().start(); + logger.info("Server started, listening on " + port); + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + // Use stderr here since the logger may has been reset by its JVM shutdown hook. + System.err.println("*** shutting down gRPC server since JVM is shutting down"); + HelloWorldServer.this.stop(); + System.err.println("*** server shut down"); + } + }); + } + + private void stop() { + if (server != null) { + server.shutdown(); + } + } + + /** + * Main launches the server from the command line. + */ + public static void main(String[] args) throws Exception { + final HelloWorldServer server = new HelloWorldServer(); + server.start(); + } + + private class GreeterImpl implements GreeterGrpc.Greeter { + + @Override + public void sayHello(HelloRequest req, StreamObserver responseObserver) { + HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); + responseObserver.onValue(reply); + responseObserver.onCompleted(); + } + } +} \ No newline at end of file diff --git a/examples/src/main/java/io/grpc/examples/RouteGuideServer.java b/examples/src/main/java/io/grpc/examples/RouteGuideServer.java index f0fc5d7cc4..2527b4693a 100644 --- a/examples/src/main/java/io/grpc/examples/RouteGuideServer.java +++ b/examples/src/main/java/io/grpc/examples/RouteGuideServer.java @@ -88,8 +88,6 @@ public class RouteGuideServer { .addService(RouteGuideGrpc.bindService(new RouteGuideService(features))) .build().start(); logger.info("Server started, listening on " + port); - // TODO(simonma): gRPC server should register JVM shutdown hook to shutdown itself, remove this - // after we support that. Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { diff --git a/examples/src/main/proto/helloworld.proto b/examples/src/main/proto/helloworld.proto new file mode 100644 index 0000000000..a09fdfd91f --- /dev/null +++ b/examples/src/main/proto/helloworld.proto @@ -0,0 +1,50 @@ +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +option java_package = "io.grpc.examples"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} \ No newline at end of file