Updated to work with new Java example location/build
This commit is contained in:
parent
c8809b1d25
commit
ff0591f8d5
195
README.md
195
README.md
|
|
@ -120,57 +120,30 @@ commands that you will need to use are:
|
||||||
- git checkout ... : check out a particular branch or a tagged version of
|
- git checkout ... : check out a particular branch or a tagged version of
|
||||||
the code to hack on
|
the code to hack on
|
||||||
|
|
||||||
|
#### Install gRPC
|
||||||
|
|
||||||
|
To build and install gRPC plugins and related tools:
|
||||||
|
- For Java, see the [Java quick start](https://github.com/grpc/grpc-java).
|
||||||
|
- For Go, see the [Go quick start](https://github.com/grpc/grpc-go).
|
||||||
|
|
||||||
#### Get the source code
|
#### Get the source code
|
||||||
|
|
||||||
The example code for this and our other examples lives in the `grpc-common`
|
The example code for our Java example lives in the `grpc-java`
|
||||||
GitHub repository. Clone this repository to your local machine by running the
|
GitHub repository. Clone this repository to your local machine by running the
|
||||||
following command:
|
following command:
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
git clone https://github.com/google/grpc-common.git
|
git clone https://github.com/google/grpc-java.git
|
||||||
```
|
```
|
||||||
|
|
||||||
Change your current directory to grpc-common/java
|
Change your current directory to grpc-java/examples
|
||||||
|
|
||||||
```
|
```
|
||||||
cd grpc-common/java
|
cd grpc-java/examples
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Install Java 8
|
|
||||||
|
|
||||||
Java gRPC is designed to work with both Java 7 and Java 8 - our example uses
|
|
||||||
Java 8. See
|
|
||||||
[Install Java
|
|
||||||
8](http://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html)
|
|
||||||
for instructions if you need to install Java 8.
|
|
||||||
|
|
||||||
#### Install Maven
|
|
||||||
|
|
||||||
To simplify building and managing gRPC's dependencies, the Java client
|
|
||||||
and server are structured as a standard
|
|
||||||
[Maven](http://maven.apache.org/guides/getting-started/)
|
|
||||||
project. See [Install Maven](http://maven.apache.org/users/index.html)
|
|
||||||
for instructions.
|
|
||||||
|
|
||||||
|
|
||||||
#### Install Go 1.4
|
|
||||||
|
|
||||||
Go gRPC requires Go 1.4, the latest version of Go. See
|
|
||||||
[Install Go](https://golang.org/doc/install) for instructions.
|
|
||||||
|
|
||||||
#### (optional) Install protoc
|
|
||||||
|
|
||||||
gRPC uses the latest version of the [protocol
|
|
||||||
buffer](https://developers.google.com/protocol-buffers/docs/overview)
|
|
||||||
compiler, protoc.
|
|
||||||
|
|
||||||
Having protoc installed isn't strictly necessary to follow along with this
|
|
||||||
example, as all the
|
|
||||||
generated code is checked into the Git repository. However, if you want
|
|
||||||
to experiment
|
|
||||||
with generating the code yourself, download and install protoc from its
|
|
||||||
[Git repo](https://github.com/google/protobuf)
|
|
||||||
|
|
||||||
<a name="servicedef"></a>
|
<a name="servicedef"></a>
|
||||||
### Defining a service
|
### Defining a service
|
||||||
|
|
@ -186,7 +159,7 @@ types as protocol buffer message types. Both the client and the
|
||||||
server use interface code generated from the service definition.
|
server use interface code generated from the service definition.
|
||||||
|
|
||||||
Here's our example service definition, defined using protocol buffers IDL in
|
Here's our example service definition, defined using protocol buffers IDL in
|
||||||
[helloworld.proto](protos/helloworld.proto). The `Greeting`
|
[helloworld.proto](https://github.com/grpc/grpc-java/tree/master/examples/src/main/proto). The `Greeting`
|
||||||
service has one method, `hello`, that lets the server receive a single
|
service has one method, `hello`, that lets the server receive a single
|
||||||
`HelloRequest`
|
`HelloRequest`
|
||||||
message from the remote client containing the user's name, then send back
|
message from the remote client containing the user's name, then send back
|
||||||
|
|
@ -196,7 +169,7 @@ can specify in gRPC - we'll look at some other types later in this document.
|
||||||
```
|
```
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
option java_package = "ex.grpc";
|
option java_package = "io.grpc.examples";
|
||||||
|
|
||||||
package helloworld;
|
package helloworld;
|
||||||
|
|
||||||
|
|
@ -229,39 +202,23 @@ in this example). The generated code contains both stub code for clients to
|
||||||
use and an abstract interface for servers to implement, both with the method
|
use and an abstract interface for servers to implement, both with the method
|
||||||
defined in our `Greeting` service.
|
defined in our `Greeting` service.
|
||||||
|
|
||||||
(If you didn't install `protoc` on your system and are working along with
|
(If you didn't install the gRPC plugins and protoc on your system and are working along with
|
||||||
the example, you can skip this step and move
|
the example, you can skip this step and move
|
||||||
onto the next one where we examine the generated code.)
|
onto the next one where we examine the generated code.)
|
||||||
|
|
||||||
As this is our first time using gRPC, we need to build the protobuf plugin
|
For simplicity, we've provided a [Gradle build file](https://github.com/grpc/grpc-java/blob/master/examples/build.gradle) with our Java examples that runs `protoc` for you with the appropriate plugin, input, and output:
|
||||||
that generates our RPC
|
|
||||||
classes. By default `protoc` just generates code for reading and writing
|
|
||||||
protocol buffers, so you need to use plugins to add additional features
|
|
||||||
to generated code. As we're creating Java code, we use the gRPC Java plugin.
|
|
||||||
|
|
||||||
To build the plugin, follow the instructions in the relevant repo: for Java,
|
```shell
|
||||||
the instructions are in [`grpc-java`](https://github.com/grpc/grpc-java).
|
../gradlew build
|
||||||
|
|
||||||
To use it to generate the code:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ mkdir -p src/main/java
|
|
||||||
$ protoc -I . helloworld.proto
|
|
||||||
--plugin=protoc-gen-grpc=external/grpc_java/bins/opt/java_plugin \
|
|
||||||
--grpc_out=src/main/java \
|
|
||||||
--java_out=src/main/java
|
|
||||||
```
|
```
|
||||||
|
|
||||||
[need to update this once I get the plugin built]
|
This generates the following classes from our .proto, which contain all the generated code
|
||||||
|
|
||||||
This generates the following classes, which contain all the generated code
|
|
||||||
we need to create our example:
|
we need to create our example:
|
||||||
|
|
||||||
- [`Helloworld.java`](java/src/main/java/ex/grpc/Helloworld.java), which
|
- `Helloworld.java`, which
|
||||||
has all the protocol buffer code to populate, serialize, and retrieve our
|
has all the protocol buffer code to populate, serialize, and retrieve our
|
||||||
`HelloRequest` and `HelloReply` message types
|
`HelloRequest` and `HelloReply` message types
|
||||||
- [`GreeterGrpc.java`](java/src/main/java/ex/grpc/GreeterGrpc.java),
|
- `GreeterGrpc.java`, which contains (along with some other useful code):
|
||||||
which contains (along with some other useful code):
|
|
||||||
- an interface for `Greeter` servers to implement
|
- an interface for `Greeter` servers to implement
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
@ -294,59 +251,67 @@ tutorial for your chosen language: check if there's one available yet in the rel
|
||||||
|
|
||||||
Our server application has two classes:
|
Our server application has two classes:
|
||||||
|
|
||||||
- a simple service implementation
|
- a main server class that hosts the service implementation and allows access over the
|
||||||
[GreeterImpl.java](java/src/main/java/ex/grpc/GreeterImpl.java).
|
network: [HelloWorldServer.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/HelloWorldServer.java).
|
||||||
|
|
||||||
|
|
||||||
|
- a simple service implementation class [GreeterImpl.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/HelloWorldServer.java#L51).
|
||||||
|
|
||||||
- a server that hosts the service implementation and allows access over the
|
|
||||||
network: [GreeterServer.java](java/src/main/java/ex/grpc/GreeterServer.java).
|
|
||||||
|
|
||||||
#### Service implementation
|
#### Service implementation
|
||||||
|
|
||||||
[GreeterImpl.java](java/src/main/java/ex/grpc/GreeterImpl.java)
|
[GreeterImpl.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/HelloWorldServer.java#L51)
|
||||||
actually implements our GreetingService's required behaviour.
|
actually implements our GreetingService's required behaviour.
|
||||||
|
|
||||||
As you can see, the class `GreeterImpl` implements the interface
|
As you can see, the class `GreeterImpl` implements the interface
|
||||||
`GreeterGrpc.Greeter` that we [generated](#generating) from our proto
|
`GreeterGrpc.Greeter` that we [generated](#generating) from our proto
|
||||||
[IDL](java/src/main/proto/helloworld.proto) by implementing the method `hello`:
|
[IDL](https://github.com/grpc/grpc-java/tree/master/examples/src/main/proto) by implementing the method `sayHello`:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public void hello(Helloworld.HelloRequest req,
|
@Override
|
||||||
StreamObserver<Helloworld.HelloReply> responseObserver) {
|
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
|
||||||
Helloworld.HelloReply reply =
|
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
|
||||||
Helloworld.HelloReply.newBuilder().setMessage(
|
responseObserver.onValue(reply);
|
||||||
"Hello " + req.getName()).build();
|
responseObserver.onCompleted();
|
||||||
responseObserver.onValue(reply);
|
}
|
||||||
responseObserver.onCompleted();
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
- `hello` takes two parameters:
|
- `hello` takes two parameters:
|
||||||
- `Helloworld.HelloRequest`: the request
|
- `HelloRequest`: the request
|
||||||
- `StreamObserver<Helloworld.HelloReply>`: a response observer, which is
|
- `StreamObserver<HelloReply>`: a response observer, which is
|
||||||
a special interface for the server to call with its response
|
a special interface for the server to call with its response
|
||||||
|
|
||||||
To return our response to the client and complete the call:
|
To return our response to the client and complete the call:
|
||||||
|
|
||||||
1. We construct and populate a `HelloReply` response object with our exciting
|
1. We construct and populate a `HelloReply` response object with our exciting
|
||||||
message, as specified in our interface definition.
|
message, as specified in our interface definition.
|
||||||
2. We use the`responseObserver` to return the `HelloReply` to the client
|
2. We return the `HelloReply` to the client and then specify that we've finished dealing with the RPC.
|
||||||
and then specify that we've finished dealing with the RPC
|
|
||||||
|
|
||||||
|
|
||||||
#### Server implementation
|
#### Server implementation
|
||||||
|
|
||||||
[GreeterServer.java](java/src/main/java/ex/grpc/GreeterServer.java)
|
[HelloWorldServer.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/HelloWorldServer.java)
|
||||||
shows the other main feature required to provide a gRPC service; making the service
|
shows the other main feature required to provide a gRPC service; making the service
|
||||||
implementation available from the network.
|
implementation available from the network.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
/* The port on which the server should run */
|
||||||
|
private int port = 50051;
|
||||||
private ServerImpl server;
|
private ServerImpl server;
|
||||||
...
|
|
||||||
private void start() throws Exception {
|
private void start() throws Exception {
|
||||||
server = NettyServerBuilder.forPort(port)
|
server = NettyServerBuilder.forPort(port)
|
||||||
.addService(GreeterGrpc.bindService(new GreeterImpl()))
|
.addService(GreeterGrpc.bindService(new GreeterImpl()))
|
||||||
.build();
|
.build().start();
|
||||||
server.startAsync();
|
logger.info("Server started, listening on " + port);
|
||||||
server.awaitRunning(5, TimeUnit.SECONDS);
|
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Use stderr here since the logger may has been reset by its JVM shutdown hook.
|
||||||
|
System.err.println("*** shutting down gRPC server since JVM is shutting down");
|
||||||
|
HelloWorldServer.this.stop();
|
||||||
|
System.err.println("*** server shut down");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -356,16 +321,6 @@ implementation that we created to a port. Then we start the server running: the
|
||||||
requests from `Greeter` service clients on our specified port. We'll cover
|
requests from `Greeter` service clients on our specified port. We'll cover
|
||||||
how all this works in a bit more detail in our language-specific documentation.
|
how all this works in a bit more detail in our language-specific documentation.
|
||||||
|
|
||||||
#### Build it
|
|
||||||
|
|
||||||
Once we've implemented everything, we use Maven to build the server:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ mvn package
|
|
||||||
```
|
|
||||||
|
|
||||||
We'll look at using a client to access the server in the next section.
|
|
||||||
|
|
||||||
<a name="client"></a>
|
<a name="client"></a>
|
||||||
### Writing a client
|
### Writing a client
|
||||||
|
|
||||||
|
|
@ -388,10 +343,10 @@ want to connect to. Then we use the channel to construct the stub instance.
|
||||||
private final ChannelImpl channel;
|
private final ChannelImpl channel;
|
||||||
private final GreeterGrpc.GreeterBlockingStub blockingStub;
|
private final GreeterGrpc.GreeterBlockingStub blockingStub;
|
||||||
|
|
||||||
public HelloClient(String host, int port) {
|
public HelloWorldClient(String host, int port) {
|
||||||
channel = NettyChannelBuilder.forAddress(host, port)
|
channel =
|
||||||
.negotiationType(NegotiationType.PLAINTEXT)
|
NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT)
|
||||||
.build();
|
.build();
|
||||||
blockingStub = GreeterGrpc.newBlockingStub(channel);
|
blockingStub = GreeterGrpc.newBlockingStub(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -408,49 +363,30 @@ Now we can contact the service and obtain a greeting:
|
||||||
|
|
||||||
1. We construct and fill in a `HelloRequest` to send to the service.
|
1. We construct and fill in a `HelloRequest` to send to the service.
|
||||||
2. We call the stub's `hello()` RPC with our request and get a `HelloReply`
|
2. We call the stub's `hello()` RPC with our request and get a `HelloReply`
|
||||||
back,
|
back, from which we can get our greeting.
|
||||||
from which we can get our greeting.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public void greet(String name) {
|
HelloRequest req = HelloRequest.newBuilder().setName(name).build();
|
||||||
logger.debug("Will try to greet " + name + " ...");
|
HelloReply reply = blockingStub.sayHello(req);
|
||||||
try {
|
|
||||||
Helloworld.HelloRequest request =
|
|
||||||
Helloworld.HelloRequest.newBuilder().setName(name).build();
|
|
||||||
Helloworld.HelloReply reply = blockingStub.SayHello(request);
|
|
||||||
logger.info("Greeting: " + reply.getMessage());
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
logger.log(Level.WARNING, "RPC failed", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Build the client
|
|
||||||
|
|
||||||
This is the same as building the server: our client and server are part of
|
|
||||||
the same maven package so the same command builds both.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ mvn package
|
|
||||||
```
|
|
||||||
|
|
||||||
<a name="run"></a>
|
<a name="run"></a>
|
||||||
### Try it out!
|
### Try it out!
|
||||||
|
|
||||||
We've added simple shell scripts to simplifying running the examples. Now
|
Our [Gradle build file](https://github.com/grpc/grpc-java/blob/master/examples/build.gradle) simplifies building and running the examples.
|
||||||
that they are built, you can run the server with:
|
|
||||||
|
You can build and run the server from the `grpc-java` root folder with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./run_greeter_server.sh
|
$ ./gradlew :grpc-examples:helloWorldServer
|
||||||
```
|
```
|
||||||
|
|
||||||
and in another terminal window confirm that it receives a message.
|
and in another terminal window confirm that it receives a message.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./run_greeter_client.sh
|
$ ./gradlew :grpc-examples:helloWorldClient
|
||||||
```
|
```
|
||||||
|
|
||||||
### Adding another client
|
### Adding another client
|
||||||
|
|
@ -461,11 +397,10 @@ generated from and implementing our `Greeter` service definition. However,
|
||||||
as you'll see if you look at the language-specific subdirectories
|
as you'll see if you look at the language-specific subdirectories
|
||||||
in this repository, we've also generated and implemented `Greeter`
|
in this repository, we've also generated and implemented `Greeter`
|
||||||
in some of gRPC's other supported languages. Each service
|
in some of gRPC's other supported languages. Each service
|
||||||
and client uses interface code generated from [exactly the same
|
and client uses interface code generated from the same proto
|
||||||
.proto](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto)
|
|
||||||
that we used for the Java example.
|
that we used for the Java example.
|
||||||
|
|
||||||
So, for example, if we visit the [`go`
|
So, for example, if we visit the [`go` example
|
||||||
directory](https://github.com/grpc/grpc-common/tree/master/go) and look at the
|
directory](https://github.com/grpc/grpc-common/tree/master/go) and look at the
|
||||||
[`greeter_client`](https://github.com/grpc/grpc-common/blob/master/go/greeter_client/main.go),
|
[`greeter_client`](https://github.com/grpc/grpc-common/blob/master/go/greeter_client/main.go),
|
||||||
we can see that like the Java client, it connects to a `Greeter` service
|
we can see that like the Java client, it connects to a `Greeter` service
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue