diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..1a49c132b536d40637978b69fdcb28a32ff199b5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+*~
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
\ No newline at end of file
diff --git a/README.md b/README.md
index 2b288236bdf35c425775abaf62b4add2575f846b..9a668f3b1cde07f17007cf1aae1ddb6dc4ca0bf9 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,81 @@
-# grpc-common
-documents, resources, examples shared across other grpc repositories
+# gRPC Helloworld Tutorial
+
+## TODO: move this to the tutorial sub-folder
+
+A great way to get introduced to gRPC is to work through this tutorial, which
+walks you through the construction of simple client and server that introduces
+various features of gRPC.
+
+When you finish the tutorial, you will be able to
+
+- Create an protobuf schema that defines a simple RPC service
+- Create a Java server that implements the schema interface
+- Create a Java client that accesses the server
+- Create a Go client that accesses the Java server
+- Update the service with advanced features like RPC streaming
+
+# Get Started
+
+The rest of this page explains how you can set up your local machine for development.
+If you just want to read the tutorial, you can go straight to the next step: [Step - 0](Step_0.md)
+
+# Working with the code
+
+You can follow along with this tutorial and hack on the code in the comfort of
+your own computer. In this way you can get hands-on practice of really writing
+gRPC code.
+
+The tutorial relies on the use of the Git versioning system for source code
+management. You don't need to know anything about Git to follow the tutorial
+other than how to install and run a few git commands.
+
+# Install Git
+
+You can download and install Git from http://git-scm.com/download. Once
+installed you should have access to the git command line tool. The main
+commands that you will need to use are:
+
+- git clone ... : clone a remote repository onto your local machine
+- git checkout ... : check out a particular branch or a tagged version of the code to hack on
+
+# Download grpc-helloworld
+
+Clone the grpc-helloword repository located at GitHub by running the following command:
+
+```
+git clone https://github.com/google/grpc-helloworld.git
+```
+
+Change your current directory to grpc-helloworld
+
+```
+cd grpc-helloworld
+```
+
+# Install Java 8
+
+Java gRPC is designed to work with both Java 7 and Java 8.  For simplicity,
+the example assumes that Java 8 is installed.  See
+[Install Java 8](http://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html)
+for instructions.
+
+# Install Maven
+
+To simplify building and the managing of gRPC's dependencies, the java client
+are server are structured as a standard [Maven](http://maven.apache.org/guides/getting-started/)
+project. See [Install Maven](http://maven.apache.org/users/index.html) for instructions.
+
+
+# Install Go 1.4
+
+Go gRPC requires Go 1.4, the latest version of Go.  See
+[Install Go](https://golang.org/doc/install) for instructions.
+
+# (optional) Install protoc
+
+gRPC uses the latest version of the protocol buffer compiler, protoc.
+
+For following this tutorial, the protoc is not strictly necessary, as all the
+generated code is checked into the Git repository.  If you want to experiment
+with generating the code yourself, download and install protoc from its
+[Git repo](https://github.com/google/protobuf)
diff --git a/Step_0.md b/Step_0.md
new file mode 100644
index 0000000000000000000000000000000000000000..3fec8376d1aa4aba70f166cc82cb4399373d4c3c
--- /dev/null
+++ b/Step_0.md
@@ -0,0 +1,41 @@
+# Step-0: define a service
+
+This section presents an example of a simple service definition that receives
+a message from a remote client. The message contains the users's name and
+sends back a greeting to that person.
+
+It's shown below in full; it's actually contained in separate file
+[helloworld.proto](helloworld.proto).
+
+```
+syntax = "proto3";
+
+package helloworld;
+
+// The request message containing the user's name.
+message HelloRequest {
+  optional string name = 1;
+}
+
+// The response message containing the greetings
+message HelloReply {
+  optional string message = 1;
+}
+
+// The greeting service definition.
+service Greeting {
+
+  // Sends a greeting
+  rpc hello (HelloRequest) returns (HelloReply) {
+  }
+}
+
+```
+
+The service stanza of the message is an example of protobuf service IDL
+(Interface Defintion Language).  Here, it defines a simple service that
+receives a request containing a name and returns a response containing a
+message.
+
+Next, in [Step-1](Step-1.md), we'll use protoc to generate client code from
+this IDL.
diff --git a/Step_1.md b/Step_1.md
new file mode 100644
index 0000000000000000000000000000000000000000..4ac68aba5dfb2146344b650ea2e4b40a9b242f80
--- /dev/null
+++ b/Step_1.md
@@ -0,0 +1,33 @@
+# Step-1: Generate a service client.
+
+In this step, we use protoc to generate the java Stub classes.  A Stub is the
+name gRPC uses for the code that initiates contact with a gRPC service running
+remotely via the internet.
+
+If you did not install protoc on your system, you can skip this step and move
+onto the next one where we examine the generated code.
+
+First, you'll need to build the protobuf plugin that generates the rpc
+classes.  `protoc` uses other tools called plugins to add additional features
+to generated code.
+
+The grpc Java Stub classes are created using a grpc java plugin, but first the
+plugin must be built and installed.
+
+To build the plugin:
+```
+$ pushd external/grpc_java
+$ make java_plugin
+$ popd
+```
+
+To use it to generate the code:
+```
+$ mkdir -p src/main/java
+$ protoc -I . helloworld.proto --plugin=protoc-gen-grpc=external/grpc_java/bins/opt/java_plugin \
+                               --grpc_out=src/main/java \
+                               --java_out=src/main/java
+```
+
+Next, in [Step-2](Step-2.md), we'll use the generated Stub implementation to
+write a client that uses the generated code to make a call to a service.
diff --git a/Step_2.md b/Step_2.md
new file mode 100644
index 0000000000000000000000000000000000000000..dd134a989c5fc8df57b42f4d04fef64615838919
--- /dev/null
+++ b/Step_2.md
@@ -0,0 +1,85 @@
+# Step-2: Write a service client.
+
+This step uses the generated code to write a simple client to access the hello
+service.  The full client is in [GreetingsClient.java](src/main/java/ex/grpc/GreetingsClient.java).
+
+
+## Configuring the service to connect to.
+
+The client contains uses a Stub to contact the service.  The internet address
+is configured in the client constructor.  gRPC Channel is the abstraction over
+transport handling; its constructor accepts the host name and port of the
+service.  The channel in turn is used to construct the Stub.
+
+
+```
+  private final ChannelImpl channel;
+  private final GreetingGrpc.GreetingBlockingStub blockingStub;
+
+  public HelloClient(String host, int port) {
+    channel = NettyChannelBuilder.forAddress(host, port)
+              .negotiationType(NegotiationType.PLAINTEXT)
+              .build();
+    blockingStub = GreetingGrpc.newBlockingStub(channel);
+  }
+
+```
+
+## 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
+
+
+```
+  public void greet(String name) {
+    logger.debug("Will try to greet " + name + " ...");
+    try {
+      Helloworld.HelloRequest request = Helloworld.HelloRequest.newBuilder().setName(name).build();
+      Helloworld.HelloReply reply = blockingStub.hello(request);
+      logger.info("Greeting: " + reply.getMessage());
+    } catch (RuntimeException e) {
+      logger.log(Level.WARNING, "RPC failed", e);
+      return;
+    }
+  }
+
+```
+
+## Running from the command line
+
+The main method puts together the example so that it can be run from a command
+line.
+
+```
+    /* Access a service running on the local machine on port 50051 */
+    HelloClient client = new HelloClient("localhost", 50051);
+    String user = "world";
+    if (args.length > 1) {
+      user = args[1];
+    }
+    client.greet(user);
+
+```
+
+It can be built as follows.
+
+```
+$ mvn package
+```
+
+It can also be run, but doing so now would end up a with a failure as there is
+no server available yet.  The [next step](Step-3.md), describes how to
+implement, build and run a server that supports the service description.
+
+## 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.
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/pom.xml b/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..da0ee205f77b2754b1f33dfbda993466d7b9f5a9
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,105 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.net.stubby</groupId>
+    <artifactId>stubby-parent</artifactId>
+    <version>0.1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>grpc-hello-world</artifactId>
+  <packaging>jar</packaging>
+
+  <name>Hello gRPC World</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>stubby-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>stubby-netty</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>stubby-okhttp</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>stubby-stub</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>stubby-testing</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>compile</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>assemble-all</id>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <descriptorRefs>
+            <descriptorRef>jar-with-dependencies</descriptorRef>
+          </descriptorRefs>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>com.internetitem</groupId>
+        <artifactId>write-properties-file-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>bootclasspath</id>
+            <phase>prepare-package</phase>
+            <goals>
+              <goal>write-properties-file</goal>
+            </goals>
+            <configuration>
+              <filename>bootclasspath.properties</filename>
+              <outputDirectory>${project.build.directory}</outputDirectory>
+              <properties>
+                <property>
+                  <name>bootclasspath</name>
+                  <value>${argLine.bootcp}</value>
+                </property>
+                <property>
+                  <name>jar</name>
+                  <value>${project.build.directory}/${project.artifactId}-${project.version}-jar-with-dependencies.jar</value>
+                </property>
+              </properties>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/run_greetings_client.sh b/run_greetings_client.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8155589adf7379a480adf032955d71e206fcf304
--- /dev/null
+++ b/run_greetings_client.sh
@@ -0,0 +1,10 @@
+#!/bin/bash -e
+TARGET='Greetings Client'
+TARGET_CLASS='ex.grpc.GreetingsClient'
+TARGET_ARGS="$@"
+
+cd "$(dirname "$0")"
+mvn -q -nsu -am package -Dcheckstyle.skip=true -DskipTests
+. target/bootclasspath.properties
+echo "[INFO] Running: $TARGET ($TARGET_CLASS $TARGET_ARGS)"
+exec java "$bootclasspath" -cp "$jar" "$TARGET_CLASS" $TARGET_ARGS
diff --git a/run_greetings_server.sh b/run_greetings_server.sh
new file mode 100755
index 0000000000000000000000000000000000000000..248229e129e0a6165b91327dca8b75c51113266a
--- /dev/null
+++ b/run_greetings_server.sh
@@ -0,0 +1,9 @@
+#!/bin/bash -e
+TARGET='Greetings Server'
+TARGET_CLASS='ex.grpc.GreetingsServer'
+
+cd "$(dirname "$0")"
+mvn -q -nsu -am package -Dcheckstyle.skip=true -DskipTests
+. target/bootclasspath.properties
+echo "[INFO] Running: $TARGET ($TARGET_CLASS)"
+exec java "$bootclasspath" -cp "$jar" "$TARGET_CLASS"
diff --git a/src/main/java/ex/grpc/GreetingsClient.java b/src/main/java/ex/grpc/GreetingsClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ae2e7076bc338767a32df09e5ac5d433a9b6a98
--- /dev/null
+++ b/src/main/java/ex/grpc/GreetingsClient.java
@@ -0,0 +1,55 @@
+package ex.grpc;
+
+import com.google.net.stubby.ChannelImpl;
+import com.google.net.stubby.stub.StreamObserver;
+import com.google.net.stubby.transport.netty.NegotiationType;
+import com.google.net.stubby.transport.netty.NettyChannelBuilder;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.concurrent.TimeUnit;
+
+public class GreetingsClient {
+  private final Logger logger = Logger.getLogger(
+      GreetingsClient.class.getName());
+  private final ChannelImpl channel;
+  private final GreetingsGrpc.GreetingsBlockingStub blockingStub;
+
+  public GreetingsClient(String host, int port) {
+    channel = NettyChannelBuilder.forAddress(host, port)
+              .negotiationType(NegotiationType.PLAINTEXT)
+              .build();
+    blockingStub = GreetingsGrpc.newBlockingStub(channel);
+  }
+
+  public void shutdown() throws InterruptedException {
+    channel.shutdown().awaitTerminated(5, TimeUnit.SECONDS);
+  }
+
+  public void greet(String name) {
+    try {
+      logger.fine("Will try to greet " + name + " ...");
+      Helloworld.HelloRequest req =
+          Helloworld.HelloRequest.newBuilder().setName(name).build();
+      Helloworld.HelloReply reply = blockingStub.hello(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 {
+    GreetingsClient client = new GreetingsClient("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/src/main/java/ex/grpc/GreetingsGrpc.java b/src/main/java/ex/grpc/GreetingsGrpc.java
new file mode 100644
index 0000000000000000000000000000000000000000..97c2f00a1e039113b0ff6c7560fdeccabdeeea53
--- /dev/null
+++ b/src/main/java/ex/grpc/GreetingsGrpc.java
@@ -0,0 +1,172 @@
+package ex.grpc;
+
+import static com.google.net.stubby.stub.Calls.createMethodDescriptor;
+import static com.google.net.stubby.stub.Calls.asyncUnaryCall;
+import static com.google.net.stubby.stub.Calls.asyncServerStreamingCall;
+import static com.google.net.stubby.stub.Calls.asyncClientStreamingCall;
+import static com.google.net.stubby.stub.Calls.duplexStreamingCall;
+import static com.google.net.stubby.stub.Calls.blockingUnaryCall;
+import static com.google.net.stubby.stub.Calls.blockingServerStreamingCall;
+import static com.google.net.stubby.stub.Calls.unaryFutureCall;
+import static com.google.net.stubby.stub.ServerCalls.createMethodDefinition;
+import static com.google.net.stubby.stub.ServerCalls.asyncUnaryRequestCall;
+import static com.google.net.stubby.stub.ServerCalls.asyncStreamingRequestCall;
+
+@javax.annotation.Generated("by gRPC proto compiler")
+public class GreetingsGrpc {
+
+  private static final com.google.net.stubby.stub.Method<ex.grpc.Helloworld.HelloRequest,
+      ex.grpc.Helloworld.HelloReply> METHOD_HELLO =
+      com.google.net.stubby.stub.Method.create(
+          com.google.net.stubby.MethodType.UNARY, "hello",
+          com.google.net.stubby.proto.ProtoUtils.marshaller(ex.grpc.Helloworld.HelloRequest.PARSER),
+          com.google.net.stubby.proto.ProtoUtils.marshaller(ex.grpc.Helloworld.HelloReply.PARSER));
+
+  public static GreetingsStub newStub(com.google.net.stubby.Channel channel) {
+    return new GreetingsStub(channel, CONFIG);
+  }
+
+  public static GreetingsBlockingStub newBlockingStub(
+      com.google.net.stubby.Channel channel) {
+    return new GreetingsBlockingStub(channel, CONFIG);
+  }
+
+  public static GreetingsFutureStub newFutureStub(
+      com.google.net.stubby.Channel channel) {
+    return new GreetingsFutureStub(channel, CONFIG);
+  }
+
+  public static final GreetingsServiceDescriptor CONFIG =
+      new GreetingsServiceDescriptor();
+
+  @javax.annotation.concurrent.Immutable
+  public static class GreetingsServiceDescriptor extends
+      com.google.net.stubby.stub.AbstractServiceDescriptor<GreetingsServiceDescriptor> {
+    public final com.google.net.stubby.MethodDescriptor<ex.grpc.Helloworld.HelloRequest,
+        ex.grpc.Helloworld.HelloReply> hello;
+
+    private GreetingsServiceDescriptor() {
+      hello = createMethodDescriptor(
+          "helloworld.Greetings", METHOD_HELLO);
+    }
+
+    private GreetingsServiceDescriptor(
+        java.util.Map<java.lang.String, com.google.net.stubby.MethodDescriptor<?, ?>> methodMap) {
+      hello = (com.google.net.stubby.MethodDescriptor<ex.grpc.Helloworld.HelloRequest,
+          ex.grpc.Helloworld.HelloReply>) methodMap.get(
+          CONFIG.hello.getName());
+    }
+
+    @java.lang.Override
+    protected GreetingsServiceDescriptor build(
+        java.util.Map<java.lang.String, com.google.net.stubby.MethodDescriptor<?, ?>> methodMap) {
+      return new GreetingsServiceDescriptor(methodMap);
+    }
+
+    @java.lang.Override
+    public com.google.common.collect.ImmutableList<com.google.net.stubby.MethodDescriptor<?, ?>> methods() {
+      return com.google.common.collect.ImmutableList.<com.google.net.stubby.MethodDescriptor<?, ?>>of(
+          hello);
+    }
+  }
+
+  public static interface Greetings {
+
+    public void hello(ex.grpc.Helloworld.HelloRequest request,
+        com.google.net.stubby.stub.StreamObserver<ex.grpc.Helloworld.HelloReply> responseObserver);
+  }
+
+  public static interface GreetingsBlockingClient {
+
+    public ex.grpc.Helloworld.HelloReply hello(ex.grpc.Helloworld.HelloRequest request);
+  }
+
+  public static interface GreetingsFutureClient {
+
+    public com.google.common.util.concurrent.ListenableFuture<ex.grpc.Helloworld.HelloReply> hello(
+        ex.grpc.Helloworld.HelloRequest request);
+  }
+
+  public static class GreetingsStub extends
+      com.google.net.stubby.stub.AbstractStub<GreetingsStub, GreetingsServiceDescriptor>
+      implements Greetings {
+    private GreetingsStub(com.google.net.stubby.Channel channel,
+        GreetingsServiceDescriptor config) {
+      super(channel, config);
+    }
+
+    @java.lang.Override
+    protected GreetingsStub build(com.google.net.stubby.Channel channel,
+        GreetingsServiceDescriptor config) {
+      return new GreetingsStub(channel, config);
+    }
+
+    @java.lang.Override
+    public void hello(ex.grpc.Helloworld.HelloRequest request,
+        com.google.net.stubby.stub.StreamObserver<ex.grpc.Helloworld.HelloReply> responseObserver) {
+      asyncUnaryCall(
+          channel.newCall(config.hello), request, responseObserver);
+    }
+  }
+
+  public static class GreetingsBlockingStub extends
+      com.google.net.stubby.stub.AbstractStub<GreetingsBlockingStub, GreetingsServiceDescriptor>
+      implements GreetingsBlockingClient {
+    private GreetingsBlockingStub(com.google.net.stubby.Channel channel,
+        GreetingsServiceDescriptor config) {
+      super(channel, config);
+    }
+
+    @java.lang.Override
+    protected GreetingsBlockingStub build(com.google.net.stubby.Channel channel,
+        GreetingsServiceDescriptor config) {
+      return new GreetingsBlockingStub(channel, config);
+    }
+
+    @java.lang.Override
+    public ex.grpc.Helloworld.HelloReply hello(ex.grpc.Helloworld.HelloRequest request) {
+      return blockingUnaryCall(
+          channel.newCall(config.hello), request);
+    }
+  }
+
+  public static class GreetingsFutureStub extends
+      com.google.net.stubby.stub.AbstractStub<GreetingsFutureStub, GreetingsServiceDescriptor>
+      implements GreetingsFutureClient {
+    private GreetingsFutureStub(com.google.net.stubby.Channel channel,
+        GreetingsServiceDescriptor config) {
+      super(channel, config);
+    }
+
+    @java.lang.Override
+    protected GreetingsFutureStub build(com.google.net.stubby.Channel channel,
+        GreetingsServiceDescriptor config) {
+      return new GreetingsFutureStub(channel, config);
+    }
+
+    @java.lang.Override
+    public com.google.common.util.concurrent.ListenableFuture<ex.grpc.Helloworld.HelloReply> hello(
+        ex.grpc.Helloworld.HelloRequest request) {
+      return unaryFutureCall(
+          channel.newCall(config.hello), request);
+    }
+  }
+
+  public static com.google.net.stubby.ServerServiceDefinition bindService(
+      final Greetings serviceImpl) {
+    return com.google.net.stubby.ServerServiceDefinition.builder("helloworld.Greetings")
+      .addMethod(createMethodDefinition(
+          METHOD_HELLO,
+          asyncUnaryRequestCall(
+            new com.google.net.stubby.stub.ServerCalls.UnaryRequestMethod<
+                ex.grpc.Helloworld.HelloRequest,
+                ex.grpc.Helloworld.HelloReply>() {
+              @java.lang.Override
+              public void invoke(
+                  ex.grpc.Helloworld.HelloRequest request,
+                  com.google.net.stubby.stub.StreamObserver<ex.grpc.Helloworld.HelloReply> responseObserver) {
+                serviceImpl.hello(request, responseObserver);
+              }
+            }))).build();
+  }
+}
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();
+  }
+}
diff --git a/src/main/java/ex/grpc/Helloworld.java b/src/main/java/ex/grpc/Helloworld.java
new file mode 100644
index 0000000000000000000000000000000000000000..f72040fa2bf81ed792ed32bb40a2e3f4383055af
--- /dev/null
+++ b/src/main/java/ex/grpc/Helloworld.java
@@ -0,0 +1,951 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: src/main/proto/helloworld.proto
+
+package ex.grpc;
+
+public final class Helloworld {
+  private Helloworld() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface HelloRequestOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:helloworld.HelloRequest)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>optional string name = 1;</code>
+     */
+    java.lang.String getName();
+    /**
+     * <code>optional string name = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getNameBytes();
+  }
+  /**
+   * Protobuf type {@code helloworld.HelloRequest}
+   *
+   * <pre>
+   * The request message containing the user's name.
+   * </pre>
+   */
+  public  static final class HelloRequest extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:helloworld.HelloRequest)
+      HelloRequestOrBuilder {
+    // Use HelloRequest.newBuilder() to construct.
+    private HelloRequest(com.google.protobuf.GeneratedMessage.Builder builder) {
+      super(builder);
+    }
+    private HelloRequest() {
+      name_ = "";
+    }
+
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+    getUnknownFields() {
+      return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
+    }
+    private HelloRequest(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      this();
+      int mutable_bitField0_ = 0;
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!input.skipField(tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+
+              name_ = bs;
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return ex.grpc.Helloworld.internal_static_helloworld_HelloRequest_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return ex.grpc.Helloworld.internal_static_helloworld_HelloRequest_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              ex.grpc.Helloworld.HelloRequest.class, ex.grpc.Helloworld.HelloRequest.Builder.class);
+    }
+
+    public static final com.google.protobuf.Parser<HelloRequest> PARSER =
+        new com.google.protobuf.AbstractParser<HelloRequest>() {
+      public HelloRequest parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new HelloRequest(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<HelloRequest> getParserForType() {
+      return PARSER;
+    }
+
+    public static final int NAME_FIELD_NUMBER = 1;
+    private java.lang.Object name_;
+    /**
+     * <code>optional string name = 1;</code>
+     */
+    public java.lang.String getName() {
+      java.lang.Object ref = name_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          name_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string name = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getNameBytes() {
+      java.lang.Object ref = name_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        name_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (!getNameBytes().isEmpty()) {
+        output.writeBytes(1, getNameBytes());
+      }
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (!getNameBytes().isEmpty()) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getNameBytes());
+      }
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    public static ex.grpc.Helloworld.HelloRequest parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static ex.grpc.Helloworld.HelloRequest parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static ex.grpc.Helloworld.HelloRequest parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static ex.grpc.Helloworld.HelloRequest parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static ex.grpc.Helloworld.HelloRequest parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static ex.grpc.Helloworld.HelloRequest parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static ex.grpc.Helloworld.HelloRequest parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static ex.grpc.Helloworld.HelloRequest parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static ex.grpc.Helloworld.HelloRequest parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static ex.grpc.Helloworld.HelloRequest parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return new Builder(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(ex.grpc.Helloworld.HelloRequest prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code helloworld.HelloRequest}
+     *
+     * <pre>
+     * The request message containing the user's name.
+     * </pre>
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:helloworld.HelloRequest)
+        ex.grpc.Helloworld.HelloRequestOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return ex.grpc.Helloworld.internal_static_helloworld_HelloRequest_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return ex.grpc.Helloworld.internal_static_helloworld_HelloRequest_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                ex.grpc.Helloworld.HelloRequest.class, ex.grpc.Helloworld.HelloRequest.Builder.class);
+      }
+
+      // Construct using ex.grpc.Helloworld.HelloRequest.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      public Builder clear() {
+        super.clear();
+        name_ = "";
+
+        return this;
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return ex.grpc.Helloworld.internal_static_helloworld_HelloRequest_descriptor;
+      }
+
+      public ex.grpc.Helloworld.HelloRequest getDefaultInstanceForType() {
+        return ex.grpc.Helloworld.HelloRequest.getDefaultInstance();
+      }
+
+      public ex.grpc.Helloworld.HelloRequest build() {
+        ex.grpc.Helloworld.HelloRequest result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public ex.grpc.Helloworld.HelloRequest buildPartial() {
+        ex.grpc.Helloworld.HelloRequest result = new ex.grpc.Helloworld.HelloRequest(this);
+        result.name_ = name_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof ex.grpc.Helloworld.HelloRequest) {
+          return mergeFrom((ex.grpc.Helloworld.HelloRequest)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(ex.grpc.Helloworld.HelloRequest other) {
+        if (other == ex.grpc.Helloworld.HelloRequest.getDefaultInstance()) return this;
+        if (!other.getName().isEmpty()) {
+          name_ = other.name_;
+          onChanged();
+        }
+        onChanged();
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        ex.grpc.Helloworld.HelloRequest parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (ex.grpc.Helloworld.HelloRequest) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      private java.lang.Object name_ = "";
+      /**
+       * <code>optional string name = 1;</code>
+       */
+      public java.lang.String getName() {
+        java.lang.Object ref = name_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            name_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string name = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getNameBytes() {
+        java.lang.Object ref = name_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          name_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string name = 1;</code>
+       */
+      public Builder setName(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        name_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string name = 1;</code>
+       */
+      public Builder clearName() {
+        
+        name_ = getDefaultInstance().getName();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string name = 1;</code>
+       */
+      public Builder setNameBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        name_ = value;
+        onChanged();
+        return this;
+      }
+      public final Builder setUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return this;
+      }
+
+      public final Builder mergeUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return this;
+      }
+
+
+      // @@protoc_insertion_point(builder_scope:helloworld.HelloRequest)
+    }
+
+    // @@protoc_insertion_point(class_scope:helloworld.HelloRequest)
+    private static final ex.grpc.Helloworld.HelloRequest defaultInstance;static {
+      defaultInstance = new ex.grpc.Helloworld.HelloRequest();
+    }
+
+    public static ex.grpc.Helloworld.HelloRequest getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public ex.grpc.Helloworld.HelloRequest getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+  }
+
+  public interface HelloReplyOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:helloworld.HelloReply)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>optional string message = 1;</code>
+     */
+    java.lang.String getMessage();
+    /**
+     * <code>optional string message = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getMessageBytes();
+  }
+  /**
+   * Protobuf type {@code helloworld.HelloReply}
+   *
+   * <pre>
+   * The response message containing the greetings
+   * </pre>
+   */
+  public  static final class HelloReply extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:helloworld.HelloReply)
+      HelloReplyOrBuilder {
+    // Use HelloReply.newBuilder() to construct.
+    private HelloReply(com.google.protobuf.GeneratedMessage.Builder builder) {
+      super(builder);
+    }
+    private HelloReply() {
+      message_ = "";
+    }
+
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+    getUnknownFields() {
+      return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
+    }
+    private HelloReply(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      this();
+      int mutable_bitField0_ = 0;
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!input.skipField(tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+
+              message_ = bs;
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return ex.grpc.Helloworld.internal_static_helloworld_HelloReply_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return ex.grpc.Helloworld.internal_static_helloworld_HelloReply_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              ex.grpc.Helloworld.HelloReply.class, ex.grpc.Helloworld.HelloReply.Builder.class);
+    }
+
+    public static final com.google.protobuf.Parser<HelloReply> PARSER =
+        new com.google.protobuf.AbstractParser<HelloReply>() {
+      public HelloReply parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new HelloReply(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<HelloReply> getParserForType() {
+      return PARSER;
+    }
+
+    public static final int MESSAGE_FIELD_NUMBER = 1;
+    private java.lang.Object message_;
+    /**
+     * <code>optional string message = 1;</code>
+     */
+    public java.lang.String getMessage() {
+      java.lang.Object ref = message_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          message_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string message = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getMessageBytes() {
+      java.lang.Object ref = message_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        message_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (!getMessageBytes().isEmpty()) {
+        output.writeBytes(1, getMessageBytes());
+      }
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (!getMessageBytes().isEmpty()) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getMessageBytes());
+      }
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    public static ex.grpc.Helloworld.HelloReply parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static ex.grpc.Helloworld.HelloReply parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static ex.grpc.Helloworld.HelloReply parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static ex.grpc.Helloworld.HelloReply parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static ex.grpc.Helloworld.HelloReply parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static ex.grpc.Helloworld.HelloReply parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static ex.grpc.Helloworld.HelloReply parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static ex.grpc.Helloworld.HelloReply parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static ex.grpc.Helloworld.HelloReply parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static ex.grpc.Helloworld.HelloReply parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return new Builder(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(ex.grpc.Helloworld.HelloReply prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code helloworld.HelloReply}
+     *
+     * <pre>
+     * The response message containing the greetings
+     * </pre>
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:helloworld.HelloReply)
+        ex.grpc.Helloworld.HelloReplyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return ex.grpc.Helloworld.internal_static_helloworld_HelloReply_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return ex.grpc.Helloworld.internal_static_helloworld_HelloReply_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                ex.grpc.Helloworld.HelloReply.class, ex.grpc.Helloworld.HelloReply.Builder.class);
+      }
+
+      // Construct using ex.grpc.Helloworld.HelloReply.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      public Builder clear() {
+        super.clear();
+        message_ = "";
+
+        return this;
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return ex.grpc.Helloworld.internal_static_helloworld_HelloReply_descriptor;
+      }
+
+      public ex.grpc.Helloworld.HelloReply getDefaultInstanceForType() {
+        return ex.grpc.Helloworld.HelloReply.getDefaultInstance();
+      }
+
+      public ex.grpc.Helloworld.HelloReply build() {
+        ex.grpc.Helloworld.HelloReply result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public ex.grpc.Helloworld.HelloReply buildPartial() {
+        ex.grpc.Helloworld.HelloReply result = new ex.grpc.Helloworld.HelloReply(this);
+        result.message_ = message_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof ex.grpc.Helloworld.HelloReply) {
+          return mergeFrom((ex.grpc.Helloworld.HelloReply)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(ex.grpc.Helloworld.HelloReply other) {
+        if (other == ex.grpc.Helloworld.HelloReply.getDefaultInstance()) return this;
+        if (!other.getMessage().isEmpty()) {
+          message_ = other.message_;
+          onChanged();
+        }
+        onChanged();
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        ex.grpc.Helloworld.HelloReply parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (ex.grpc.Helloworld.HelloReply) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      private java.lang.Object message_ = "";
+      /**
+       * <code>optional string message = 1;</code>
+       */
+      public java.lang.String getMessage() {
+        java.lang.Object ref = message_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            message_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string message = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getMessageBytes() {
+        java.lang.Object ref = message_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          message_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string message = 1;</code>
+       */
+      public Builder setMessage(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        message_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string message = 1;</code>
+       */
+      public Builder clearMessage() {
+        
+        message_ = getDefaultInstance().getMessage();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string message = 1;</code>
+       */
+      public Builder setMessageBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        message_ = value;
+        onChanged();
+        return this;
+      }
+      public final Builder setUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return this;
+      }
+
+      public final Builder mergeUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return this;
+      }
+
+
+      // @@protoc_insertion_point(builder_scope:helloworld.HelloReply)
+    }
+
+    // @@protoc_insertion_point(class_scope:helloworld.HelloReply)
+    private static final ex.grpc.Helloworld.HelloReply defaultInstance;static {
+      defaultInstance = new ex.grpc.Helloworld.HelloReply();
+    }
+
+    public static ex.grpc.Helloworld.HelloReply getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public ex.grpc.Helloworld.HelloReply getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+  }
+
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_helloworld_HelloRequest_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_helloworld_HelloRequest_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_helloworld_HelloReply_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_helloworld_HelloReply_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\037src/main/proto/helloworld.proto\022\nhello" +
+      "world\"\034\n\014HelloRequest\022\014\n\004name\030\001 \001(\t\"\035\n\nH" +
+      "elloReply\022\017\n\007message\030\001 \001(\t2H\n\tGreetings\022" +
+      ";\n\005hello\022\030.helloworld.HelloRequest\032\026.hel" +
+      "loworld.HelloReply\"\000B\t\n\007ex.grpcb\006proto3"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+        new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
+          public com.google.protobuf.ExtensionRegistry assignDescriptors(
+              com.google.protobuf.Descriptors.FileDescriptor root) {
+            descriptor = root;
+            return null;
+          }
+        };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+    internal_static_helloworld_HelloRequest_descriptor =
+      getDescriptor().getMessageTypes().get(0);
+    internal_static_helloworld_HelloRequest_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_helloworld_HelloRequest_descriptor,
+        new java.lang.String[] { "Name", });
+    internal_static_helloworld_HelloReply_descriptor =
+      getDescriptor().getMessageTypes().get(1);
+    internal_static_helloworld_HelloReply_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_helloworld_HelloReply_descriptor,
+        new java.lang.String[] { "Message", });
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/src/main/proto/helloworld.proto b/src/main/proto/helloworld.proto
new file mode 100644
index 0000000000000000000000000000000000000000..da5c3a1d85daaf554e536c8abdb47dbe82270ce8
--- /dev/null
+++ b/src/main/proto/helloworld.proto
@@ -0,0 +1,22 @@
+syntax = "proto3";
+
+option java_package = "ex.grpc";
+
+package helloworld;
+
+// The request message containing the user's name.
+message HelloRequest {
+  optional string name = 1;
+}
+
+// The response message containing the greetings
+message HelloReply {
+  optional string message = 1;
+}
+
+// The greeting service definition.
+service Greetings {
+  // Sends a greeting
+  rpc hello (HelloRequest) returns (HelloReply) {
+  }
+}