Adding RouteGuide example and deleting others.

This commit is contained in:
nmittler 2015-02-23 12:03:59 -08:00
parent 494d273b05
commit b897a89e78
14 changed files with 1410 additions and 909 deletions

View File

@ -20,16 +20,17 @@ subprojects {
ext {
libraries = [
protobuf: 'com.google.protobuf:protobuf-java:3.0.0-pre',
guava: 'com.google.guava:guava:18.0',
jsr305: 'com.google.code.findbugs:jsr305:3.0.0',
oauth_client: 'com.google.oauth-client:google-oauth-client:1.18.0-rc',
javaee_api: 'javax:javaee-api:7.0',
hpack: 'com.twitter:hpack:0.9.1',
protobuf_plugin: 'ws.antonov.gradle.plugins:gradle-plugin-protobuf:0.9.1',
okhttp: 'com.squareup.okhttp:okhttp:2.2.0',
// used to collect benchmark results
hdrhistogram: 'org.hdrhistogram:HdrHistogram:2.1.4',
hpack: 'com.twitter:hpack:0.9.1',
javaee_api: 'javax:javaee-api:7.0',
jsonp: 'org.glassfish:javax.json:1.0.4',
jsr305: 'com.google.code.findbugs:jsr305:3.0.0',
oauth_client: 'com.google.oauth-client:google-oauth-client:1.18.0-rc',
okhttp: 'com.squareup.okhttp:okhttp:2.2.0',
protobuf: 'com.google.protobuf:protobuf-java:3.0.0-pre',
protobuf_plugin: 'ws.antonov.gradle.plugins:gradle-plugin-protobuf:0.9.1',
// TODO: Unreleased dependencies.
// These must already be installed in the local maven repository.

View File

@ -1,22 +1,19 @@
grpc Examples
==============================================
In order to run the examples simply execute one of the gradle tasks `mathserver`, `mathclient`,
`stockserver` or `stockclient`.
In order to run the examples simply execute one of the gradle tasks `routeGuideServer` or
`routeGuideClient`.
For example, say you want to play around with the math examples. First you want to start
the server and then have the client connect to it and do some fun calculations.
Assuming you are in the grpc-java root folder you would first start the math server by running
Assuming you are in the grpc-java root folder you would first start the server by running
```
$ ./gradlew :grpc-examples:mathserver
$ ./gradlew :grpc-examples:routeGuideServer
```
and in a different terminal window then run the client by typing
```
$ ./gradlew :grpc-examples:mathclient
$ ./gradlew :grpc-examples:routeGuideClient
```
That's it!

View File

@ -16,32 +16,21 @@ dependencies {
compile project(':grpc-core'),
project(':grpc-netty'),
project(':grpc-okhttp'),
project(':grpc-stub')
project(':grpc-stub'),
libraries.jsonp
}
protobufCodeGenPlugins = ["java_plugin:$rootDir/compiler/build/binaries/java_pluginExecutable/java_plugin"]
generateProto.dependsOn ':grpc-compiler:java_pluginExecutable'
task mathserver(type: JavaExec) {
main = "io.grpc.examples.MathServer"
description = "Executes the math server."
task routeGuideServer(type: JavaExec) {
main = "io.grpc.examples.RouteGuideServer"
description = "Executes the route guide server."
classpath = sourceSets.main.runtimeClasspath
}
task mathclient(type: JavaExec) {
main = "io.grpc.examples.MathClient"
description = "Executes the math client."
classpath = sourceSets.main.runtimeClasspath
}
task stockserver(type: JavaExec) {
main = "io.grpc.examples.StockServer"
description = "Executes the stock server."
classpath = sourceSets.main.runtimeClasspath
}
task stockclient(type: JavaExec) {
main = "io.grpc.examples.StockClient"
description = "Executes the stock client."
task routeGuideClient(type: JavaExec) {
main = "io.grpc.examples.RouteGuideClient"
description = "Executes the route guide client."
classpath = sourceSets.main.runtimeClasspath
}

View File

@ -1,251 +0,0 @@
/*
* Copyright 2014, 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.
*/
package io.grpc.examples;
import com.google.common.util.concurrent.SettableFuture;
import io.grpc.examples.CalcGrpc;
import io.grpc.examples.CalcGrpc.CalcBlockingStub;
import io.grpc.examples.CalcGrpc.CalcStub;
import io.grpc.examples.Math.DivArgs;
import io.grpc.examples.Math.DivReply;
import io.grpc.examples.Math.FibArgs;
import io.grpc.examples.Math.Num;
import io.grpc.ChannelImpl;
import io.grpc.stub.StreamObserver;
import io.grpc.transport.netty.NegotiationType;
import io.grpc.transport.netty.NettyChannelBuilder;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Sample client code that makes gRPC calls to the server.
*/
public class MathClient {
private final Logger logger = Logger.getLogger(MathClient.class.getName());
private final Random rand = new Random();
private final ChannelImpl channel;
private final CalcBlockingStub blockingStub;
private final CalcStub asyncStub;
public MathClient(String host, int port) {
channel = NettyChannelBuilder.forAddress(host, port)
.negotiationType(NegotiationType.PLAINTEXT)
.build();
blockingStub = CalcGrpc.newBlockingStub(channel);
asyncStub = CalcGrpc.newStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTerminated(5, TimeUnit.SECONDS);
}
/**
* This example shows how to make a blocking unary call.
*/
public void blockingDiv(long dividend, long divisor) {
logger.info("*** Blocking Div: Dividend=" + dividend + ", Divisor=" + divisor);
DivReply reply;
try {
reply = blockingStub.div(
DivArgs.newBuilder().setDividend(dividend).setDivisor(divisor).build());
} catch (RuntimeException e) {
logger.log(Level.WARNING, "RPC failed", e);
return;
}
logger.info("Result: Quotient=" + reply.getQuotient() + ", remainder=" + reply.getRemainder());
}
/**
* This example shows how to make an asynchronous unary call.
*/
public void asyncDiv(long dividend, long divisor) {
logger.info("*** Async Div: Dividend=" + dividend + ", Divisor=" + divisor);
DivArgs request = DivArgs.newBuilder().setDividend(dividend).setDivisor(divisor).build();
final SettableFuture<DivReply> responseFuture = SettableFuture.create();
asyncStub.div(request, new StreamObserver<DivReply> (){
DivReply reply;
@Override
public void onValue(DivReply value) {
reply = value;
}
@Override
public void onError(Throwable t) {
responseFuture.setException(t);
}
@Override
public void onCompleted() {
responseFuture.set(reply);
}
});
logger.info("Waiting for result...");
try {
DivReply reply = responseFuture.get();
logger.info(
"Result: Quotient=" + reply.getQuotient() + ", remainder=" + reply.getRemainder());
} catch (InterruptedException e) {
logger.log(Level.WARNING, "Interrupted while waiting for result...", e);
} catch (ExecutionException e) {
logger.log(Level.WARNING, "RPC failed", e);
}
}
/**
* This example shows how to make a bi-directional streaming call, which can only be asynchronous.
*/
public void divMany() {
logger.info("*** DivMany");
final SettableFuture<Void> finishFuture = SettableFuture.create();
StreamObserver<DivArgs> requestSink = asyncStub.divMany(new StreamObserver<DivReply>() {
int count = 0;
@Override
public void onValue(DivReply value) {
count++;
logger.info("Result " + count + ": Quotient=" + value.getQuotient() + ", remainder="
+ value.getRemainder());
}
@Override
public void onError(Throwable t) {
finishFuture.setException(t);
}
@Override
public void onCompleted() {
finishFuture.set(null);
}
});
int count = 5;
for (int i = 0; i < count; i++) {
long dividend = rand.nextLong();
long divisor = rand.nextInt() + 1; // plus 1 to avoid 0 divisor.
logger.info("Request " + (i + 1) + ": Dividend=" + dividend + ", Divisor=%d" + divisor);
requestSink.onValue(
DivArgs.newBuilder().setDividend(dividend).setDivisor(divisor).build());
}
requestSink.onCompleted();
try {
finishFuture.get();
logger.info("Finished " + count + " div requests");
} catch (InterruptedException e) {
logger.log(Level.WARNING, "Interrupted while waiting for result...", e);
} catch (ExecutionException e) {
logger.log(Level.WARNING, "RPC failed", e);
}
}
/**
* This example shows how to make a client streaming call.
*/
public void sum() throws InterruptedException {
final CountDownLatch completed = new CountDownLatch(1);
logger.info("*** Sum");
int count = 5;
StreamObserver<Num> responseObserver = new StreamObserver<Num>() {
@Override
public void onValue(Num value) {
logger.info("Sum=" + value);
}
@Override
public void onError(Throwable t) {
logger.log(Level.SEVERE, "Error receiving response", t);
}
@Override
public void onCompleted() {
completed.countDown();
}
};
StreamObserver<Num> requestObserver = asyncStub.sum(responseObserver);
StringBuilder numMsg = new StringBuilder();
for (int i = 0; i < count; i++) {
int value = rand.nextInt();
requestObserver.onValue(Num.newBuilder().setNum(value).build());
numMsg.append(value);
if (i != count - 1) {
numMsg.append(" + ");
}
}
logger.info(numMsg.toString());
requestObserver.onCompleted();
completed.await();
}
/**
* This example shows how to make a blocking server streaming call.
*
* <p> The asynchronous usage is similar to {@link #divMany}.
*/
public void blockingFib() {
// TODO(madongfly): Support "send until cancel". Currently, client application can not
// cancel a server streaming call.
int limit = rand.nextInt(20) + 10;
logger.info("*** Blocking Fib, print the first " + limit + " fibonacci numbers.");
Iterator<Num> iterator = blockingStub.fib(FibArgs.newBuilder().setLimit(limit).build());
StringBuilder resultMsg = new StringBuilder();
int realCount = 0;
while (iterator.hasNext()) {
realCount++;
resultMsg.append(iterator.next().getNum());
resultMsg.append(", ");
}
logger.info("The first " + realCount + " fibonacci numbers: " + resultMsg.toString());
}
public static void main(String[] args) throws InterruptedException {
MathClient client = new MathClient("localhost", 8980);
try {
client.blockingDiv(2014, 4);
// Note: This call should be failed, but we can not get the server specified error info
// currently, so the error message logged is not clear.
client.blockingDiv(73, 0);
client.asyncDiv(1986, 12);
client.divMany();
client.sum();
client.blockingFib();
} finally {
client.shutdown();
}
}
}

View File

@ -1,184 +0,0 @@
/*
* Copyright 2014, 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.
*/
package io.grpc.examples;
import io.grpc.examples.CalcGrpc;
import io.grpc.examples.Math.DivArgs;
import io.grpc.examples.Math.DivReply;
import io.grpc.examples.Math.FibArgs;
import io.grpc.examples.Math.Num;
import io.grpc.ServerImpl;
import io.grpc.stub.StreamObserver;
import io.grpc.transport.netty.NettyServerBuilder;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A sample gRPC server that serve the Calc (see math.proto) service.
*/
public class MathServer {
private final Logger logger = Logger.getLogger(MathServer.class.getName());
private final int port;
private ServerImpl gRpcServer;
public MathServer(int port) {
this.port = port;
}
public void start() {
gRpcServer = NettyServerBuilder.forPort(port)
.addService(CalcGrpc.bindService(new CalcService()))
.build().start();
logger.info("Server started, listening on " + port);
// TODO(madongfly): 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() {
// 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");
MathServer.this.stop();
System.err.println("*** server shut down");
}
});
}
public void stop() {
if (gRpcServer != null) {
gRpcServer.shutdown();
}
}
public static void main(String[] args) throws Exception {
MathServer server = new MathServer(8980);
server.start();
}
/**
* Our implementation of Calc service.
*
* <p> See math.proto for details of the methods.
*/
private class CalcService implements CalcGrpc.Calc {
@Override
public void div(DivArgs request, StreamObserver<DivReply> responseObserver) {
if (request.getDivisor() == 0) {
responseObserver.onError(new IllegalArgumentException("divisor is 0"));
return;
}
responseObserver.onValue(div(request));
responseObserver.onCompleted();
}
@Override
public StreamObserver<DivArgs> divMany(final StreamObserver<DivReply> responseObserver) {
return new StreamObserver<DivArgs>() {
@Override
public void onValue(DivArgs value) {
if (value.getDivisor() == 0) {
responseObserver.onError(new IllegalArgumentException("divisor is 0"));
return;
}
responseObserver.onValue(div(value));
}
@Override
public void onError(Throwable t) {
logger.log(Level.WARNING, "Encountered error in divMany", t);
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}};
}
@Override
public void fib(FibArgs request, StreamObserver<Num> responseObserver) {
int limit = (int) request.getLimit();
if (limit <= 0) {
// TODO(madongfly): Support "send until cancel". Currently, client application can not
// cancel a server streaming call.
return;
}
long preLast = 1;
long last = 1;
for (int i = 0; i < limit; i++) {
if (i < 2) {
responseObserver.onValue(Num.newBuilder().setNum(1).build());
} else {
long fib = preLast + last;
responseObserver.onValue(Num.newBuilder().setNum(fib).build());
preLast = last;
last = fib;
}
}
responseObserver.onCompleted();
}
@Override
public StreamObserver<Num> sum(final StreamObserver<Num> responseObserver) {
return new StreamObserver<Num>() {
long sum = 0;
@Override
public void onValue(Num value) {
sum += value.getNum();
}
@Override
public void onError(Throwable t) {
logger.log(Level.WARNING, "Encountered error in sum", t);
}
@Override
public void onCompleted() {
responseObserver.onValue(Num.newBuilder().setNum(sum).build());
responseObserver.onCompleted();
}
};
}
private DivReply div(DivArgs request) {
long divisor = request.getDivisor();
long dividend = request.getDividend();
return DivReply.newBuilder()
.setQuotient(dividend / divisor)
.setRemainder(dividend % divisor)
.build();
}
}
}

View File

@ -0,0 +1,255 @@
/*
* 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.
*/
package io.grpc.examples;
import com.google.common.util.concurrent.SettableFuture;
import io.grpc.ChannelImpl;
import io.grpc.examples.RouteGuideGrpc.RouteGuideBlockingStub;
import io.grpc.examples.RouteGuideGrpc.RouteGuideStub;
import io.grpc.examples.RouteGuideOuterClass.Feature;
import io.grpc.examples.RouteGuideOuterClass.Point;
import io.grpc.examples.RouteGuideOuterClass.Rectangle;
import io.grpc.examples.RouteGuideOuterClass.RouteNote;
import io.grpc.examples.RouteGuideOuterClass.RouteSummary;
import io.grpc.stub.StreamObserver;
import io.grpc.transport.netty.NegotiationType;
import io.grpc.transport.netty.NettyChannelBuilder;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Sample client code that makes gRPC calls to the server.
*/
public class RouteGuideClient {
private static final Logger logger = Logger.getLogger(RouteGuideClient.class.getName());
private final ChannelImpl channel;
private final RouteGuideBlockingStub blockingStub;
private final RouteGuideStub asyncStub;
public RouteGuideClient(String host, int port) {
channel = NettyChannelBuilder.forAddress(host, port)
.negotiationType(NegotiationType.PLAINTEXT)
.build();
blockingStub = RouteGuideGrpc.newBlockingStub(channel);
asyncStub = RouteGuideGrpc.newStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTerminated(5, TimeUnit.SECONDS);
}
/**
* This example shows how to make a blocking unary call.
*/
public void getFeature(int lat, int lon) {
try {
info("*** GetFeature: lat={0} lon={1}", lat, lon);
Point request = Point.newBuilder().setLatitude(lat).setLongitude(lon).build();
Feature feature = blockingStub.getFeature(request);
if (RouteGuideUtil.exists(feature)) {
info("Found feature called \"{0}\" at {1}, {2}",
feature.getName(),
RouteGuideUtil.getLatitude(feature.getLocation()),
RouteGuideUtil.getLongitude(feature.getLocation()));
} else {
info("Found no feature at {0}, {1}",
RouteGuideUtil.getLatitude(feature.getLocation()),
RouteGuideUtil.getLongitude(feature.getLocation()));
}
} catch (RuntimeException e) {
logger.log(Level.WARNING, "RPC failed", e);
throw e;
}
}
/**
* This example shows how to make a blocking unary call.
*/
public void listFeatures(int lowLat, int lowLon, int hiLat, int hiLon) {
try {
info("*** ListFeatures: lowLat={0} lowLon={1} hiLat={2} hiLon={3}", lowLat, lowLon, hiLat,
hiLon);
Rectangle request =
Rectangle.newBuilder()
.setLo(Point.newBuilder().setLatitude(lowLat).setLongitude(lowLon).build())
.setHi(Point.newBuilder().setLatitude(hiLat).setLongitude(hiLon).build()).build();
Iterator<Feature> features = blockingStub.listFeatures(request);
StringBuilder responseLog = new StringBuilder("Result: ");
while (features.hasNext()) {
Feature feature = features.next();
responseLog.append(feature);
}
info(responseLog.toString());
} catch (RuntimeException e) {
logger.log(Level.WARNING, "RPC failed", e);
throw e;
}
}
public void recordRoute(List<Feature> features, int numPoints) throws Exception {
info("*** RecordRoute");
final SettableFuture<Void> finishFuture = SettableFuture.create();
StreamObserver<RouteSummary> responseObserver = new StreamObserver<RouteSummary>() {
@Override
public void onValue(RouteSummary summary) {
info("Finished trip with {0} points. Passed {1} features. "
+ "Travelled {2} meters. It took {3} seconds.", summary.getPointCount(),
summary.getFeatureCount(), summary.getDistance(), summary.getElapsedTime());
}
@Override
public void onError(Throwable t) {
finishFuture.setException(t);
}
@Override
public void onCompleted() {
finishFuture.set(null);
}
};
StreamObserver<Point> requestObserver = asyncStub.recordRoute(responseObserver);
try {
// Send numPoints points randomly selected from the features list.
StringBuilder numMsg = new StringBuilder();
Random rand = new Random();
for (int i = 0; i < numPoints; ++i) {
int index = rand.nextInt(features.size());
Point point = features.get(index).getLocation();
info("Visiting point {0}, {1}", RouteGuideUtil.getLatitude(point),
RouteGuideUtil.getLongitude(point));
requestObserver.onValue(point);
// Sleep for a bit before sending the next one.
Thread.sleep(rand.nextInt(1000) + 500);
if (finishFuture.isDone()) {
break;
}
}
info(numMsg.toString());
requestObserver.onCompleted();
finishFuture.get();
info("Finished RecordRoute");
} catch (Exception e) {
requestObserver.onError(e);
logger.log(Level.WARNING, "RecordRoute Failed", e);
throw e;
}
}
/**
* This example shows how to make a bi-directional streaming call, which can only be asynchronous.
*/
public void routeChat() throws Exception {
info("*** RoutChat");
final SettableFuture<Void> finishFuture = SettableFuture.create();
StreamObserver<RouteNote> requestObserver =
asyncStub.routeChat(new StreamObserver<RouteNote>() {
@Override
public void onValue(RouteNote note) {
info("Got message \"{0}\" at {1}, {2}", note.getMessage(), note.getLocation()
.getLatitude(), note.getLocation().getLongitude());
}
@Override
public void onError(Throwable t) {
finishFuture.setException(t);
}
@Override
public void onCompleted() {
finishFuture.set(null);
}
});
try {
RouteNote[] requests =
{newNote("First message", 0, 0), newNote("Second message", 0, 1),
newNote("Third message", 1, 0), newNote("Fourth message", 1, 1)};
for (RouteNote request : requests) {
info("Sending message \"{0}\" at {1}, {2}", request.getMessage(), request.getLocation()
.getLatitude(), request.getLocation().getLongitude());
requestObserver.onValue(request);
}
requestObserver.onCompleted();
finishFuture.get();
info("Finished RouteChat");
} catch (Exception t) {
requestObserver.onError(t);
logger.log(Level.WARNING, "RouteChat Failed", t);
throw t;
}
}
public static void main(String[] args) throws Exception {
RouteGuideClient client = new RouteGuideClient("localhost", 8980);
try {
// Looking for a valid feature
client.getFeature(409146138, -746188906);
// Feature missing.
client.getFeature(0, 0);
// Looking for features between 40, -75 and 42, -73.
client.listFeatures(400000000, -750000000, 420000000, -730000000);
// Record a few randomly selected points from the features file.
client.recordRoute(RouteGuideUtil.parseFeatures(RouteGuideUtil.getDefaultFeaturesFile()), 10);
// Send and receive some notes.
client.routeChat();
} finally {
client.shutdown();
}
}
private static void info(String msg, Object... params) {
logger.log(Level.INFO, msg, params);
}
private RouteNote newNote(String message, int lat, int lon) {
return RouteNote.newBuilder().setMessage(message)
.setLocation(Point.newBuilder().setLatitude(lat).setLongitude(lon).build()).build();
}
}

View File

@ -0,0 +1,302 @@
/*
* 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.
*/
package io.grpc.examples;
import static java.lang.Math.atan2;
import static java.lang.Math.cos;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.sin;
import static java.lang.Math.sqrt;
import static java.lang.Math.toRadians;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import io.grpc.ServerImpl;
import io.grpc.examples.RouteGuideOuterClass.Feature;
import io.grpc.examples.RouteGuideOuterClass.Point;
import io.grpc.examples.RouteGuideOuterClass.Rectangle;
import io.grpc.examples.RouteGuideOuterClass.RouteNote;
import io.grpc.examples.RouteGuideOuterClass.RouteSummary;
import io.grpc.stub.StreamObserver;
import io.grpc.transport.netty.NettyServerBuilder;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A sample gRPC server that serve the RouteGuide (see route_guide.proto) service.
*/
public class RouteGuideServer {
private static final Logger logger = Logger.getLogger(RouteGuideServer.class.getName());
private final int port;
private final Collection<Feature> features;
private ServerImpl gRpcServer;
public RouteGuideServer(int port) {
this(port, RouteGuideUtil.getDefaultFeaturesFile());
}
public RouteGuideServer(int port, URL featureFile) {
try {
this.port = port;
features = RouteGuideUtil.parseFeatures(featureFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void start() {
gRpcServer = NettyServerBuilder.forPort(port)
.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() {
// 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");
RouteGuideServer.this.stop();
System.err.println("*** server shut down");
}
});
}
public void stop() {
if (gRpcServer != null) {
gRpcServer.shutdown();
}
}
public static void main(String[] args) throws Exception {
RouteGuideServer server = new RouteGuideServer(8980);
server.start();
}
/**
* Our implementation of RouteGuide service.
*
* <p> See route_guide.proto for details of the methods.
*/
private static class RouteGuideService implements RouteGuideGrpc.RouteGuide {
private final Collection<Feature> features;
private final ConcurrentMap<Point, List<RouteNote>> routeNotes =
new ConcurrentHashMap<Point, List<RouteNote>>();
RouteGuideService(Collection<Feature> features) {
this.features = features;
}
/**
* Gets the {@link Feature} at the requested {@link Point}. If no feature at that location
* exists, an unnammed feature is returned at the provided location.
*
* @param request the requested location for the feature.
* @param responseObserver the observer that will receive the feature at the requested point.
*/
@Override
public void getFeature(Point request, StreamObserver<Feature> responseObserver) {
responseObserver.onValue(getFeature(request));
responseObserver.onCompleted();
}
/**
* Gets all features contained within the given bounding {@link Rectangle}.
*
* @param request the bounding rectangle for the requested features.
* @param responseObserver the observer that will receive the features.
*/
@Override
public void listFeatures(Rectangle request, StreamObserver<Feature> responseObserver) {
int left = min(request.getLo().getLongitude(), request.getHi().getLongitude());
int right = max(request.getLo().getLongitude(), request.getHi().getLongitude());
int top = max(request.getLo().getLatitude(), request.getHi().getLatitude());
int bottom = min(request.getLo().getLatitude(), request.getHi().getLatitude());
for (Feature feature : features) {
if (!RouteGuideUtil.exists(feature)) {
continue;
}
int lat = feature.getLocation().getLatitude();
int lon = feature.getLocation().getLongitude();
if (lon >= left && lon <= right && lat >= bottom && lat <= top) {
responseObserver.onValue(feature);
}
}
responseObserver.onCompleted();
}
/**
* Gets a stream of points, and responds with statistics about the "trip": number of points,
* number of known features visited, total distance traveled, and total time spent.
*
* @param responseObserver an observer to receive the response summary.
* @return an observer to receive the requested route points.
*/
@Override
public StreamObserver<Point> recordRoute(final StreamObserver<RouteSummary> responseObserver) {
return new StreamObserver<Point>() {
int pointCount;
int featureCount;
int distance;
Point previous;
long startTime = System.nanoTime();
@Override
public void onValue(Point point) {
pointCount++;
if (RouteGuideUtil.exists(getFeature(point))) {
featureCount++;
}
// For each point after the first, add the incremental distance from the previous point to
// the total distance value.
if (previous != null) {
distance += calcDistance(previous, point);
}
previous = point;
}
@Override
public void onError(Throwable t) {
logger.log(Level.WARNING, "Encountered error in recordRoute", t);
}
@Override
public void onCompleted() {
long seconds = NANOSECONDS.toSeconds(System.nanoTime() - startTime);
responseObserver.onValue(RouteSummary.newBuilder().setPointCount(pointCount)
.setFeatureCount(featureCount).setDistance(distance)
.setElapsedTime((int) seconds).build());
responseObserver.onCompleted();
}
};
}
/**
* Receives a stream of message/location pairs, and responds with a stream of all previous
* messages at each of those locations.
*
* @param responseObserver an observer to receive the stream of previous messages.
* @return an observer to handle requested message/location pairs.
*/
@Override
public StreamObserver<RouteNote> routeChat(final StreamObserver<RouteNote> responseObserver) {
return new StreamObserver<RouteNote>() {
@Override
public void onValue(RouteNote note) {
List<RouteNote> notes = getOrCreateNotes(note.getLocation());
// Respond with all previous notes at this location.
for (RouteNote prevNote : notes.toArray(new RouteNote[0])) {
responseObserver.onValue(prevNote);
}
// Now add the new note to the list
notes.add(note);
}
@Override
public void onError(Throwable t) {
logger.log(Level.WARNING, "Encountered error in routeChat", t);
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
/**
* Get the notes list for the given location. If missing, create it.
*/
private List<RouteNote> getOrCreateNotes(Point location) {
List<RouteNote> notes = Collections.synchronizedList(new ArrayList<RouteNote>());
List<RouteNote> prevNotes = routeNotes.putIfAbsent(location, notes);
return prevNotes != null ? prevNotes : notes;
}
/**
* Gets the feature at the given point.
*
* @param location the location to check.
* @return The feature object at the point. Note that an empty name indicates no feature.
*/
private Feature getFeature(Point location) {
for (Feature feature : features) {
if (feature.getLocation().getLatitude() == location.getLatitude()
&& feature.getLocation().getLongitude() == location.getLongitude()) {
return feature;
}
}
// No feature was found, return an unnamed feature.
return Feature.newBuilder().setName("").setLocation(location).build();
}
/**
* Calculate the distance between two points using the "haversine" formula.
* This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
*
* @param start The starting point
* @param end The end point
* @return The distance between the points in meters
*/
private static double calcDistance(Point start, Point end) {
double lat1 = RouteGuideUtil.getLatitude(start);
double lat2 = RouteGuideUtil.getLatitude(end);
double lon1 = RouteGuideUtil.getLongitude(start);
double lon2 = RouteGuideUtil.getLongitude(end);
int R = 6371000; // metres
double φ1 = toRadians(lat1);
double φ2 = toRadians(lat2);
double Δφ = toRadians(lat2-lat1);
double Δλ = toRadians(lon2-lon1);
double a = sin(Δφ/2) * sin(Δφ/2) + cos(φ1) * cos(φ2) * sin(Δλ/2) * sin(Δλ/2);
double c = 2 * atan2(sqrt(a), sqrt(1-a));
return R * c;
}
}
}

View File

@ -0,0 +1,111 @@
/*
* 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.
*/
package io.grpc.examples;
import io.grpc.examples.RouteGuideOuterClass.Feature;
import io.grpc.examples.RouteGuideOuterClass.Point;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;
/**
* Common utilities for the RouteGuide demo.
*/
public class RouteGuideUtil {
private static final double COORD_FACTOR = 1e7;
/**
* Gets the latitude for the given point.
*/
public static double getLatitude(Point location) {
return location.getLatitude() / COORD_FACTOR;
}
/**
* Gets the longitude for the given point.
*/
public static double getLongitude(Point location) {
return location.getLongitude() / COORD_FACTOR;
}
/**
* Gets the default features file from classpath.
*/
public static URL getDefaultFeaturesFile() {
return RouteGuideServer.class.getResource("route_guide_db.json");
}
/**
* Parses the JSON input file containing the list of features.
*/
public static List<Feature> parseFeatures(URL file) throws IOException {
InputStream input = file.openStream();
try {
JsonReader reader = Json.createReader(input);
List<Feature> features = new ArrayList<Feature>();
for (JsonValue value : reader.readArray()) {
JsonObject obj = (JsonObject) value;
String name = obj.getString("name", "");
JsonObject location = obj.getJsonObject("location");
int lat = location.getInt("latitude");
int lon = location.getInt("longitude");
Feature feature =
Feature
.newBuilder()
.setName(name)
.setLocation(
Point.newBuilder().setLatitude(lat)
.setLongitude(lon).build()).build();
features.add(feature);
}
return features;
} finally {
input.close();
}
}
/**
* Indicates whether the given feature exists (i.e. has a valid name).
*/
public static boolean exists(Feature feature) {
return feature != null && !feature.getName().isEmpty();
}
}

View File

@ -1,214 +0,0 @@
/*
* Copyright 2014, 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.
*/
package io.grpc.examples;
import io.grpc.examples.StockGrpc;
import io.grpc.examples.StockGrpc.StockBlockingStub;
import io.grpc.examples.StockGrpc.StockStub;
import io.grpc.examples.StockOuterClass.StockReply;
import io.grpc.examples.StockOuterClass.StockRequest;
import io.grpc.ChannelImpl;
import io.grpc.stub.StreamObserver;
import io.grpc.transport.netty.NegotiationType;
import io.grpc.transport.netty.NettyChannelBuilder;
import java.util.Iterator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Sample client code that makes GRPC calls to the server.
*/
public class StockClient {
private final ChannelImpl channel = NettyChannelBuilder.forAddress("localhost", 8980)
.negotiationType(NegotiationType.PLAINTEXT)
.build();
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTerminated(5, TimeUnit.SECONDS);
}
public void makeBlockingSimpleCall() {
StockBlockingStub stub = StockGrpc.newBlockingStub(channel)
.configureNewStub().setTimeout(2, TimeUnit.SECONDS).build();
StockRequest request = StockRequest.newBuilder().setSymbol("GOOG").build();
System.out.println("***Blocking simple call, request=" + request);
StockReply reply = stub.getLastTradePrice(request);
System.out.println("response=" + reply);
}
public void makeAsyncSimpleCall() {
StockStub stub = StockGrpc.newStub(channel)
.configureNewStub().setTimeout(2, TimeUnit.SECONDS).build();
StockRequest request = StockRequest.newBuilder().setSymbol("MSFT").build();
System.out.println("***Async simple call, request=" + request);
stub.getLastTradePrice(request, new StreamObserver<StockReply>() {
StockReply response;
@Override
public void onValue(StockReply response) {
this.response = response;
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onCompleted() {
System.out.println("Completed, response=" + response);
}
});
}
public void makeSequentialCalls() {
StockBlockingStub stub = StockGrpc.newBlockingStub(channel)
.configureNewStub().setTimeout(2, TimeUnit.SECONDS).build();
System.out.println("***Making sequential calls");
StockRequest request1 = StockRequest.newBuilder().setSymbol("AMZN").build();
System.out.println("First request=" + request1);
StockReply response1 = stub.getLastTradePrice(request1);
System.out.println("First response=" + response1);
StockRequest request2 = StockRequest.newBuilder().setSymbol(response1.getSymbol()).build();
System.out.println("Second request=" + request2);
StockReply response2 = stub.getLastTradePrice(request2);
System.out.println("Second response=" + response2);
}
public void makeAsyncCalls() throws InterruptedException {
StockStub stub = StockGrpc.newStub(channel)
.configureNewStub().setTimeout(2, TimeUnit.SECONDS).build();
System.out.println("***Making two calls in parallel");
final StockRequest request1 = StockRequest.newBuilder().setSymbol("IBM").build();
final StockRequest request2 = StockRequest.newBuilder().setSymbol("APPL").build();
final CountDownLatch completeLatch = new CountDownLatch(2);
stub.getLastTradePrice(request1, new StreamObserver<StockReply>() {
StockReply response;
@Override
public void onValue(StockReply response) {
this.response = response;
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onCompleted() {
System.out.println("Completed for first request=" + request1 + ", response=" + response);
completeLatch.countDown();
}
});
stub.getLastTradePrice(request2, new StreamObserver<StockReply>() {
StockReply response;
@Override
public void onValue(StockReply response) {
this.response = response;
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onCompleted() {
System.out.println("Completed for second request=" + request2 + ", response=" + response);
completeLatch.countDown();
}
});
completeLatch.await();
}
public void makeServerStreamingCall() {
StockBlockingStub stub = StockGrpc.newBlockingStub(channel)
.configureNewStub().setTimeout(2, TimeUnit.SECONDS).build();
StockRequest request = StockRequest.newBuilder().setSymbol("FB").setNumTradesToWatch(5).build();
System.out.println("***Making a server streaming call, request=" + request);
for (Iterator<StockReply> responses = stub.watchFutureTrades(request); responses.hasNext(); ) {
StockReply response = responses.next();
System.out.println("Response=" + response);
}
System.out.println("Completed");
}
public void makeClientStreamingCall() throws InterruptedException {
StockStub stub = StockGrpc.newStub(channel)
.configureNewStub().setTimeout(2, TimeUnit.SECONDS).build();
System.out.println("***Making a client streaming call");
final CountDownLatch completeLatch = new CountDownLatch(1);
StreamObserver<StockRequest> requestSink = stub.getHighestTradePrice(
new StreamObserver<StockReply>() {
StockReply response;
@Override
public void onValue(StockReply response) {
this.response = response;
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onCompleted() {
System.out.println("Completed. response=" + response);
completeLatch.countDown();
}
});
for (String symbol : new String[] {"ORCL", "TWTR", "QQQ", "SIRI", "ZNGA", "RAD"}) {
StockRequest request = StockRequest.newBuilder().setSymbol(symbol).build();
System.out.println("request=" + request);
requestSink.onValue(request);
}
requestSink.onCompleted();
completeLatch.await();
}
public static void main(String[] args) throws InterruptedException {
StockClient client = new StockClient();
try {
client.makeBlockingSimpleCall();
client.makeAsyncSimpleCall();
client.makeSequentialCalls();
client.makeAsyncCalls();
client.makeServerStreamingCall();
client.makeClientStreamingCall();
System.out.println("***All done");
} finally {
client.shutdown();
}
}
}

View File

@ -1,140 +0,0 @@
/*
* Copyright 2014, 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.
*/
package io.grpc.examples;
import io.grpc.examples.StockGrpc;
import io.grpc.examples.StockOuterClass.StockReply;
import io.grpc.examples.StockOuterClass.StockRequest;
import io.grpc.ServerImpl;
import io.grpc.stub.StreamObserver;
import io.grpc.transport.netty.NettyServerBuilder;
import java.util.Random;
/**
* A sample GRPC server that implements the Stock service.
*/
public class StockServer implements StockGrpc.Stock {
private final Random rand = new Random();
private float getStockPrice(String symbol) {
return rand.nextFloat() * 1000;
}
// Simple request-response RPC
@Override
public void getLastTradePrice(StockRequest request, StreamObserver<StockReply> responseObserver) {
String symbol = request.getSymbol();
float price = getStockPrice(symbol);
responseObserver.onValue(
StockReply.newBuilder().setSymbol(symbol).setPrice(price).build());
responseObserver.onCompleted();
}
// Bi-directional streaming
@Override
public StreamObserver<StockRequest> getLastTradePriceMultiple(
final StreamObserver<StockReply> responseObserver) {
return new StreamObserver<StockRequest>() {
@Override
public void onValue(StockRequest request) {
String symbol = request.getSymbol();
float price = getStockPrice(symbol);
responseObserver.onValue(
StockReply.newBuilder().setSymbol(symbol).setPrice(price).build());
}
@Override
public void onError(Throwable t) {
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
// Server streaming
@Override
public void watchFutureTrades(StockRequest request, StreamObserver<StockReply> responseObserver) {
String symbol = request.getSymbol();
for (int i = 0; i < request.getNumTradesToWatch(); i++) {
float price = getStockPrice(symbol);
responseObserver.onValue(
StockReply.newBuilder().setSymbol(symbol).setPrice(price).build());
}
responseObserver.onCompleted();
}
// Client streaming
@Override
public StreamObserver<StockRequest> getHighestTradePrice(
final StreamObserver<StockReply> responseObserver) {
return new StreamObserver<StockRequest>() {
String highestSymbol;
float highestPrice;
@Override
public void onValue(StockRequest request) {
String symbol = request.getSymbol();
float price = getStockPrice(symbol);
if (highestSymbol == null || price > highestPrice) {
highestPrice = price;
highestSymbol = symbol;
}
}
@Override
public void onError(Throwable t) {
}
@Override
public void onCompleted() {
if (highestSymbol != null) {
responseObserver.onValue(
StockReply.newBuilder().setSymbol(highestSymbol).setPrice(highestPrice).build());
}
responseObserver.onCompleted();
}
};
}
public static void main(String[] args) throws Exception {
ServerImpl server = NettyServerBuilder.forPort(8980)
.addService(StockGrpc.bindService(new StockServer()))
.build().start();
System.out.println("Server started");
}
}

View File

@ -1,52 +0,0 @@
syntax = "proto2";
package io.grpc.examples;
option java_package = "io.grpc.examples";
option java_outer_classname = "Math";
message DivArgs {
required int64 dividend = 1;
required int64 divisor = 2;
}
message DivReply {
required int64 quotient = 1;
required int64 remainder = 2;
}
message FibArgs {
optional int64 limit = 1;
}
message Num {
required int64 num = 1;
}
message FibReply {
required int64 count = 1;
}
service Calc {
// Div divides args.dividend by args.divisor and returns the quotient and
// remainder.
rpc Div (DivArgs) returns (DivReply) {
}
// DivMany accepts an arbitrary number of division args from the client stream
// and sends back the results in the reply stream. The stream continues until
// the client closes its end; the server does the same after sending all the
// replies. The stream ends immediately if either end aborts.
rpc DivMany (stream DivArgs) returns (stream DivReply) {
}
// Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib
// generates up to limit numbers; otherwise it continues until the call is
// canceled. Unlike Fib above, Fib has no final FibReply.
rpc Fib (FibArgs) returns (stream Num) {
}
// Sum sums a stream of numbers, returning the final result once the stream
// is closed.
rpc Sum (stream Num) returns (Num) {
}
}

View File

@ -0,0 +1,120 @@
// 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 examples;
// Interface exported by the server.
service RouteGuide {
// A simple RPC.
//
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
optional int32 latitude = 1;
optional int32 longitude = 2;
}
// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
// One corner of the rectangle.
optional Point lo = 1;
// The other corner of the rectangle.
optional Point hi = 2;
}
// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
optional string name = 1;
// The point where the feature is detected.
optional Point location = 2;
}
// A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
optional Point location = 1;
// The message to be sent.
optional string message = 2;
}
// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
optional int32 point_count = 1;
// The number of known features passed while traversing the route.
optional int32 feature_count = 2;
// The distance covered in metres.
optional int32 distance = 3;
// The duration of the traversal in seconds.
optional int32 elapsed_time = 4;
}

View File

@ -1,34 +0,0 @@
syntax = "proto2";
package io.grpc.examples;
option java_package = "io.grpc.examples";
// Protocol type definitions
message StockRequest {
optional string symbol = 1;
optional int32 num_trades_to_watch = 2 [default=0];
};
message StockReply {
optional float price = 1;
optional string symbol = 2;
};
// Interface exported by the server
service Stock {
// Simple blocking RPC
rpc GetLastTradePrice(StockRequest) returns (StockReply) {
};
// Bidirectional streaming RPC
rpc GetLastTradePriceMultiple(stream StockRequest) returns
(stream StockReply) {
};
// Unidirectional server-to-client streaming RPC
rpc WatchFutureTrades(StockRequest) returns (stream StockReply) {
};
// Unidirectional client-to-server streaming RPC
rpc GetHighestTradePrice(stream StockRequest) returns (StockReply) {
};
};

View File

@ -0,0 +1,601 @@
[{
"location": {
"latitude": 407838351,
"longitude": -746143763
},
"name": "Patriots Path, Mendham, NJ 07945, USA"
}, {
"location": {
"latitude": 408122808,
"longitude": -743999179
},
"name": "101 New Jersey 10, Whippany, NJ 07981, USA"
}, {
"location": {
"latitude": 413628156,
"longitude": -749015468
},
"name": "U.S. 6, Shohola, PA 18458, USA"
}, {
"location": {
"latitude": 419999544,
"longitude": -740371136
},
"name": "5 Conners Road, Kingston, NY 12401, USA"
}, {
"location": {
"latitude": 414008389,
"longitude": -743951297
},
"name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA"
}, {
"location": {
"latitude": 419611318,
"longitude": -746524769
},
"name": "287 Flugertown Road, Livingston Manor, NY 12758, USA"
}, {
"location": {
"latitude": 406109563,
"longitude": -742186778
},
"name": "4001 Tremley Point Road, Linden, NJ 07036, USA"
}, {
"location": {
"latitude": 416802456,
"longitude": -742370183
},
"name": "352 South Mountain Road, Wallkill, NY 12589, USA"
}, {
"location": {
"latitude": 412950425,
"longitude": -741077389
},
"name": "Bailey Turn Road, Harriman, NY 10926, USA"
}, {
"location": {
"latitude": 412144655,
"longitude": -743949739
},
"name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA"
}, {
"location": {
"latitude": 415736605,
"longitude": -742847522
},
"name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA"
}, {
"location": {
"latitude": 413843930,
"longitude": -740501726
},
"name": "162 Merrill Road, Highland Mills, NY 10930, USA"
}, {
"location": {
"latitude": 410873075,
"longitude": -744459023
},
"name": "Clinton Road, West Milford, NJ 07480, USA"
}, {
"location": {
"latitude": 412346009,
"longitude": -744026814
},
"name": "16 Old Brook Lane, Warwick, NY 10990, USA"
}, {
"location": {
"latitude": 402948455,
"longitude": -747903913
},
"name": "3 Drake Lane, Pennington, NJ 08534, USA"
}, {
"location": {
"latitude": 406337092,
"longitude": -740122226
},
"name": "6324 8th Avenue, Brooklyn, NY 11220, USA"
}, {
"location": {
"latitude": 406421967,
"longitude": -747727624
},
"name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA"
}, {
"location": {
"latitude": 416318082,
"longitude": -749677716
},
"name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA"
}, {
"location": {
"latitude": 415301720,
"longitude": -748416257
},
"name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA"
}, {
"location": {
"latitude": 402647019,
"longitude": -747071791
},
"name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA"
}, {
"location": {
"latitude": 412567807,
"longitude": -741058078
},
"name": "New York State Reference Route 987E, Southfields, NY 10975, USA"
}, {
"location": {
"latitude": 416855156,
"longitude": -744420597
},
"name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA"
}, {
"location": {
"latitude": 404663628,
"longitude": -744820157
},
"name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA"
}, {
"location": {
"latitude": 407113723,
"longitude": -749746483
},
"name": ""
}, {
"location": {
"latitude": 402133926,
"longitude": -743613249
},
"name": ""
}, {
"location": {
"latitude": 400273442,
"longitude": -741220915
},
"name": ""
}, {
"location": {
"latitude": 411236786,
"longitude": -744070769
},
"name": ""
}, {
"location": {
"latitude": 411633782,
"longitude": -746784970
},
"name": "211-225 Plains Road, Augusta, NJ 07822, USA"
}, {
"location": {
"latitude": 415830701,
"longitude": -742952812
},
"name": ""
}, {
"location": {
"latitude": 413447164,
"longitude": -748712898
},
"name": "165 Pedersen Ridge Road, Milford, PA 18337, USA"
}, {
"location": {
"latitude": 405047245,
"longitude": -749800722
},
"name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA"
}, {
"location": {
"latitude": 418858923,
"longitude": -746156790
},
"name": ""
}, {
"location": {
"latitude": 417951888,
"longitude": -748484944
},
"name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA"
}, {
"location": {
"latitude": 407033786,
"longitude": -743977337
},
"name": "26 East 3rd Street, New Providence, NJ 07974, USA"
}, {
"location": {
"latitude": 417548014,
"longitude": -740075041
},
"name": ""
}, {
"location": {
"latitude": 410395868,
"longitude": -744972325
},
"name": ""
}, {
"location": {
"latitude": 404615353,
"longitude": -745129803
},
"name": ""
}, {
"location": {
"latitude": 406589790,
"longitude": -743560121
},
"name": "611 Lawrence Avenue, Westfield, NJ 07090, USA"
}, {
"location": {
"latitude": 414653148,
"longitude": -740477477
},
"name": "18 Lannis Avenue, New Windsor, NY 12553, USA"
}, {
"location": {
"latitude": 405957808,
"longitude": -743255336
},
"name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA"
}, {
"location": {
"latitude": 411733589,
"longitude": -741648093
},
"name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA"
}, {
"location": {
"latitude": 412676291,
"longitude": -742606606
},
"name": "1270 Lakes Road, Monroe, NY 10950, USA"
}, {
"location": {
"latitude": 409224445,
"longitude": -748286738
},
"name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA"
}, {
"location": {
"latitude": 406523420,
"longitude": -742135517
},
"name": "652 Garden Street, Elizabeth, NJ 07202, USA"
}, {
"location": {
"latitude": 401827388,
"longitude": -740294537
},
"name": "349 Sea Spray Court, Neptune City, NJ 07753, USA"
}, {
"location": {
"latitude": 410564152,
"longitude": -743685054
},
"name": "13-17 Stanley Street, West Milford, NJ 07480, USA"
}, {
"location": {
"latitude": 408472324,
"longitude": -740726046
},
"name": "47 Industrial Avenue, Teterboro, NJ 07608, USA"
}, {
"location": {
"latitude": 412452168,
"longitude": -740214052
},
"name": "5 White Oak Lane, Stony Point, NY 10980, USA"
}, {
"location": {
"latitude": 409146138,
"longitude": -746188906
},
"name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA"
}, {
"location": {
"latitude": 404701380,
"longitude": -744781745
},
"name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA"
}, {
"location": {
"latitude": 409642566,
"longitude": -746017679
},
"name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA"
}, {
"location": {
"latitude": 408031728,
"longitude": -748645385
},
"name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA"
}, {
"location": {
"latitude": 413700272,
"longitude": -742135189
},
"name": "367 Prospect Road, Chester, NY 10918, USA"
}, {
"location": {
"latitude": 404310607,
"longitude": -740282632
},
"name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA"
}, {
"location": {
"latitude": 409319800,
"longitude": -746201391
},
"name": "11 Ward Street, Mount Arlington, NJ 07856, USA"
}, {
"location": {
"latitude": 406685311,
"longitude": -742108603
},
"name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA"
}, {
"location": {
"latitude": 419018117,
"longitude": -749142781
},
"name": "43 Dreher Road, Roscoe, NY 12776, USA"
}, {
"location": {
"latitude": 412856162,
"longitude": -745148837
},
"name": "Swan Street, Pine Island, NY 10969, USA"
}, {
"location": {
"latitude": 416560744,
"longitude": -746721964
},
"name": "66 Pleasantview Avenue, Monticello, NY 12701, USA"
}, {
"location": {
"latitude": 405314270,
"longitude": -749836354
},
"name": ""
}, {
"location": {
"latitude": 414219548,
"longitude": -743327440
},
"name": ""
}, {
"location": {
"latitude": 415534177,
"longitude": -742900616
},
"name": "565 Winding Hills Road, Montgomery, NY 12549, USA"
}, {
"location": {
"latitude": 406898530,
"longitude": -749127080
},
"name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA"
}, {
"location": {
"latitude": 407586880,
"longitude": -741670168
},
"name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA"
}, {
"location": {
"latitude": 400106455,
"longitude": -742870190
},
"name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA"
}, {
"location": {
"latitude": 400066188,
"longitude": -746793294
},
"name": ""
}, {
"location": {
"latitude": 418803880,
"longitude": -744102673
},
"name": "40 Mountain Road, Napanoch, NY 12458, USA"
}, {
"location": {
"latitude": 414204288,
"longitude": -747895140
},
"name": ""
}, {
"location": {
"latitude": 414777405,
"longitude": -740615601
},
"name": ""
}, {
"location": {
"latitude": 415464475,
"longitude": -747175374
},
"name": "48 North Road, Forestburgh, NY 12777, USA"
}, {
"location": {
"latitude": 404062378,
"longitude": -746376177
},
"name": ""
}, {
"location": {
"latitude": 405688272,
"longitude": -749285130
},
"name": ""
}, {
"location": {
"latitude": 400342070,
"longitude": -748788996
},
"name": ""
}, {
"location": {
"latitude": 401809022,
"longitude": -744157964
},
"name": ""
}, {
"location": {
"latitude": 404226644,
"longitude": -740517141
},
"name": "9 Thompson Avenue, Leonardo, NJ 07737, USA"
}, {
"location": {
"latitude": 410322033,
"longitude": -747871659
},
"name": ""
}, {
"location": {
"latitude": 407100674,
"longitude": -747742727
},
"name": ""
}, {
"location": {
"latitude": 418811433,
"longitude": -741718005
},
"name": "213 Bush Road, Stone Ridge, NY 12484, USA"
}, {
"location": {
"latitude": 415034302,
"longitude": -743850945
},
"name": ""
}, {
"location": {
"latitude": 411349992,
"longitude": -743694161
},
"name": ""
}, {
"location": {
"latitude": 404839914,
"longitude": -744759616
},
"name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA"
}, {
"location": {
"latitude": 414638017,
"longitude": -745957854
},
"name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA"
}, {
"location": {
"latitude": 412127800,
"longitude": -740173578
},
"name": ""
}, {
"location": {
"latitude": 401263460,
"longitude": -747964303
},
"name": ""
}, {
"location": {
"latitude": 412843391,
"longitude": -749086026
},
"name": ""
}, {
"location": {
"latitude": 418512773,
"longitude": -743067823
},
"name": ""
}, {
"location": {
"latitude": 404318328,
"longitude": -740835638
},
"name": "42-102 Main Street, Belford, NJ 07718, USA"
}, {
"location": {
"latitude": 419020746,
"longitude": -741172328
},
"name": ""
}, {
"location": {
"latitude": 404080723,
"longitude": -746119569
},
"name": ""
}, {
"location": {
"latitude": 401012643,
"longitude": -744035134
},
"name": ""
}, {
"location": {
"latitude": 404306372,
"longitude": -741079661
},
"name": ""
}, {
"location": {
"latitude": 403966326,
"longitude": -748519297
},
"name": ""
}, {
"location": {
"latitude": 405002031,
"longitude": -748407866
},
"name": ""
}, {
"location": {
"latitude": 409532885,
"longitude": -742200683
},
"name": ""
}, {
"location": {
"latitude": 416851321,
"longitude": -742674555
},
"name": ""
}, {
"location": {
"latitude": 406411633,
"longitude": -741722051
},
"name": "3387 Richmond Terrace, Staten Island, NY 10303, USA"
}, {
"location": {
"latitude": 413069058,
"longitude": -744597778
},
"name": "261 Van Sickle Road, Goshen, NY 10924, USA"
}, {
"location": {
"latitude": 418465462,
"longitude": -746859398
},
"name": ""
}, {
"location": {
"latitude": 411733222,
"longitude": -744228360
},
"name": ""
}, {
"location": {
"latitude": 410248224,
"longitude": -747127767
},
"name": "3 Hasta Way, Newton, NJ 07860, USA"
}]