diff --git a/grpc/tests/JavaGrpcTest.java b/grpc/tests/JavaGrpcTest.java
new file mode 100644
index 0000000..98a67b5
--- /dev/null
+++ b/grpc/tests/JavaGrpcTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import MyGame.Example.Monster;
+import MyGame.Example.MonsterStorageGrpc;
+import MyGame.Example.Stat;
+import com.google.flatbuffers.FlatBufferBuilder;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.Server;
+import io.grpc.ServerBuilder;
+import io.grpc.stub.StreamObserver;
+import org.junit.Assert;
+
+import java.io.IOException;
+import java.lang.InterruptedException;
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.CountDownLatch;
+
+
+/**
+ * Demonstrates basic client-server interaction using grpc-java over netty.
+ */
+public class JavaGrpcTest {
+    static final String BIG_MONSTER_NAME = "Cyberdemon";
+    static final short nestedMonsterHp = 600;
+    static final short nestedMonsterMana = 1024;
+    static final int numStreamedMsgs = 10;
+    static final int timeoutMs = 3000;
+    static Server server;
+    static ManagedChannel channel;
+    static MonsterStorageGrpc.MonsterStorageBlockingStub blockingStub;
+    static MonsterStorageGrpc.MonsterStorageStub asyncStub;
+
+    static class MyService extends MonsterStorageGrpc.MonsterStorageImplBase {
+        @Override
+        public void store(Monster request, io.grpc.stub.StreamObserver<Stat> responseObserver) {
+            Assert.assertEquals(request.name(), BIG_MONSTER_NAME);
+            Assert.assertEquals(request.hp(), nestedMonsterHp);
+            Assert.assertEquals(request.mana(), nestedMonsterMana);
+            System.out.println("Received store request from " + request.name());
+            // Create a response from the incoming request name.
+            Stat stat = GameFactory.createStat("Hello " + request.name(), 100, 10);
+            responseObserver.onNext(stat);
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void retrieve(Stat request, io.grpc.stub.StreamObserver<Monster> responseObserver) {
+            // Create 10 monsters for streaming response.
+            for (int i=0; i<numStreamedMsgs; i++) {
+                Monster monster = GameFactory.createMonsterFromStat(request, i);
+                responseObserver.onNext(monster);
+            }
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public StreamObserver<Monster> getMaxHitPoint(final StreamObserver<Stat> responseObserver) {
+          return computeMinMax(responseObserver, false);
+        }
+
+        @Override
+        public StreamObserver<Monster> getMinMaxHitPoints(final StreamObserver<Stat> responseObserver) {
+          return computeMinMax(responseObserver, true);
+        }
+
+        private StreamObserver<Monster> computeMinMax(final StreamObserver<Stat> responseObserver, final boolean includeMin) {
+          final AtomicInteger maxHp = new AtomicInteger(Integer.MIN_VALUE);
+          final AtomicReference<String> maxHpMonsterName = new AtomicReference<String>();
+          final AtomicInteger maxHpCount = new AtomicInteger();
+
+          final AtomicInteger minHp = new AtomicInteger(Integer.MAX_VALUE);
+          final AtomicReference<String> minHpMonsterName = new AtomicReference<String>();
+          final AtomicInteger minHpCount = new AtomicInteger();
+
+          return new StreamObserver<Monster>() {
+            public void onNext(Monster monster) {
+              if (monster.hp() > maxHp.get()) {
+                // Found a monster of higher hit points.
+                maxHp.set(monster.hp());
+                maxHpMonsterName.set(monster.name()); 
+                maxHpCount.set(1);
+              }
+              else if (monster.hp() == maxHp.get()) {
+                // Count how many times we saw a monster of current max hit points.
+                maxHpCount.getAndIncrement();
+              }
+
+              if (monster.hp() < minHp.get()) {
+                // Found a monster of a lower hit points.
+                minHp.set(monster.hp());
+                minHpMonsterName.set(monster.name());
+                minHpCount.set(1);
+              }
+              else if (monster.hp() == minHp.get()) {
+                // Count how many times we saw a monster of current min hit points.
+                minHpCount.getAndIncrement();
+              }
+            }
+            public void onCompleted() {
+              Stat maxHpStat = GameFactory.createStat(maxHpMonsterName.get(), maxHp.get(), maxHpCount.get());
+              // Send max hit points first.
+              responseObserver.onNext(maxHpStat);
+              if (includeMin) {
+                // Send min hit points.
+                Stat minHpStat = GameFactory.createStat(minHpMonsterName.get(), minHp.get(), minHpCount.get());
+                responseObserver.onNext(minHpStat);
+              }
+              responseObserver.onCompleted();
+            }
+            public void onError(Throwable t) {
+              // Not expected
+              Assert.fail();
+            };
+          };
+        }
+    }
+
+    @org.junit.BeforeClass
+    public static void startServer() throws IOException {
+        server = ServerBuilder.forPort(0).addService(new MyService()).build().start();
+        int port = server.getPort();
+        channel = ManagedChannelBuilder.forAddress("localhost", port)
+                // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
+                // needing certificates.
+                .usePlaintext(true)
+                .directExecutor()
+                .build();
+        blockingStub = MonsterStorageGrpc.newBlockingStub(channel);
+        asyncStub = MonsterStorageGrpc.newStub(channel);
+    }
+
+    @org.junit.Test
+    public void testUnary() throws IOException {
+        Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
+        Stat stat = blockingStub.store(monsterRequest);
+        Assert.assertEquals(stat.id(), "Hello " + BIG_MONSTER_NAME);
+        System.out.println("Received stat response from service: " + stat.id());
+    }
+
+    @org.junit.Test
+    public void testServerStreaming() throws IOException {
+        Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
+        Stat stat = blockingStub.store(monsterRequest);
+        Iterator<Monster> iterator = blockingStub.retrieve(stat);
+        int counter = 0;
+        while(iterator.hasNext()) {
+            Monster m = iterator.next();
+            System.out.println("Received monster " + m.name());
+            counter ++;
+        }
+        Assert.assertEquals(counter, numStreamedMsgs);
+        System.out.println("FlatBuffers GRPC client/server test: completed successfully");
+    }
+
+    @org.junit.Test
+    public void testClientStreaming() throws IOException, InterruptedException {
+      final AtomicReference<Stat> maxHitStat = new AtomicReference<Stat>();
+      final CountDownLatch streamAlive = new CountDownLatch(1);
+
+      StreamObserver<Stat> statObserver = new StreamObserver<Stat>() {
+        public void onCompleted() { 
+          streamAlive.countDown();
+        }
+        public void onError(Throwable ex) { }
+        public void onNext(Stat stat) {
+          maxHitStat.set(stat);
+        }
+      };
+      StreamObserver<Monster> monsterStream = asyncStub.getMaxHitPoint(statObserver);
+      short count = 10;
+      for (short i = 0;i < count; ++i) {
+        Monster monster = GameFactory.createMonster(BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana);
+        monsterStream.onNext(monster);
+      }
+      monsterStream.onCompleted();
+      // Wait a little bit for the server to send the stats of the monster with the max hit-points.
+      streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS);
+      Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1));
+      Assert.assertEquals(maxHitStat.get().val(), nestedMonsterHp * (count - 1));
+      Assert.assertEquals(maxHitStat.get().count(), 1);
+    }
+
+    @org.junit.Test
+    public void testBiDiStreaming() throws IOException, InterruptedException {
+      final AtomicReference<Stat> maxHitStat = new AtomicReference<Stat>();
+      final AtomicReference<Stat> minHitStat = new AtomicReference<Stat>();
+      final CountDownLatch streamAlive = new CountDownLatch(1);
+
+      StreamObserver<Stat> statObserver = new StreamObserver<Stat>() {
+        public void onCompleted() {
+          streamAlive.countDown();
+        }
+        public void onError(Throwable ex) { }
+        public void onNext(Stat stat) {
+          // We expect the server to send the max stat first and then the min stat.
+          if (maxHitStat.get() == null) {
+            maxHitStat.set(stat);
+          }
+          else {
+            minHitStat.set(stat);
+          }
+        }
+      };
+      StreamObserver<Monster> monsterStream = asyncStub.getMinMaxHitPoints(statObserver);
+      short count = 10;
+      for (short i = 0;i < count; ++i) {
+        Monster monster = GameFactory.createMonster(BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana);
+        monsterStream.onNext(monster);
+      }
+      monsterStream.onCompleted();
+
+      // Wait a little bit for the server to send the stats of the monster with the max and min hit-points.
+      streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS);
+
+      Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1));
+      Assert.assertEquals(maxHitStat.get().val(), nestedMonsterHp * (count - 1));
+      Assert.assertEquals(maxHitStat.get().count(), 1);
+
+      Assert.assertEquals(minHitStat.get().id(), BIG_MONSTER_NAME + 0);
+      Assert.assertEquals(minHitStat.get().val(), nestedMonsterHp * 0);
+      Assert.assertEquals(minHitStat.get().count(), 1);
+    }
+}
