├── examples
├── settings.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── src
│ └── main
│ │ ├── proto
│ │ ├── helloworld.proto
│ │ ├── route_guide.proto
│ │ └── error_details.proto
│ │ ├── java
│ │ └── io
│ │ │ └── grpc
│ │ │ └── examples
│ │ │ ├── header
│ │ │ ├── HeaderServerInterceptor.java
│ │ │ ├── HeaderClientInterceptor.java
│ │ │ ├── CustomHeaderServer.java
│ │ │ └── CustomHeaderClient.java
│ │ │ └── helloworld
│ │ │ ├── HelloWorldServer.java
│ │ │ └── HelloWorldClient.java
│ │ └── resources
│ │ └── io
│ │ └── grpc
│ │ └── examples
│ │ └── routeguide
│ │ └── route_guide_db.json
├── gradlew.bat
├── pom.xml
├── build.gradle
└── gradlew
└── README.md
/examples/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'examples'
2 |
--------------------------------------------------------------------------------
/examples/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makdharma/grpc-zookeeper-lb/HEAD/examples/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/examples/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Apr 06 10:19:48 PDT 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # grpc-zookeeper-lb
2 | This is a toy example of using Zookeeper for load balancing with gRPC. To run:
3 | 1. Compile HelloWorldClient and HelloWorldServer.
4 |
5 | ```git clone https://github.com/makdharma/grpc-zookeeper-lb```
6 |
7 | ```cd grpc-zookeeper-lb/examples; ./gradelw installDist```
8 |
9 | 2. Download zookeeper stock docker image and start zookeeper.
10 |
11 | ```docker pull zookeeper```
12 |
13 | ```docker run -p 2181:2181 --restart always -d zookeeper```
14 |
15 | 3. Start couple of servers
16 |
17 | ```./build/install/examples/bin/hello-world-server 50000 zk://localhost:2181```
18 |
19 | ```./build/install/examples/bin/hello-world-server 50001 zk://localhost:2181```
20 |
21 | 4. Run hello-world-client. It should alternate between two servers.
22 |
23 | ```./build/install/examples/bin/hello-world-client zk://localhost:2181```
24 |
25 |
--------------------------------------------------------------------------------
/examples/src/main/proto/helloworld.proto:
--------------------------------------------------------------------------------
1 | // Copyright 2015, Google Inc.
2 | // All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the names of its
15 | // contributors may be used to endorse or promote products derived from
16 | // this software without specific prior written permission.
17 | //
18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 | syntax = "proto3";
31 |
32 | option java_multiple_files = true;
33 | option java_package = "io.grpc.examples.helloworld";
34 | option java_outer_classname = "HelloWorldProto";
35 | option objc_class_prefix = "HLW";
36 |
37 | package helloworld;
38 |
39 | // The greeting service definition.
40 | service Greeter {
41 | // Sends a greeting
42 | rpc SayHello (HelloRequest) returns (HelloReply) {}
43 | }
44 |
45 | // The request message containing the user's name.
46 | message HelloRequest {
47 | string name = 1;
48 | }
49 |
50 | // The response message containing the greetings
51 | message HelloReply {
52 | string message = 1;
53 | }
54 |
--------------------------------------------------------------------------------
/examples/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/examples/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | io.grpc
5 | examples
6 | jar
7 |
9 | 1.3.0
10 | examples
11 | http://maven.apache.org
12 |
13 | 1.3.0
14 |
15 |
16 |
17 | io.grpc
18 | grpc-netty
19 | ${grpc.version}
20 |
21 |
22 | io.grpc
23 | grpc-protobuf
24 | ${grpc.version}
25 |
26 |
27 | io.grpc
28 | grpc-stub
29 | ${grpc.version}
30 |
31 |
32 | junit
33 | junit
34 | 4.11
35 | test
36 |
37 |
38 | org.mockito
39 | mockito-core
40 | 1.9.5
41 | test
42 |
43 |
44 |
45 |
46 |
47 | kr.motd.maven
48 | os-maven-plugin
49 | 1.4.1.Final
50 |
51 |
52 |
53 |
54 | org.xolstice.maven.plugins
55 | protobuf-maven-plugin
56 | 0.5.0
57 |
58 | com.google.protobuf:protoc:3.2.0:exe:${os.detected.classifier}
59 | grpc-java
60 | io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
61 |
62 |
63 |
64 |
65 | compile
66 | compile-custom
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/examples/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'com.google.protobuf'
3 |
4 | buildscript {
5 | repositories {
6 | mavenCentral()
7 | }
8 | dependencies {
9 | // ASSUMES GRADLE 2.12 OR HIGHER. Use plugin version 0.7.5 with earlier
10 | // gradle versions
11 | classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
12 | }
13 | }
14 |
15 | repositories {
16 | mavenCentral()
17 | mavenLocal()
18 | }
19 |
20 | // IMPORTANT: You probably want the non-SNAPSHOT version of gRPC. Make sure you
21 | // are looking at a tagged version of the example and not "master"!
22 |
23 | // Feel free to delete the comment at the next line. It is just for safely
24 | // updating the version in our release process.
25 | def grpcVersion = '1.3.0' // CURRENT_GRPC_VERSION
26 |
27 | dependencies {
28 | compile "io.grpc:grpc-netty:${grpcVersion}"
29 | compile "io.grpc:grpc-protobuf:${grpcVersion}"
30 | compile "io.grpc:grpc-stub:${grpcVersion}"
31 | compile 'org.apache.zookeeper:zookeeper:3.4.8'
32 |
33 | testCompile "junit:junit:4.11"
34 | testCompile "org.mockito:mockito-core:1.9.5"
35 | }
36 |
37 | protobuf {
38 | protoc {
39 | artifact = 'com.google.protobuf:protoc:3.2.0'
40 | }
41 | plugins {
42 | grpc {
43 | artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
44 | }
45 | }
46 | generateProtoTasks {
47 | all()*.plugins {
48 | grpc {
49 | // To generate deprecated interfaces and static bindService method,
50 | // turn the enable_deprecated option to true below:
51 | option 'enable_deprecated=false'
52 | }
53 | }
54 | }
55 | }
56 |
57 | // Inform IntelliJ projects about the generated code.
58 | apply plugin: 'idea'
59 |
60 | idea {
61 | module {
62 | // Not using generatedSourceDirs because of
63 | // https://discuss.gradle.org/t/support-for-intellij-2016/15294/8
64 | sourceDirs += file("${projectDir}/build/generated/source/proto/main/java");
65 | sourceDirs += file("${projectDir}/build/generated/source/proto/main/grpc");
66 | }
67 | }
68 |
69 | // Provide convenience executables for trying out the examples.
70 | apply plugin: 'application'
71 |
72 | startScripts.enabled = false
73 |
74 | task helloWorldServer(type: CreateStartScripts) {
75 | mainClassName = 'io.grpc.examples.helloworld.HelloWorldServer'
76 | applicationName = 'hello-world-server'
77 | outputDir = new File(project.buildDir, 'tmp')
78 | classpath = jar.outputs.files + project.configurations.runtime
79 | }
80 |
81 | task helloWorldClient(type: CreateStartScripts) {
82 | mainClassName = 'io.grpc.examples.helloworld.HelloWorldClient'
83 | applicationName = 'hello-world-client'
84 | outputDir = new File(project.buildDir, 'tmp')
85 | classpath = jar.outputs.files + project.configurations.runtime
86 | }
87 |
88 | applicationDistribution.into('bin') {
89 | from(helloWorldServer)
90 | from(helloWorldClient)
91 | fileMode = 0755
92 | }
93 |
--------------------------------------------------------------------------------
/examples/src/main/java/io/grpc/examples/header/HeaderServerInterceptor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, Google Inc. All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are
6 | * met:
7 | *
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above
11 | * copyright notice, this list of conditions and the following disclaimer
12 | * in the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * * Neither the name of Google Inc. nor the names of its
16 | * contributors may be used to endorse or promote products derived from
17 | * this software without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | package io.grpc.examples.header;
33 |
34 | import com.google.common.annotations.VisibleForTesting;
35 | import io.grpc.ForwardingServerCall.SimpleForwardingServerCall;
36 | import io.grpc.Metadata;
37 | import io.grpc.ServerCall;
38 | import io.grpc.ServerCallHandler;
39 | import io.grpc.ServerInterceptor;
40 | import java.util.logging.Logger;
41 |
42 | /**
43 | * A interceptor to handle server header.
44 | */
45 | public class HeaderServerInterceptor implements ServerInterceptor {
46 |
47 | private static final Logger logger = Logger.getLogger(HeaderServerInterceptor.class.getName());
48 |
49 | @VisibleForTesting
50 | static final Metadata.Key CUSTOM_HEADER_KEY =
51 | Metadata.Key.of("custom_server_header_key", Metadata.ASCII_STRING_MARSHALLER);
52 |
53 |
54 | @Override
55 | public ServerCall.Listener interceptCall(
56 | ServerCall call,
57 | final Metadata requestHeaders,
58 | ServerCallHandler next) {
59 | logger.info("header received from client:" + requestHeaders);
60 | return next.startCall(new SimpleForwardingServerCall(call) {
61 | @Override
62 | public void sendHeaders(Metadata responseHeaders) {
63 | responseHeaders.put(CUSTOM_HEADER_KEY, "customRespondValue");
64 | super.sendHeaders(responseHeaders);
65 | }
66 | }, requestHeaders);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/examples/src/main/java/io/grpc/examples/header/HeaderClientInterceptor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, Google Inc. All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are
6 | * met:
7 | *
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above
11 | * copyright notice, this list of conditions and the following disclaimer
12 | * in the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * * Neither the name of Google Inc. nor the names of its
16 | * contributors may be used to endorse or promote products derived from
17 | * this software without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | package io.grpc.examples.header;
33 |
34 | import com.google.common.annotations.VisibleForTesting;
35 | import io.grpc.CallOptions;
36 | import io.grpc.Channel;
37 | import io.grpc.ClientCall;
38 | import io.grpc.ClientInterceptor;
39 | import io.grpc.ForwardingClientCall.SimpleForwardingClientCall;
40 | import io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener;
41 | import io.grpc.Metadata;
42 | import io.grpc.MethodDescriptor;
43 | import java.util.logging.Logger;
44 |
45 | /**
46 | * A interceptor to handle client header.
47 | */
48 | public class HeaderClientInterceptor implements ClientInterceptor {
49 |
50 | private static final Logger logger = Logger.getLogger(HeaderClientInterceptor.class.getName());
51 |
52 | @VisibleForTesting
53 | static final Metadata.Key CUSTOM_HEADER_KEY =
54 | Metadata.Key.of("custom_client_header_key", Metadata.ASCII_STRING_MARSHALLER);
55 |
56 | @Override
57 | public ClientCall interceptCall(MethodDescriptor method,
58 | CallOptions callOptions, Channel next) {
59 | return new SimpleForwardingClientCall(next.newCall(method, callOptions)) {
60 |
61 | @Override
62 | public void start(Listener responseListener, Metadata headers) {
63 | /* put custom header */
64 | headers.put(CUSTOM_HEADER_KEY, "customRequestValue");
65 | super.start(new SimpleForwardingClientCallListener(responseListener) {
66 | @Override
67 | public void onHeaders(Metadata headers) {
68 | /**
69 | * if you don't need receive header from server,
70 | * you can use {@link io.grpc.stub.MetadataUtils#attachHeaders}
71 | * directly to send header
72 | */
73 | logger.info("header received from server:" + headers);
74 | super.onHeaders(headers);
75 | }
76 | }, headers);
77 | }
78 | };
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/examples/src/main/java/io/grpc/examples/header/CustomHeaderServer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, Google Inc. All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are
6 | * met:
7 | *
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above
11 | * copyright notice, this list of conditions and the following disclaimer
12 | * in the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * * Neither the name of Google Inc. nor the names of its
16 | * contributors may be used to endorse or promote products derived from
17 | * this software without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | package io.grpc.examples.header;
33 |
34 | import io.grpc.Server;
35 | import io.grpc.ServerBuilder;
36 | import io.grpc.ServerInterceptors;
37 | import io.grpc.examples.helloworld.GreeterGrpc;
38 | import io.grpc.examples.helloworld.HelloReply;
39 | import io.grpc.examples.helloworld.HelloRequest;
40 | import io.grpc.stub.StreamObserver;
41 | import java.io.IOException;
42 | import java.util.logging.Logger;
43 |
44 | /**
45 | * A simple server that like {@link io.grpc.examples.helloworld.HelloWorldServer}.
46 | * You can get and response any header in {@link io.grpc.examples.header.HeaderServerInterceptor}.
47 | */
48 | public class CustomHeaderServer {
49 | private static final Logger logger = Logger.getLogger(CustomHeaderServer.class.getName());
50 |
51 | /* The port on which the server should run */
52 | private static final int port = 50051;
53 | private Server server;
54 |
55 | private void start() throws IOException {
56 | server = ServerBuilder.forPort(port)
57 | .addService(ServerInterceptors.intercept(new GreeterImpl(), new HeaderServerInterceptor()))
58 | .build()
59 | .start();
60 | logger.info("Server started, listening on " + port);
61 | Runtime.getRuntime().addShutdownHook(new Thread() {
62 | @Override
63 | public void run() {
64 | // Use stderr here since the logger may have been reset by its JVM shutdown hook.
65 | System.err.println("*** shutting down gRPC server since JVM is shutting down");
66 | CustomHeaderServer.this.stop();
67 | System.err.println("*** server shut down");
68 | }
69 | });
70 | }
71 |
72 | private void stop() {
73 | if (server != null) {
74 | server.shutdown();
75 | }
76 | }
77 |
78 | /**
79 | * Await termination on the main thread since the grpc library uses daemon threads.
80 | */
81 | private void blockUntilShutdown() throws InterruptedException {
82 | if (server != null) {
83 | server.awaitTermination();
84 | }
85 | }
86 |
87 | /**
88 | * Main launches the server from the command line.
89 | */
90 | public static void main(String[] args) throws IOException, InterruptedException {
91 | final CustomHeaderServer server = new CustomHeaderServer();
92 | server.start();
93 | server.blockUntilShutdown();
94 | }
95 |
96 | private static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
97 |
98 | @Override
99 | public void sayHello(HelloRequest req, StreamObserver responseObserver) {
100 | HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
101 | responseObserver.onNext(reply);
102 | responseObserver.onCompleted();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/examples/src/main/java/io/grpc/examples/header/CustomHeaderClient.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, Google Inc. All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are
6 | * met:
7 | *
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above
11 | * copyright notice, this list of conditions and the following disclaimer
12 | * in the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * * Neither the name of Google Inc. nor the names of its
16 | * contributors may be used to endorse or promote products derived from
17 | * this software without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | package io.grpc.examples.header;
33 |
34 | import io.grpc.Channel;
35 | import io.grpc.ClientInterceptor;
36 | import io.grpc.ClientInterceptors;
37 | import io.grpc.ManagedChannel;
38 | import io.grpc.ManagedChannelBuilder;
39 | import io.grpc.StatusRuntimeException;
40 | import io.grpc.examples.helloworld.GreeterGrpc;
41 | import io.grpc.examples.helloworld.HelloReply;
42 | import io.grpc.examples.helloworld.HelloRequest;
43 | import java.util.concurrent.TimeUnit;
44 | import java.util.logging.Level;
45 | import java.util.logging.Logger;
46 |
47 | /**
48 | * A simple client that like {@link io.grpc.examples.helloworld.HelloWorldClient}.
49 | * This client can help you create custom headers.
50 | */
51 | public class CustomHeaderClient {
52 | private static final Logger logger = Logger.getLogger(CustomHeaderClient.class.getName());
53 |
54 | private final ManagedChannel originChannel;
55 | private final GreeterGrpc.GreeterBlockingStub blockingStub;
56 |
57 | /**
58 | * A custom client.
59 | */
60 | private CustomHeaderClient(String host, int port) {
61 | originChannel = ManagedChannelBuilder.forAddress(host, port)
62 | .usePlaintext(true)
63 | .build();
64 | ClientInterceptor interceptor = new HeaderClientInterceptor();
65 | Channel channel = ClientInterceptors.intercept(originChannel, interceptor);
66 | blockingStub = GreeterGrpc.newBlockingStub(channel);
67 | }
68 |
69 | private void shutdown() throws InterruptedException {
70 | originChannel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
71 | }
72 |
73 | /**
74 | * A simple client method that like {@link io.grpc.examples.helloworld.HelloWorldClient}.
75 | */
76 | private void greet(String name) {
77 | logger.info("Will try to greet " + name + " ...");
78 | HelloRequest request = HelloRequest.newBuilder().setName(name).build();
79 | HelloReply response;
80 | try {
81 | response = blockingStub.sayHello(request);
82 | } catch (StatusRuntimeException e) {
83 | logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
84 | return;
85 | }
86 | logger.info("Greeting: " + response.getMessage());
87 | }
88 |
89 | /**
90 | * Main start the client from the command line.
91 | */
92 | public static void main(String[] args) throws Exception {
93 | CustomHeaderClient client = new CustomHeaderClient("localhost", 50051);
94 | try {
95 | /* Access a service running on the local machine on port 50051 */
96 | String user = "world";
97 | if (args.length > 0) {
98 | user = args[0]; /* Use the arg as the name to greet if provided */
99 | }
100 | client.greet(user);
101 | } finally {
102 | client.shutdown();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/examples/src/main/proto/route_guide.proto:
--------------------------------------------------------------------------------
1 | // Copyright 2015, Google Inc.
2 | // All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the names of its
15 | // contributors may be used to endorse or promote products derived from
16 | // this software without specific prior written permission.
17 | //
18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 | syntax = "proto3";
31 |
32 | option java_multiple_files = true;
33 | option java_package = "io.grpc.examples.routeguide";
34 | option java_outer_classname = "RouteGuideProto";
35 | option objc_class_prefix = "RTG";
36 |
37 | package routeguide;
38 |
39 | // Interface exported by the server.
40 | service RouteGuide {
41 | // A simple RPC.
42 | //
43 | // Obtains the feature at a given position.
44 | //
45 | // A feature with an empty name is returned if there's no feature at the given
46 | // position.
47 | rpc GetFeature(Point) returns (Feature) {}
48 |
49 | // A server-to-client streaming RPC.
50 | //
51 | // Obtains the Features available within the given Rectangle. Results are
52 | // streamed rather than returned at once (e.g. in a response message with a
53 | // repeated field), as the rectangle may cover a large area and contain a
54 | // huge number of features.
55 | rpc ListFeatures(Rectangle) returns (stream Feature) {}
56 |
57 | // A client-to-server streaming RPC.
58 | //
59 | // Accepts a stream of Points on a route being traversed, returning a
60 | // RouteSummary when traversal is completed.
61 | rpc RecordRoute(stream Point) returns (RouteSummary) {}
62 |
63 | // A Bidirectional streaming RPC.
64 | //
65 | // Accepts a stream of RouteNotes sent while a route is being traversed,
66 | // while receiving other RouteNotes (e.g. from other users).
67 | rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
68 | }
69 |
70 | // Points are represented as latitude-longitude pairs in the E7 representation
71 | // (degrees multiplied by 10**7 and rounded to the nearest integer).
72 | // Latitudes should be in the range +/- 90 degrees and longitude should be in
73 | // the range +/- 180 degrees (inclusive).
74 | message Point {
75 | int32 latitude = 1;
76 | int32 longitude = 2;
77 | }
78 |
79 | // A latitude-longitude rectangle, represented as two diagonally opposite
80 | // points "lo" and "hi".
81 | message Rectangle {
82 | // One corner of the rectangle.
83 | Point lo = 1;
84 |
85 | // The other corner of the rectangle.
86 | Point hi = 2;
87 | }
88 |
89 | // A feature names something at a given point.
90 | //
91 | // If a feature could not be named, the name is empty.
92 | message Feature {
93 | // The name of the feature.
94 | string name = 1;
95 |
96 | // The point where the feature is detected.
97 | Point location = 2;
98 | }
99 |
100 | // Not used in the RPC. Instead, this is here for the form serialized to disk.
101 | message FeatureDatabase {
102 | repeated Feature feature = 1;
103 | }
104 |
105 | // A RouteNote is a message sent while at a given point.
106 | message RouteNote {
107 | // The location from which the message is sent.
108 | Point location = 1;
109 |
110 | // The message to be sent.
111 | string message = 2;
112 | }
113 |
114 | // A RouteSummary is received in response to a RecordRoute rpc.
115 | //
116 | // It contains the number of individual points received, the number of
117 | // detected features, and the total distance covered as the cumulative sum of
118 | // the distance between each point.
119 | message RouteSummary {
120 | // The number of points received.
121 | int32 point_count = 1;
122 |
123 | // The number of known features passed while traversing the route.
124 | int32 feature_count = 2;
125 |
126 | // The distance covered in metres.
127 | int32 distance = 3;
128 |
129 | // The duration of the traversal in seconds.
130 | int32 elapsed_time = 4;
131 | }
132 |
--------------------------------------------------------------------------------
/examples/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn ( ) {
37 | echo "$*"
38 | }
39 |
40 | die ( ) {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save ( ) {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/examples/src/main/proto/error_details.proto:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | syntax = "proto3";
16 |
17 | package google.rpc;
18 |
19 | import "google/protobuf/duration.proto";
20 |
21 | option java_multiple_files = true;
22 | option java_outer_classname = "ErrorDetailsProto";
23 | option java_package = "com.google.rpc";
24 |
25 |
26 | // Describes when the clients can retry a failed request. Clients could ignore
27 | // the recommendation here or retry when this information is missing from error
28 | // responses.
29 | //
30 | // It's always recommended that clients should use exponential backoff when
31 | // retrying.
32 | //
33 | // Clients should wait until `retry_delay` amount of time has passed since
34 | // receiving the error response before retrying. If retrying requests also
35 | // fail, clients should use an exponential backoff scheme to gradually increase
36 | // the delay between retries based on `retry_delay`, until either a maximum
37 | // number of retires have been reached or a maximum retry delay cap has been
38 | // reached.
39 | message RetryInfo {
40 | // Clients should wait at least this long between retrying the same request.
41 | google.protobuf.Duration retry_delay = 1;
42 | }
43 |
44 | // Describes additional debugging info.
45 | message DebugInfo {
46 | // The stack trace entries indicating where the error occurred.
47 | repeated string stack_entries = 1;
48 |
49 | // Additional debugging information provided by the server.
50 | string detail = 2;
51 | }
52 |
53 | // Describes how a quota check failed.
54 | //
55 | // For example if a daily limit was exceeded for the calling project,
56 | // a service could respond with a QuotaFailure detail containing the project
57 | // id and the description of the quota limit that was exceeded. If the
58 | // calling project hasn't enabled the service in the developer console, then
59 | // a service could respond with the project id and set `service_disabled`
60 | // to true.
61 | //
62 | // Also see RetryDetail and Help types for other details about handling a
63 | // quota failure.
64 | message QuotaFailure {
65 | // A message type used to describe a single quota violation. For example, a
66 | // daily quota or a custom quota that was exceeded.
67 | message Violation {
68 | // The subject on which the quota check failed.
69 | // For example, "clientip:" or "project:".
71 | string subject = 1;
72 |
73 | // A description of how the quota check failed. Clients can use this
74 | // description to find more about the quota configuration in the service's
75 | // public documentation, or find the relevant quota limit to adjust through
76 | // developer console.
77 | //
78 | // For example: "Service disabled" or "Daily Limit for read operations
79 | // exceeded".
80 | string description = 2;
81 | }
82 |
83 | // Describes all quota violations.
84 | repeated Violation violations = 1;
85 | }
86 |
87 | // Describes violations in a client request. This error type focuses on the
88 | // syntactic aspects of the request.
89 | message BadRequest {
90 | // A message type used to describe a single bad request field.
91 | message FieldViolation {
92 | // A path leading to a field in the request body. The value will be a
93 | // sequence of dot-separated identifiers that identify a protocol buffer
94 | // field. E.g., "violations.field" would identify this field.
95 | string field = 1;
96 |
97 | // A description of why the request element is bad.
98 | string description = 2;
99 | }
100 |
101 | // Describes all violations in a client request.
102 | repeated FieldViolation field_violations = 1;
103 | }
104 |
105 | // Contains metadata about the request that clients can attach when filing a bug
106 | // or providing other forms of feedback.
107 | message RequestInfo {
108 | // An opaque string that should only be interpreted by the service generating
109 | // it. For example, it can be used to identify requests in the service's logs.
110 | string request_id = 1;
111 |
112 | // Any data that was used to serve this request. For example, an encrypted
113 | // stack trace that can be sent back to the service provider for debugging.
114 | string serving_data = 2;
115 | }
116 |
117 | // Describes the resource that is being accessed.
118 | message ResourceInfo {
119 | // A name for the type of resource being accessed, e.g. "sql table",
120 | // "cloud storage bucket", "file", "Google calendar"; or the type URL
121 | // of the resource: e.g. "type.googleapis.com/google.pubsub.v1.Topic".
122 | string resource_type = 1;
123 |
124 | // The name of the resource being accessed. For example, a shared calendar
125 | // name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current
126 | // error is [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED].
127 | string resource_name = 2;
128 |
129 | // The owner of the resource (optional).
130 | // For example, "user:" or "project:".
132 | string owner = 3;
133 |
134 | // Describes what error is encountered when accessing this resource.
135 | // For example, updating a cloud project may require the `writer` permission
136 | // on the developer console project.
137 | string description = 4;
138 | }
139 |
140 | // Provides links to documentation or for performing an out of band action.
141 | //
142 | // For example, if a quota check failed with an error indicating the calling
143 | // project hasn't enabled the accessed service, this can contain a URL pointing
144 | // directly to the right place in the developer console to flip the bit.
145 | message Help {
146 | // Describes a URL link.
147 | message Link {
148 | // Describes what the link offers.
149 | string description = 1;
150 |
151 | // The URL of the link.
152 | string url = 2;
153 | }
154 |
155 | // URL(s) pointing to additional information on handling the current error.
156 | repeated Link links = 1;
157 | }
--------------------------------------------------------------------------------
/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, Google Inc. All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are
6 | * met:
7 | *
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above
11 | * copyright notice, this list of conditions and the following disclaimer
12 | * in the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * * Neither the name of Google Inc. nor the names of its
16 | * contributors may be used to endorse or promote products derived from
17 | * this software without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | package io.grpc.examples.helloworld;
33 |
34 | import io.grpc.Server;
35 | import io.grpc.ServerBuilder;
36 | import io.grpc.stub.StreamObserver;
37 | import java.io.IOException;
38 | import java.io.IOException;
39 | import java.net.URI;
40 | import java.util.concurrent.CountDownLatch;
41 | import java.util.Date;
42 | import java.util.logging.Logger;
43 | import java.text.SimpleDateFormat;
44 | import org.apache.zookeeper.AsyncCallback.StatCallback;
45 | import org.apache.zookeeper.CreateMode;
46 | import org.apache.zookeeper.data.Stat;
47 | import org.apache.zookeeper.KeeperException;
48 | import org.apache.zookeeper.KeeperException.Code;
49 | import org.apache.zookeeper.WatchedEvent;
50 | import org.apache.zookeeper.Watcher;
51 | import org.apache.zookeeper.Watcher.Event.KeeperState;
52 | import org.apache.zookeeper.ZooDefs;
53 | import org.apache.zookeeper.ZooKeeper;
54 |
55 | class ZookeeperConnection {
56 | private static final Logger logger = Logger.getLogger("ZooKeeper");
57 | private ZooKeeper zoo;
58 | public void ZookeeperConnection() {
59 | }
60 |
61 | /**
62 | * Connects to a zookeeper ensemble in zkUriStr.
63 | * serverIp and portStr are the IP/Port of this server.
64 | */
65 | public boolean connect(String zkUriStr, String serverIp, String portStr)
66 | throws IOException,InterruptedException {
67 | final CountDownLatch connectedSignal = new CountDownLatch(1);
68 | String zkhostport;
69 | try {
70 | URI zkUri = new URI(zkUriStr);
71 | zkhostport = zkUri.getHost().toString() + ":" + Integer.toString(zkUri.getPort());
72 | } catch (Exception e) {
73 | logger.severe("Could not parse zk URI " + zkUriStr);
74 | return false;
75 | }
76 |
77 | zoo = new ZooKeeper(zkhostport, 5000, new Watcher() {
78 | public void process(WatchedEvent we) {
79 | if (we.getState() == KeeperState.SyncConnected) {
80 | connectedSignal.countDown();
81 | }
82 | }
83 | });
84 | /* Wait for zookeeper connection */
85 | connectedSignal.await();
86 |
87 | String path = "/grpc_hello_world_service";
88 | Stat stat;
89 | String currTime = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date());
90 | try {
91 | stat = zoo.exists(path, true);
92 | if (stat == null) {
93 | zoo.create(path, currTime.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
94 | }
95 | } catch (Exception e) {
96 | logger.severe("Failed to create path");
97 | return false;
98 | }
99 |
100 | String server_addr = path + "/" + serverIp + ":" + portStr;
101 | try {
102 | stat = zoo.exists(server_addr, true);
103 | if (stat == null) {
104 | try {
105 | zoo.create(server_addr, currTime.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
106 | } catch (Exception e) {
107 | logger.severe("Failed to create server_data");
108 | return false;
109 | }
110 | } else {
111 | try {
112 | zoo.setData(server_addr, currTime.getBytes(), stat.getVersion());
113 | } catch (Exception e) {
114 | logger.severe("Failed to update server_data");
115 | return false;
116 | }
117 | }
118 | } catch (Exception e) {
119 | logger.severe("Failed to add server_data");
120 | return false;
121 | }
122 | return true;
123 | }
124 |
125 | // Method to disconnect from zookeeper server
126 | public void close() throws InterruptedException {
127 | zoo.close();
128 | }
129 | }
130 |
131 | /**
132 | * Server that manages startup/shutdown of a {@code Greeter} server.
133 | */
134 | public class HelloWorldServer {
135 | static String portStr;
136 | private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName());
137 |
138 | private Server server;
139 |
140 | private void start(String port) throws IOException {
141 | /* The port on which the server should run */
142 | server = ServerBuilder.forPort(Integer.parseInt(port))
143 | .addService(new GreeterImpl())
144 | .build()
145 | .start();
146 | logger.info("Server started, listening on " + port);
147 | Runtime.getRuntime().addShutdownHook(new Thread() {
148 | @Override
149 | public void run() {
150 | // Use stderr here since the logger may have been reset by its JVM shutdown hook.
151 | System.err.println("*** shutting down gRPC server since JVM is shutting down");
152 | HelloWorldServer.this.stop();
153 | System.err.println("*** server shut down");
154 | }
155 | });
156 | }
157 |
158 | private void stop() {
159 | if (server != null) {
160 | server.shutdown();
161 | }
162 | }
163 |
164 | /**
165 | * Await termination on the main thread since the grpc library uses daemon threads.
166 | */
167 | private void blockUntilShutdown() throws InterruptedException {
168 | if (server != null) {
169 | server.awaitTermination();
170 | }
171 | }
172 |
173 |
174 | /**
175 | * Main launches the server from the command line.
176 | */
177 | public static void main(String[] args) throws IOException, InterruptedException {
178 | /* Argument parsing */
179 | if (args.length != 2) {
180 | System.out.println("Usage: helloworld_server PORT zk://ADDR:PORT");
181 | return;
182 | }
183 |
184 | String zk_addr;
185 |
186 | try {
187 | portStr = new String(args[0]);
188 | zk_addr = new String(args[1]);
189 | } catch (Exception e) {
190 | System.out.println("Usage: helloworld_server PORT zk://ADDR:PORT");
191 | return;
192 | }
193 |
194 | ZookeeperConnection zk_conn = new ZookeeperConnection();
195 | if (!zk_conn.connect(zk_addr, "localhost", portStr)) {
196 | return;
197 | }
198 |
199 | final HelloWorldServer server = new HelloWorldServer();
200 | server.start(portStr);
201 | server.blockUntilShutdown();
202 | }
203 |
204 | static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
205 |
206 | @Override
207 | public void sayHello(HelloRequest req,
208 | StreamObserverresponseObserver) {
209 | HelloReply reply = HelloReply.newBuilder().setMessage(
210 | "Hello " + req.getName() + " from " + portStr).build();
211 | responseObserver.onNext(reply);
212 | responseObserver.onCompleted();
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, Google Inc. All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are
6 | * met:
7 | *
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above
11 | * copyright notice, this list of conditions and the following disclaimer
12 | * in the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * * Neither the name of Google Inc. nor the names of its
16 | * contributors may be used to endorse or promote products derived from
17 | * this software without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | package io.grpc.examples.helloworld;
33 |
34 | import io.grpc.Attributes;
35 | import io.grpc.EquivalentAddressGroup;
36 | import io.grpc.ManagedChannel;
37 | import io.grpc.ManagedChannelBuilder;
38 | import io.grpc.NameResolver;
39 | import io.grpc.NameResolverProvider;
40 | import io.grpc.StatusRuntimeException;
41 | import io.grpc.util.RoundRobinLoadBalancerFactory;
42 | import java.net.InetSocketAddress;
43 | import java.net.SocketAddress;
44 | import java.net.URI;
45 | import java.util.concurrent.CountDownLatch;
46 | import java.util.concurrent.TimeUnit;
47 | import java.util.logging.Level;
48 | import java.util.logging.Logger;
49 | import java.util.Comparator;
50 | import java.util.List;
51 | import java.util.ArrayList;
52 | import javax.annotation.Nullable;
53 | import org.apache.zookeeper.AsyncCallback.StatCallback;
54 | import org.apache.zookeeper.CreateMode;
55 | import org.apache.zookeeper.data.Stat;
56 | import org.apache.zookeeper.KeeperException;
57 | import org.apache.zookeeper.KeeperException.Code;
58 | import org.apache.zookeeper.Watcher;
59 | import org.apache.zookeeper.Watcher.Event.KeeperState;
60 | import org.apache.zookeeper.WatchedEvent;
61 | import org.apache.zookeeper.ZooDefs;
62 | import org.apache.zookeeper.ZooKeeper;
63 |
64 |
65 | class ZkNameResolver extends NameResolver implements Watcher {
66 | /** Hard-coded path to the ZkNode that knows about servers.
67 | * Note this must match with the path used by HelloWorldServer */
68 | public static final String PATH = "/grpc_hello_world_service";
69 | /** 2 seconds to indicate that client disconnected */
70 | public static final int TIMEOUT_MS = 2000;
71 |
72 | private URI zkUri;
73 | private ZooKeeper zoo;
74 | private Listener listener;
75 | private final Logger logger = Logger.getLogger("ZK");
76 |
77 | /**
78 | * The callback from Zookeeper when servers are added/removed.
79 | */
80 | @Override
81 | public void process(WatchedEvent we) {
82 | if (we.getType() == Event.EventType.None) {
83 | logger.info("Connection expired");
84 | } else {
85 | try {
86 | List servers = zoo.getChildren(PATH, false);
87 | AddServersToListener(servers);
88 | zoo.getChildren(PATH, this);
89 | } catch(Exception ex) {
90 | logger.info(ex.getMessage());
91 | }
92 | }
93 | }
94 |
95 | private void AddServersToListener(List servers) {
96 | List addrs = new ArrayList();
97 | logger.info("Updating server list");
98 | for (String child : servers) {
99 | try {
100 | logger.info("Online: " + child);
101 | URI uri = new URI("dummy://" + child);
102 | // Convert "host:port" into host and port
103 | String host = uri.getHost();
104 | int port = uri.getPort();
105 | List sockaddrs_list= new ArrayList();
106 | sockaddrs_list.add(new InetSocketAddress(host, port));
107 | addrs.add(new EquivalentAddressGroup(sockaddrs_list));
108 | } catch(Exception ex) {
109 | logger.info("Unparsable server address: " + child);
110 | logger.info(ex.getMessage());
111 | }
112 | }
113 | if (addrs.size() > 0) {
114 | listener.onAddresses(addrs, Attributes.EMPTY);
115 | } else {
116 | logger.info("No servers online. Keep looking");
117 | }
118 | }
119 |
120 |
121 | public ZkNameResolver (URI zkUri) {
122 | this.zkUri = zkUri;
123 | }
124 |
125 | @Override
126 | public String getServiceAuthority() {
127 | return zkUri.getAuthority();
128 | }
129 |
130 | @Override
131 | public void start(Listener listener) {
132 | this.listener = listener;
133 | final CountDownLatch connectedSignal = new CountDownLatch(1);
134 | try {
135 | String zkaddr = zkUri.getHost().toString() + ":" + Integer.toString(zkUri.getPort());
136 | logger.info("Connecting to Zookeeper Address " + zkaddr);
137 |
138 | this.zoo = new ZooKeeper(zkaddr, TIMEOUT_MS, new Watcher() {
139 | public void process(WatchedEvent we) {
140 | if (we.getState() == KeeperState.SyncConnected) {
141 | connectedSignal.countDown();
142 | }
143 | }
144 | });
145 | connectedSignal.await();
146 | logger.info("Connected!");
147 | } catch (Exception e) {
148 | logger.info("Failed to connect");
149 | return;
150 | }
151 |
152 |
153 | try {
154 | Stat stat = zoo.exists(PATH, true);
155 | if (stat == null) {
156 | logger.info("PATH does not exist.");
157 | } else {
158 | logger.info("PATH exists");
159 | }
160 | } catch (Exception e) {
161 | logger.info("Failed to get stat");
162 | return;
163 | }
164 |
165 | try {
166 | final CountDownLatch connectedSignal1 = new CountDownLatch(1);
167 | List servers = zoo.getChildren(PATH, this);
168 | AddServersToListener(servers);
169 | } catch(Exception e) {
170 | logger.info(e.getMessage());
171 | }
172 | }
173 |
174 | @Override
175 | public void shutdown() {
176 | }
177 | }
178 |
179 | class ZkNameResolverProvider extends NameResolverProvider {
180 | @Nullable
181 | @Override
182 | public NameResolver newNameResolver(URI targetUri, Attributes params) {
183 | return new ZkNameResolver(targetUri);
184 | }
185 |
186 | @Override
187 | protected int priority() {
188 | return 5;
189 | }
190 |
191 | @Override
192 | protected boolean isAvailable() {
193 | return true;
194 | }
195 |
196 | @Override
197 | public String getDefaultScheme() {
198 | return "zk";
199 | }
200 | }
201 |
202 | /**
203 | * A simple client that requests a greeting from the {@link HelloWorldServer},
204 | * and round robin load-balances among all available servers.
205 | */
206 | public class HelloWorldClient {
207 | private static final Logger logger = Logger.getLogger("Client");
208 |
209 | private final ManagedChannel channel;
210 | private final GreeterGrpc.GreeterBlockingStub blockingStub;
211 |
212 | /**
213 | * Construct client connecting to HelloWorld server using Zookeeper name resolver
214 | * and Round Robin load balancer.
215 | */
216 | public HelloWorldClient(String zkAddr) {
217 | this(ManagedChannelBuilder.forTarget(zkAddr)
218 | .loadBalancerFactory(RoundRobinLoadBalancerFactory.getInstance())
219 | .nameResolverFactory(new ZkNameResolverProvider())
220 | .usePlaintext(true));
221 | }
222 |
223 | /** Construct client for accessing the server using the existing channel. */
224 | HelloWorldClient(ManagedChannelBuilder> channelBuilder) {
225 | channel = channelBuilder.build();
226 | blockingStub = GreeterGrpc.newBlockingStub(channel);
227 | }
228 |
229 | public void shutdown() throws InterruptedException {
230 | channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
231 | }
232 |
233 | /** Say hello to server. */
234 | public void greet() {
235 | HelloRequest request = HelloRequest.newBuilder().setName("world").build();
236 | HelloReply response;
237 | try {
238 | response = blockingStub.sayHello(request);
239 | } catch (StatusRuntimeException e) {
240 | logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
241 | return;
242 | }
243 | logger.info("Greeting: " + response.getMessage());
244 | }
245 |
246 | /**
247 | * Greeter client. First argument of {@code args} is the address of the
248 | * Zookeeper ensemble. The client keeps making simple RPCs until interrupted
249 | * with a Ctrl-C.
250 | */
251 | public static void main(String[] args) throws Exception {
252 | if (args.length != 1) {
253 | System.out.println("Usage: helloworld_client zk://ADDR:PORT");
254 | return;
255 | }
256 | HelloWorldClient client = new HelloWorldClient(args[0]);
257 | try {
258 | while(true) {
259 | client.greet();
260 | Thread.sleep(1000);
261 | }
262 | } finally {
263 | client.shutdown();
264 | }
265 | }
266 | }
267 |
--------------------------------------------------------------------------------
/examples/src/main/resources/io/grpc/examples/routeguide/route_guide_db.json:
--------------------------------------------------------------------------------
1 | {
2 | "feature": [{
3 | "location": {
4 | "latitude": 407838351,
5 | "longitude": -746143763
6 | },
7 | "name": "Patriots Path, Mendham, NJ 07945, USA"
8 | }, {
9 | "location": {
10 | "latitude": 408122808,
11 | "longitude": -743999179
12 | },
13 | "name": "101 New Jersey 10, Whippany, NJ 07981, USA"
14 | }, {
15 | "location": {
16 | "latitude": 413628156,
17 | "longitude": -749015468
18 | },
19 | "name": "U.S. 6, Shohola, PA 18458, USA"
20 | }, {
21 | "location": {
22 | "latitude": 419999544,
23 | "longitude": -740371136
24 | },
25 | "name": "5 Conners Road, Kingston, NY 12401, USA"
26 | }, {
27 | "location": {
28 | "latitude": 414008389,
29 | "longitude": -743951297
30 | },
31 | "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA"
32 | }, {
33 | "location": {
34 | "latitude": 419611318,
35 | "longitude": -746524769
36 | },
37 | "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA"
38 | }, {
39 | "location": {
40 | "latitude": 406109563,
41 | "longitude": -742186778
42 | },
43 | "name": "4001 Tremley Point Road, Linden, NJ 07036, USA"
44 | }, {
45 | "location": {
46 | "latitude": 416802456,
47 | "longitude": -742370183
48 | },
49 | "name": "352 South Mountain Road, Wallkill, NY 12589, USA"
50 | }, {
51 | "location": {
52 | "latitude": 412950425,
53 | "longitude": -741077389
54 | },
55 | "name": "Bailey Turn Road, Harriman, NY 10926, USA"
56 | }, {
57 | "location": {
58 | "latitude": 412144655,
59 | "longitude": -743949739
60 | },
61 | "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA"
62 | }, {
63 | "location": {
64 | "latitude": 415736605,
65 | "longitude": -742847522
66 | },
67 | "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA"
68 | }, {
69 | "location": {
70 | "latitude": 413843930,
71 | "longitude": -740501726
72 | },
73 | "name": "162 Merrill Road, Highland Mills, NY 10930, USA"
74 | }, {
75 | "location": {
76 | "latitude": 410873075,
77 | "longitude": -744459023
78 | },
79 | "name": "Clinton Road, West Milford, NJ 07480, USA"
80 | }, {
81 | "location": {
82 | "latitude": 412346009,
83 | "longitude": -744026814
84 | },
85 | "name": "16 Old Brook Lane, Warwick, NY 10990, USA"
86 | }, {
87 | "location": {
88 | "latitude": 402948455,
89 | "longitude": -747903913
90 | },
91 | "name": "3 Drake Lane, Pennington, NJ 08534, USA"
92 | }, {
93 | "location": {
94 | "latitude": 406337092,
95 | "longitude": -740122226
96 | },
97 | "name": "6324 8th Avenue, Brooklyn, NY 11220, USA"
98 | }, {
99 | "location": {
100 | "latitude": 406421967,
101 | "longitude": -747727624
102 | },
103 | "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA"
104 | }, {
105 | "location": {
106 | "latitude": 416318082,
107 | "longitude": -749677716
108 | },
109 | "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA"
110 | }, {
111 | "location": {
112 | "latitude": 415301720,
113 | "longitude": -748416257
114 | },
115 | "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA"
116 | }, {
117 | "location": {
118 | "latitude": 402647019,
119 | "longitude": -747071791
120 | },
121 | "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA"
122 | }, {
123 | "location": {
124 | "latitude": 412567807,
125 | "longitude": -741058078
126 | },
127 | "name": "New York State Reference Route 987E, Southfields, NY 10975, USA"
128 | }, {
129 | "location": {
130 | "latitude": 416855156,
131 | "longitude": -744420597
132 | },
133 | "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA"
134 | }, {
135 | "location": {
136 | "latitude": 404663628,
137 | "longitude": -744820157
138 | },
139 | "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA"
140 | }, {
141 | "location": {
142 | "latitude": 407113723,
143 | "longitude": -749746483
144 | },
145 | "name": ""
146 | }, {
147 | "location": {
148 | "latitude": 402133926,
149 | "longitude": -743613249
150 | },
151 | "name": ""
152 | }, {
153 | "location": {
154 | "latitude": 400273442,
155 | "longitude": -741220915
156 | },
157 | "name": ""
158 | }, {
159 | "location": {
160 | "latitude": 411236786,
161 | "longitude": -744070769
162 | },
163 | "name": ""
164 | }, {
165 | "location": {
166 | "latitude": 411633782,
167 | "longitude": -746784970
168 | },
169 | "name": "211-225 Plains Road, Augusta, NJ 07822, USA"
170 | }, {
171 | "location": {
172 | "latitude": 415830701,
173 | "longitude": -742952812
174 | },
175 | "name": ""
176 | }, {
177 | "location": {
178 | "latitude": 413447164,
179 | "longitude": -748712898
180 | },
181 | "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA"
182 | }, {
183 | "location": {
184 | "latitude": 405047245,
185 | "longitude": -749800722
186 | },
187 | "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA"
188 | }, {
189 | "location": {
190 | "latitude": 418858923,
191 | "longitude": -746156790
192 | },
193 | "name": ""
194 | }, {
195 | "location": {
196 | "latitude": 417951888,
197 | "longitude": -748484944
198 | },
199 | "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA"
200 | }, {
201 | "location": {
202 | "latitude": 407033786,
203 | "longitude": -743977337
204 | },
205 | "name": "26 East 3rd Street, New Providence, NJ 07974, USA"
206 | }, {
207 | "location": {
208 | "latitude": 417548014,
209 | "longitude": -740075041
210 | },
211 | "name": ""
212 | }, {
213 | "location": {
214 | "latitude": 410395868,
215 | "longitude": -744972325
216 | },
217 | "name": ""
218 | }, {
219 | "location": {
220 | "latitude": 404615353,
221 | "longitude": -745129803
222 | },
223 | "name": ""
224 | }, {
225 | "location": {
226 | "latitude": 406589790,
227 | "longitude": -743560121
228 | },
229 | "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA"
230 | }, {
231 | "location": {
232 | "latitude": 414653148,
233 | "longitude": -740477477
234 | },
235 | "name": "18 Lannis Avenue, New Windsor, NY 12553, USA"
236 | }, {
237 | "location": {
238 | "latitude": 405957808,
239 | "longitude": -743255336
240 | },
241 | "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA"
242 | }, {
243 | "location": {
244 | "latitude": 411733589,
245 | "longitude": -741648093
246 | },
247 | "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA"
248 | }, {
249 | "location": {
250 | "latitude": 412676291,
251 | "longitude": -742606606
252 | },
253 | "name": "1270 Lakes Road, Monroe, NY 10950, USA"
254 | }, {
255 | "location": {
256 | "latitude": 409224445,
257 | "longitude": -748286738
258 | },
259 | "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA"
260 | }, {
261 | "location": {
262 | "latitude": 406523420,
263 | "longitude": -742135517
264 | },
265 | "name": "652 Garden Street, Elizabeth, NJ 07202, USA"
266 | }, {
267 | "location": {
268 | "latitude": 401827388,
269 | "longitude": -740294537
270 | },
271 | "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA"
272 | }, {
273 | "location": {
274 | "latitude": 410564152,
275 | "longitude": -743685054
276 | },
277 | "name": "13-17 Stanley Street, West Milford, NJ 07480, USA"
278 | }, {
279 | "location": {
280 | "latitude": 408472324,
281 | "longitude": -740726046
282 | },
283 | "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA"
284 | }, {
285 | "location": {
286 | "latitude": 412452168,
287 | "longitude": -740214052
288 | },
289 | "name": "5 White Oak Lane, Stony Point, NY 10980, USA"
290 | }, {
291 | "location": {
292 | "latitude": 409146138,
293 | "longitude": -746188906
294 | },
295 | "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA"
296 | }, {
297 | "location": {
298 | "latitude": 404701380,
299 | "longitude": -744781745
300 | },
301 | "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA"
302 | }, {
303 | "location": {
304 | "latitude": 409642566,
305 | "longitude": -746017679
306 | },
307 | "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA"
308 | }, {
309 | "location": {
310 | "latitude": 408031728,
311 | "longitude": -748645385
312 | },
313 | "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA"
314 | }, {
315 | "location": {
316 | "latitude": 413700272,
317 | "longitude": -742135189
318 | },
319 | "name": "367 Prospect Road, Chester, NY 10918, USA"
320 | }, {
321 | "location": {
322 | "latitude": 404310607,
323 | "longitude": -740282632
324 | },
325 | "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA"
326 | }, {
327 | "location": {
328 | "latitude": 409319800,
329 | "longitude": -746201391
330 | },
331 | "name": "11 Ward Street, Mount Arlington, NJ 07856, USA"
332 | }, {
333 | "location": {
334 | "latitude": 406685311,
335 | "longitude": -742108603
336 | },
337 | "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA"
338 | }, {
339 | "location": {
340 | "latitude": 419018117,
341 | "longitude": -749142781
342 | },
343 | "name": "43 Dreher Road, Roscoe, NY 12776, USA"
344 | }, {
345 | "location": {
346 | "latitude": 412856162,
347 | "longitude": -745148837
348 | },
349 | "name": "Swan Street, Pine Island, NY 10969, USA"
350 | }, {
351 | "location": {
352 | "latitude": 416560744,
353 | "longitude": -746721964
354 | },
355 | "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA"
356 | }, {
357 | "location": {
358 | "latitude": 405314270,
359 | "longitude": -749836354
360 | },
361 | "name": ""
362 | }, {
363 | "location": {
364 | "latitude": 414219548,
365 | "longitude": -743327440
366 | },
367 | "name": ""
368 | }, {
369 | "location": {
370 | "latitude": 415534177,
371 | "longitude": -742900616
372 | },
373 | "name": "565 Winding Hills Road, Montgomery, NY 12549, USA"
374 | }, {
375 | "location": {
376 | "latitude": 406898530,
377 | "longitude": -749127080
378 | },
379 | "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA"
380 | }, {
381 | "location": {
382 | "latitude": 407586880,
383 | "longitude": -741670168
384 | },
385 | "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA"
386 | }, {
387 | "location": {
388 | "latitude": 400106455,
389 | "longitude": -742870190
390 | },
391 | "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA"
392 | }, {
393 | "location": {
394 | "latitude": 400066188,
395 | "longitude": -746793294
396 | },
397 | "name": ""
398 | }, {
399 | "location": {
400 | "latitude": 418803880,
401 | "longitude": -744102673
402 | },
403 | "name": "40 Mountain Road, Napanoch, NY 12458, USA"
404 | }, {
405 | "location": {
406 | "latitude": 414204288,
407 | "longitude": -747895140
408 | },
409 | "name": ""
410 | }, {
411 | "location": {
412 | "latitude": 414777405,
413 | "longitude": -740615601
414 | },
415 | "name": ""
416 | }, {
417 | "location": {
418 | "latitude": 415464475,
419 | "longitude": -747175374
420 | },
421 | "name": "48 North Road, Forestburgh, NY 12777, USA"
422 | }, {
423 | "location": {
424 | "latitude": 404062378,
425 | "longitude": -746376177
426 | },
427 | "name": ""
428 | }, {
429 | "location": {
430 | "latitude": 405688272,
431 | "longitude": -749285130
432 | },
433 | "name": ""
434 | }, {
435 | "location": {
436 | "latitude": 400342070,
437 | "longitude": -748788996
438 | },
439 | "name": ""
440 | }, {
441 | "location": {
442 | "latitude": 401809022,
443 | "longitude": -744157964
444 | },
445 | "name": ""
446 | }, {
447 | "location": {
448 | "latitude": 404226644,
449 | "longitude": -740517141
450 | },
451 | "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA"
452 | }, {
453 | "location": {
454 | "latitude": 410322033,
455 | "longitude": -747871659
456 | },
457 | "name": ""
458 | }, {
459 | "location": {
460 | "latitude": 407100674,
461 | "longitude": -747742727
462 | },
463 | "name": ""
464 | }, {
465 | "location": {
466 | "latitude": 418811433,
467 | "longitude": -741718005
468 | },
469 | "name": "213 Bush Road, Stone Ridge, NY 12484, USA"
470 | }, {
471 | "location": {
472 | "latitude": 415034302,
473 | "longitude": -743850945
474 | },
475 | "name": ""
476 | }, {
477 | "location": {
478 | "latitude": 411349992,
479 | "longitude": -743694161
480 | },
481 | "name": ""
482 | }, {
483 | "location": {
484 | "latitude": 404839914,
485 | "longitude": -744759616
486 | },
487 | "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA"
488 | }, {
489 | "location": {
490 | "latitude": 414638017,
491 | "longitude": -745957854
492 | },
493 | "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA"
494 | }, {
495 | "location": {
496 | "latitude": 412127800,
497 | "longitude": -740173578
498 | },
499 | "name": ""
500 | }, {
501 | "location": {
502 | "latitude": 401263460,
503 | "longitude": -747964303
504 | },
505 | "name": ""
506 | }, {
507 | "location": {
508 | "latitude": 412843391,
509 | "longitude": -749086026
510 | },
511 | "name": ""
512 | }, {
513 | "location": {
514 | "latitude": 418512773,
515 | "longitude": -743067823
516 | },
517 | "name": ""
518 | }, {
519 | "location": {
520 | "latitude": 404318328,
521 | "longitude": -740835638
522 | },
523 | "name": "42-102 Main Street, Belford, NJ 07718, USA"
524 | }, {
525 | "location": {
526 | "latitude": 419020746,
527 | "longitude": -741172328
528 | },
529 | "name": ""
530 | }, {
531 | "location": {
532 | "latitude": 404080723,
533 | "longitude": -746119569
534 | },
535 | "name": ""
536 | }, {
537 | "location": {
538 | "latitude": 401012643,
539 | "longitude": -744035134
540 | },
541 | "name": ""
542 | }, {
543 | "location": {
544 | "latitude": 404306372,
545 | "longitude": -741079661
546 | },
547 | "name": ""
548 | }, {
549 | "location": {
550 | "latitude": 403966326,
551 | "longitude": -748519297
552 | },
553 | "name": ""
554 | }, {
555 | "location": {
556 | "latitude": 405002031,
557 | "longitude": -748407866
558 | },
559 | "name": ""
560 | }, {
561 | "location": {
562 | "latitude": 409532885,
563 | "longitude": -742200683
564 | },
565 | "name": ""
566 | }, {
567 | "location": {
568 | "latitude": 416851321,
569 | "longitude": -742674555
570 | },
571 | "name": ""
572 | }, {
573 | "location": {
574 | "latitude": 406411633,
575 | "longitude": -741722051
576 | },
577 | "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA"
578 | }, {
579 | "location": {
580 | "latitude": 413069058,
581 | "longitude": -744597778
582 | },
583 | "name": "261 Van Sickle Road, Goshen, NY 10924, USA"
584 | }, {
585 | "location": {
586 | "latitude": 418465462,
587 | "longitude": -746859398
588 | },
589 | "name": ""
590 | }, {
591 | "location": {
592 | "latitude": 411733222,
593 | "longitude": -744228360
594 | },
595 | "name": ""
596 | }, {
597 | "location": {
598 | "latitude": 410248224,
599 | "longitude": -747127767
600 | },
601 | "name": "3 Hasta Way, Newton, NJ 07860, USA"
602 | }]
603 | }
604 |
--------------------------------------------------------------------------------