From 9436767d209030024f205920a9035facc6158342 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Tue, 24 Feb 2015 07:42:14 -0800 Subject: [PATCH 01/17] rename the gem to reflect the fact that it contains two samples --- ruby/{greeter.gemspec => grpc-demo.gemspec} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename ruby/{greeter.gemspec => grpc-demo.gemspec} (82%) diff --git a/ruby/greeter.gemspec b/ruby/grpc-demo.gemspec similarity index 82% rename from ruby/greeter.gemspec rename to ruby/grpc-demo.gemspec index 795c84c0f5f..d4e2ec7a266 100644 --- a/ruby/greeter.gemspec +++ b/ruby/grpc-demo.gemspec @@ -2,7 +2,7 @@ # encoding: utf-8 Gem::Specification.new do |s| - s.name = 'grpc-greeter' + s.name = 'grpc-demo' s.version = '0.1.0' s.authors = ['gRPC Authors'] s.email = 'temiola@google.com' @@ -11,7 +11,7 @@ Gem::Specification.new do |s| s.description = 'Simple demo of using gRPC from Ruby' s.files = `git ls-files -- ruby/*`.split("\n") - s.executables = `git ls-files -- ruby/greeter*.rb`.split("\n").map do |f| + s.executables = `git ls-files -- ruby/*client.rb ruby/*server.rb`.split("\n").map do |f| File.basename(f) end s.require_paths = ['lib'] From 2cf333c197a3d1e9f3a1d62273a2be45888d95d4 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Tue, 24 Feb 2015 07:43:10 -0800 Subject: [PATCH 02/17] Adds the generated code for the route_guide example --- ruby/lib/route_guide.rb | 37 ++++++++++++++++++++++++++++++++ ruby/lib/route_guide_services.rb | 27 +++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 ruby/lib/route_guide.rb create mode 100644 ruby/lib/route_guide_services.rb diff --git a/ruby/lib/route_guide.rb b/ruby/lib/route_guide.rb new file mode 100644 index 00000000000..98bac8395ce --- /dev/null +++ b/ruby/lib/route_guide.rb @@ -0,0 +1,37 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: route_guide.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_message "examples.Point" do + optional :latitude, :int32, 1 + optional :longitude, :int32, 2 + end + add_message "examples.Rectangle" do + optional :lo, :message, 1, "examples.Point" + optional :hi, :message, 2, "examples.Point" + end + add_message "examples.Feature" do + optional :name, :string, 1 + optional :location, :message, 2, "examples.Point" + end + add_message "examples.RouteNote" do + optional :location, :message, 1, "examples.Point" + optional :message, :string, 2 + end + add_message "examples.RouteSummary" do + optional :point_count, :int32, 1 + optional :feature_count, :int32, 2 + optional :distance, :int32, 3 + optional :elapsed_time, :int32, 4 + end +end + +module Examples + Point = Google::Protobuf::DescriptorPool.generated_pool.lookup("examples.Point").msgclass + Rectangle = Google::Protobuf::DescriptorPool.generated_pool.lookup("examples.Rectangle").msgclass + Feature = Google::Protobuf::DescriptorPool.generated_pool.lookup("examples.Feature").msgclass + RouteNote = Google::Protobuf::DescriptorPool.generated_pool.lookup("examples.RouteNote").msgclass + RouteSummary = Google::Protobuf::DescriptorPool.generated_pool.lookup("examples.RouteSummary").msgclass +end diff --git a/ruby/lib/route_guide_services.rb b/ruby/lib/route_guide_services.rb new file mode 100644 index 00000000000..6e07653c425 --- /dev/null +++ b/ruby/lib/route_guide_services.rb @@ -0,0 +1,27 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# Source: route_guide.proto for package 'examples' + +require 'grpc' +require 'route_guide' + +module Examples + module RouteGuide + + # TODO: add proto service documentation here + class Service + + include GRPC::GenericService + + self.marshal_class_method = :encode + self.unmarshal_class_method = :decode + self.service_name = 'examples.RouteGuide' + + rpc :GetFeature, Point, Feature + rpc :ListFeatures, Rectangle, stream(Feature) + rpc :RecordRoute, stream(Point), RouteSummary + rpc :RouteChat, stream(RouteNote), stream(RouteNote) + end + + Stub = Service.rpc_stub_class + end +end From 2e24c588caf9d297c045f10c607901cd1500d4af Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Thu, 26 Feb 2015 01:25:16 -0800 Subject: [PATCH 03/17] Adds a route_guide client and server --- ruby/route_guide/route_guide_client.rb | 166 +++++++++++++++++++ ruby/route_guide/route_guide_server.rb | 211 +++++++++++++++++++++++++ 2 files changed, 377 insertions(+) create mode 100755 ruby/route_guide/route_guide_client.rb create mode 100755 ruby/route_guide/route_guide_server.rb diff --git a/ruby/route_guide/route_guide_client.rb b/ruby/route_guide/route_guide_client.rb new file mode 100755 index 00000000000..640654c80a3 --- /dev/null +++ b/ruby/route_guide/route_guide_client.rb @@ -0,0 +1,166 @@ +#!/usr/bin/env ruby + +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Sample app that connects to a Route Guide service. +# +# Usage: $ path/to/route_guide_client.rb path/to/route_guide_db.json & + +this_dir = File.expand_path(File.dirname(__FILE__)) +lib_dir = File.join(File.dirname(this_dir), 'lib') +$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) + +require 'grpc' +require 'route_guide_services' + +include Examples + +GET_FEATURE_POINTS = [ + Point.new(latitude: 409_146_138, longitude: -746_188_906), + Point.new(latitude: 0, longitude: 0) +] + +# runs a GetFeature rpc. +# +# - once with a point known to be present in the sample route database +# - once with a point that is not in the sample database +def run_get_feature(stub) + p 'GetFeature' + p '----------' + GET_FEATURE_POINTS.each do |pt| + resp = stub.get_feature(pt) + if resp.name != '' + p "- found '#{resp.name}' at #{pt.inspect}" + else + p "- found nothing at #{pt.inspect}" + end + end +end + +LIST_FEATURES_RECT = Rectangle.new( + lo: Point.new(latitude: 400_000_000, longitude: -750_000_000), + hi: Point.new(latitude: 420_000_000, longitude: -730_000_000)) + +# runs a ListFeatures rpc. +# +# - the rectangle to chosen to include most of the known features +# in the sample db. +def run_list_features(stub) + p 'ListFeatures' + p '------------' + resps = stub.list_features(LIST_FEATURES_RECT) + resps.each do |r| + p "- found '#{r.name}' at #{r.location.inspect}" + end +end + +# RandomRoute provides an Enumerable that yields a random 'route' of points +# from a list of Features. +class RandomRoute + def initialize(features, size) + @features = features + @size = size + end + + # yields a point, waiting between 0 and 1 seconds between each yield + # + # @return an Enumerable that yields a random point + def each + return enum_for(:each) unless block_given? + @size.times do + json_feature = @features[rand(0..@features.length)] + next if json_feature.nil? + location = json_feature['location'] + pt = Point.new( + Hash[location.each_pair.map { |k, v| [k.to_sym, v] }]) + p "- next point is #{pt.inspect}" + yield pt + sleep(rand(0..1)) + end + end +end + +# runs a RecordRoute rpc. +# +# - the rectangle to chosen to include most of the known features +# in the sample db. +def run_record_route(stub, features) + p 'RecordRoute' + p '-----------' + points_on_route = 10 # arbitrary + deadline = points_on_route # as delay b/w each is max 1 second + reqs = RandomRoute.new(features, points_on_route) + resp = stub.record_route(reqs.each, deadline) + p "summary: #{resp.inspect}" +end + +ROUTE_CHAT_NOTES = [ + RouteNote.new(message: 'doh - a deer', + location: Point.new(latitude: 0, longitude: 0)), + RouteNote.new(message: 'ray - a drop of golden sun', + location: Point.new(latitude: 0, longitude: 1)), + RouteNote.new(message: 'me - the name I call myself', + location: Point.new(latitude: 1, longitude: 0)), + RouteNote.new(message: 'fa - a longer way to run', + location: Point.new(latitude: 1, longitude: 1)), + RouteNote.new(message: 'soh - with needle and a thread', + location: Point.new(latitude: 0, longitude: 1)) +] + +# runs a RouteChat rpc. +# +# sends a canned set of route notes and prints out the responses. +def run_route_chat(stub) + p 'Route Chat' + p '----------' + # TODO: decouple sending and receiving, i.e have the response enumerator run + # on its own thread. + resps = stub.route_chat(ROUTE_CHAT_NOTES) + resps.each { |r| p "received #{r.inspect}" } +end + +def main + stub = RouteGuide::Stub.new('localhost:50051') + run_get_feature(stub) + run_list_features(stub) + run_route_chat(stub) + if ARGV.length == 0 + p 'no feature database; skipping record_route and route_chat' + exit + end + + raw_data = [] + File.open(ARGV[0]) do |f| + raw_data = MultiJson.load(f.read) + end + run_record_route(stub, raw_data) +end + +main diff --git a/ruby/route_guide/route_guide_server.rb b/ruby/route_guide/route_guide_server.rb new file mode 100755 index 00000000000..8f12ba250d3 --- /dev/null +++ b/ruby/route_guide/route_guide_server.rb @@ -0,0 +1,211 @@ +#!/usr/bin/env ruby +# -*- coding: utf-8 -*- + +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Sample app that connects to a Route Guide service. +# +# Usage: $ path/to/route_guide_server.rb path/to/route_guide_db.json & + +this_dir = File.expand_path(File.dirname(__FILE__)) +lib_dir = File.join(File.dirname(this_dir), 'lib') +$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) + +require 'grpc' +require 'multi_json' +require 'route_guide_services' + +include Examples +COORD_FACTOR = 1e7 +RADIUS = 637_100 + +# Determines the distance between two points. +def calculate_distance(point_a, point_b) + to_radians = proc { |x| x * Math::PI / 180 } + lat_a = point_a.latitude / COORD_FACTOR + lat_b = point_b.latitude / COORD_FACTOR + long_a = point_a.longitude / COORD_FACTOR + long_b = point_b.longitude / COORD_FACTOR + φ1 = to_radians.call(lat_a) + φ2 = to_radians.call(lat_b) + Δφ = to_radians.call(lat_a - lat_b) + Δλ = to_radians.call(long_a - long_b) + a = Math.sin(Δφ / 2)**2 + + Math.cos(φ1) * Math.cos(φ2) + + Math.sin(Δλ / 2)**2 + (2 * RADIUS * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))).to_i +end + +# RectangleEnum provides an Enumerator of the points in a feature_db within a +# given Rectangle. +class RectangleEnum + # @param [Hash] feature_db + # @param [Rectangle] bounds + def initialize(feature_db, bounds) + @feature_db = feature_db + @bounds = bounds + lats = [@bounds.lo.latitude, @bounds.hi.latitude] + longs = [@bounds.lo.longitude, @bounds.hi.longitude] + @lo_lat, @hi_lat = lats.min, lats.max + @lo_long, @hi_long = longs.min, longs.max + end + + # in? determines if location lies within the bounds of this instances + # Rectangle. + def in?(location) + location['longitude'] >= @lo_long && + location['longitude'] <= @hi_long && + location['latitude'] >= @lo_lat && + location['latitude'] <= @hi_lat + end + + # each yields the features in the instances feature_db that lie within the + # instance rectangle. + def each + return enum_for(:each) unless block_given? + @feature_db.each_pair do |location, name| + next unless in?(location) + next if name.nil? || name == '' + pt = Point.new( + Hash[location.each_pair.map { |k, v| [k.to_sym, v] }]) + yield Feature.new(location: pt, name: name) + end + end +end + +# A EnumeratorQueue wraps a Queue to yield the items added to it. +class EnumeratorQueue + extend Forwardable + def_delegators :@q, :push + + def initialize(sentinel) + @q = Queue.new + @sentinel = sentinel + @received_notes = {} + end + + def each_item + return enum_for(:each_item) unless block_given? + loop do + r = @q.pop + break if r.equal?(@sentinel) + fail r if r.is_a? Exception + yield r + end + end +end + +# ServerImpl provides an implementation of the RouteGuide service. +class ServerImpl < RouteGuide::Service + # @param [Hash] feature_db {location => name} + def initialize(feature_db) + @feature_db = feature_db + @received_notes = Hash.new { |h, k| h[k] = [] } + end + + def get_feature(point, _call) + name = @feature_db[{ + 'longitude' => point.longitude, + 'latitude' => point.latitude }] || '' + Feature.new(location: point, name: name) + end + + def list_features(rectangle, _call) + RectangleEnum.new(@feature_db, rectangle).each + end + + def record_route(call) + started, elapsed_time = 0, 0 + distance, count, features, last = 0, 0, 0, nil + call.each_remote_read do |point| + count += 1 + name = @feature_db[{ + 'longitude' => point.longitude, + 'latitude' => point.latitude }] || '' + features += 1 unless name == '' + if last.nil? + last = point + started = Time.now.to_i + next + end + elapsed_time = Time.now.to_i - started + distance += calculate_distance(point, last) + last = point + end + RouteSummary.new(point_count: count, + feature_count: features, + distance: distance, + elapsed_time: elapsed_time) + end + + def route_chat(notes) + q = EnumeratorQueue.new(self) + # run a separate thread that processes the incoming requests + t = Thread.new do + begin + notes.each do |n| + key = { + 'latitude' => n.location.latitude, + 'longitude' => n.location.longitude + } + earlier_msgs = @received_notes[key] + @received_notes[key] << n.message + # send back the earlier messages at this point + earlier_msgs.each do |r| + q.push(RouteNote.new(location: n.location, message: r)) + end + end + q.push(self) # signal completion + rescue StandardError => e + q.push(e) # signal completion via an error + end + end + q.each_item + end +end + +def main + if ARGV.length == 0 + fail 'Please specify the path to the route_guide json database' + end + raw_data = [] + File.open(ARGV[0]) do |f| + raw_data = MultiJson.load(f.read) + end + feature_db = Hash[raw_data.map { |x| [x['location'], x['name']] }] + port = '0.0.0.0:50051' + s = GRPC::RpcServer.new + s.add_http2_port(port) + logger.info("... running insecurely on #{port}") + s.handle(ServerImpl.new(feature_db)) + s.run +end + +main From ad8891c2c65ec944afb1c63c0080b5ec1dbec248 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Thu, 26 Feb 2015 01:25:56 -0800 Subject: [PATCH 04/17] Updates the gemspec to treat the route_guide client and server as binaries --- ruby/grpc-demo.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/grpc-demo.gemspec b/ruby/grpc-demo.gemspec index d4e2ec7a266..8a8c4b35eec 100644 --- a/ruby/grpc-demo.gemspec +++ b/ruby/grpc-demo.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |s| s.description = 'Simple demo of using gRPC from Ruby' s.files = `git ls-files -- ruby/*`.split("\n") - s.executables = `git ls-files -- ruby/*client.rb ruby/*server.rb`.split("\n").map do |f| + s.executables = `git ls-files -- ruby/greeter*.rb ruby/route_guide/*.rb`.split("\n").map do |f| File.basename(f) end s.require_paths = ['lib'] From 704f53ac69b4021db275630c765dd93db9895238 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Thu, 26 Feb 2015 01:29:03 -0800 Subject: [PATCH 05/17] Fixed a messages --- ruby/route_guide/route_guide_client.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ruby/route_guide/route_guide_client.rb b/ruby/route_guide/route_guide_client.rb index 640654c80a3..181623a68ac 100755 --- a/ruby/route_guide/route_guide_client.rb +++ b/ruby/route_guide/route_guide_client.rb @@ -152,10 +152,9 @@ def main run_list_features(stub) run_route_chat(stub) if ARGV.length == 0 - p 'no feature database; skipping record_route and route_chat' + p 'no feature database; skipping record_route' exit end - raw_data = [] File.open(ARGV[0]) do |f| raw_data = MultiJson.load(f.read) From c66fe1ec5bf8330c767e18187e9f78a1402dce95 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Thu, 26 Feb 2015 03:53:16 -0800 Subject: [PATCH 06/17] Adds a route_guide tutorial --- ruby/README.md | 5 + ruby/route_guide/README.md | 286 +++++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 ruby/route_guide/README.md diff --git a/ruby/README.md b/ruby/README.md index c5902a3039b..8bdf4d93a2e 100644 --- a/ruby/README.md +++ b/ruby/README.md @@ -47,3 +47,8 @@ $ bundle exec ./greeter_server.rb & $ # from this directory $ bundle exec ./greeter_client.rb ``` + +Tutorial +-------- + +You can find a more detailed tutorial in [gRPC Basics: Ruby](https://github.com/grpc/grpc-common/blob/master/ruby/route_guide/README.md) diff --git a/ruby/route_guide/README.md b/ruby/route_guide/README.md new file mode 100644 index 00000000000..736a3809904 --- /dev/null +++ b/ruby/route_guide/README.md @@ -0,0 +1,286 @@ +#gRPC Basics: Ruby + +This tutorial provides a basic Ruby programmer's introduction to working with gRPC. By walking through this example you'll learn how to: + +- Define a service in a .proto file. +- Generate server and client code using the protocol buffer compiler. +- Use the Ruby gRPC API to write a simple client and server for your service. + +It assumes that you have read the [Getting started](https://github.com/grpc/grpc-common) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release: you can see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. + +This isn't a comprehensive guide to using gRPC in Ruby: more reference documentation is coming soon. + +## Why use gRPC? + +Our example is a simple route mapping application that lets clients get information about features on their route, create a summary of their route, and exchange route information such as traffic updates with the server and other clients. + +With gRPC we can define our service once in a .proto file and implement clients and servers in any of gRPC's supported languages, which in turn can be run in environments ranging from servers inside Google to your own tablet - all the complexity of communication between different languages and environments is handled for you by gRPC. We also get all the advantages of working with protocol buffers, including efficient serialization, a simple IDL, and easy interface updating. + +## Example code and setup + +The example code for our tutorial is in [grpc/grpc-common/ruby/route_guide](https://github.com/grpc/grpc-common/tree/master/ruby/route_guide). To download the example, clone the `grpc-common` repository by running the following command: +```shell +$ git clone https://github.com/google/grpc-common.git +``` + +Then change your current directory to `grpc-common/ruby/route_guide`: +```shell +$ cd grpc-common/ruby/route_guide +``` + +You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Ruby quick start guide](https://github.com/grpc/grpc-common/tree/master/ruby). + + +## Defining the service + +Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc-common)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`grpc-common/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/protos/route_guide.proto). + +To define a service, you specify a named `service` in your .proto file: + +``` +service RouteGuide { + ... +} +``` + +Then you define `rpc` methods inside your service definition, specifying their request and response types. gRPC lets you define four kinds of service method, all of which are used in the `RouteGuide` service: + +- A *simple RPC* where the client sends a request to the server using the stub and waits for a response to come back, just like a normal function call. +``` + // Obtains the feature at a given position. + rpc GetFeature(Point) returns (Feature) {} +``` + +- A *server-side streaming RPC* where the client sends a request to the server and gets a stream to read a sequence of messages back. The client reads from the returned stream until there are no more messages. As you can see in our example, you specify a server-side streaming method by placing the `stream` keyword before the *response* type. +``` + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + rpc ListFeatures(Rectangle) returns (stream Feature) {} +``` + +- A *client-side streaming RPC* where the client writes a sequence of messages and sends them to the server, again using a provided stream. Once the client has finished writing the messages, it waits for the server to read them all and return its response. You specify a server-side streaming method by placing the `stream` keyword before the *request* type. +``` + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + rpc RecordRoute(stream Point) returns (RouteSummary) {} +``` + +- A *bidirectional streaming RPC* where both sides send a sequence of messages using a read-write stream. The two streams operate independently, so clients and servers can read and write in whatever order they like: for example, the server could wait to receive all the client messages before writing its responses, or it could alternately read a message then write a message, or some other combination of reads and writes. The order of messages in each stream is preserved. You specify this type of method by placing the `stream` keyword before both the request and the response. +``` + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} +``` + +Our .proto file also contains protocol buffer message type definitions for all the request and response types used in our service methods - for example, here's the `Point` message type: +``` +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +message Point { + int32 latitude = 1; + int32 longitude = 2; +} +``` + + +## Generating client and server code + +Next we need to generate the gRPC client and server interfaces from our .proto service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC Ruby plugin. + +If you want to run this yourself, make sure you've installed protoc and followed the gRPC Ruby plugin [installation instructions](https://github.com/grpc/grpc/blob/master/INSTALL) first): + +Once that's done, the following command can be used to generate the ruby code. + +```shell +$ protoc -I ../../protos --ruby_out=lib --grpc_out=lib --plugin=protoc-gen-grpc=`which grpc_ruby_plugin` ../../protos/route_guide.proto +``` + +Running this command regenerates the following files in the lib directory: +- `lib/route_guide.pb` defines a module `Examples::RouteGuide` + - This contain all the protocol buffer code to populate, serialize, and retrieve our request and response message types +- `lib/route_guide_services.pb`, extends `Examples::RouteGuide` with stub and service classes + - it adds a class `Service` that is to be used as a base class for define RouteGuide service implementations + - a class `Stub` that can be used to access remote RouteGuide instances + + + +## Creating the server + +First let's look at how we create a `RouteGuide` server. If you're only interested in creating gRPC clients, you can skip this section and go straight to [Creating the client](#client) (though you might find it interesting anyway!). + +There are two parts to making our `RouteGuide` service do its job: +- Implementing the service interface generated from our service definition: doing the actual "work" of our service. +- Running a gRPC server to listen for requests from clients and return the service responses. + +You can find our example `RouteGuide` server in [grpc-common/ruby/route_guide/route_guide_server.rb](https://github.com/grpc/grpc-common/blob/master/ruby/route_guide/route_guide_server.rb). Let's take a closer look at how it works. + +### Implementing RouteGuide + +As you can see, our server has a `ServerImpl` class that extends the generated `RouteGuide::Service`: + +```ruby +# ServerImpl provides an implementation of the RouteGuide service. +class ServerImpl < RouteGuide::Service +``` + +`ServerImpl` implements all our service methods. Let's look at the simplest type first, `GetFeature`, which just gets a `Point` from the client and returns the corresponding feature information from its database in a `Feature`. + +```ruby + def get_feature(point, _call) + name = @feature_db[{ + 'longitude' => point.longitude, + 'latitude' => point.latitude }] || '' + Feature.new(location: point, name: name) + end +``` + +The method is passed a _call for the RPC, the client's `Point` protocol buffer request, and returns `Feature` protocol buffer. In the method we create the `Feature` with the appropriate information, and then `return` it. + +Now let's look at something a bit more complicated - a streaming RPC. `ListFeatures` is a server-side streaming RPC, so we need to send back multiple `Feature`s to our client. + +```ruby +# in ServerImpl + + def list_features(rectangle, _call) + RectangleEnum.new(@feature_db, rectangle).each + end + +``` + +As you can see, here the request object is a `Rectangle` in which our client wants to find `Feature`s), but instead of returning a simple response we need to return an [Enumerator](http://ruby-doc.org//core-2.2.0/Enumerator.html) that yields the responses. In the method, we use a helper class `RectangleEnum`, to act as an Enumerator implementation. + +Similarly, the client-side streaming method `record_route` uses an [Enumerable](http://ruby-doc.org//core-2.2.0/Enumerable.html), but here it's obtained from the call object, which we've ignored in the earlier examples. `call.each_remote_read` yields each message sent by the client in turn. + +```ruby + call.each_remote_read do |point| + ... + end +``` +Finally, let's look at our bidirectional streaming RPC `route_chat`. + +```ruby + def route_chat(notes) + q = EnumeratorQueue.new(self) + t = Thread.new do + begin + notes.each do |n| + ... + end + end + q = EnumeratorQueue.new(self) + ... + return q.each_item + end +``` + +Here the method receives an [Enumerable](http://ruby-doc.org//core-2.2.0/Enumerable.html), notes, but also returns an [Enumerator](http://ruby-doc.org//core-2.2.0/Enumerator.html) that yields the responses. The implementation demonstrates how to set these up so that the requests and responses can be handled concurrently. Although each side will always get the other's messages in the order they were written, both the client and server can read and write in any order — the streams operate completely independently. + +### Starting the server + +Once we've implemented all our methods, we also need to start up a gRPC server so that clients can actually use our service. The following snippet shows how we do this for our `RouteGuide` service: + +```ruby + s = GRPC::RpcServer.new + s.add_http2_port(port) + logger.info("... running insecurely on #{port}") + s.handle(ServerImpl.new(feature_db)) + s.run +``` +As you can see, we build and start our server using a `GRPC::RpcServer`. To do this, we: + +1. Create an instance of our service implementation class `ServerImpl`. +2. Specify the address and port we want to use to listen for client requests using the builder's `add_http2_port` method. +3. Register our service implementation with the `GRPC::RpcServer`. +4. Call `run` on the`GRPC::RpcServer` to create and start an RPC server for our service. + + +## Creating the client + +In this section, we'll look at creating a Rubyclient for our `RouteGuide` service. You can see our complete example client code in [grpc-common/ruby/route_guide/route_guide_client.rb](https://github.com/grpc/grpc-common/blob/master/ruby/route_guide/route_guide_client.rb). + +### Creating a stub + +To call service methods, we first need to create a *stub*. + +We use the `Stub` class of `RouteGuide` module generated from our .proto. + +```ruby + stub = RouteGuide::Stub.new('localhost:50051') +``` + +### Calling service methods + +Now let's look at how we call our service methods. Note that the gRPC Ruby only provides *blocking/synchronous* versions of each method: this means that the RPC call waits for the server to respond, and will either return a response or raise an exception. + +#### Simple RPC + +Calling the simple RPC `GetFeature` is nearly as straightforward as calling a local method. + +```ruby +GET_FEATURE_POINTS = [ + Point.new(latitude: 409_146_138, longitude: -746_188_906), + Point.new(latitude: 0, longitude: 0) +] +.. + GET_FEATURE_POINTS.each do |pt| + resp = stub.get_feature(pt) + ... + p "- found '#{resp.name}' at #{pt.inspect}" + end +``` + +As you can see, we create and populate a request protocol buffer object (in our case `Point`), and create a response protocol buffer object for the server to fill in. Finally, we call the method on the stub, passing it the context, request, and response. If the method returns `OK`, then we can read the response information from the server from our response object. + + +#### Streaming RPCs + +Now let's look at our streaming methods. If you've already read [Creating the server](#server) some of this may look very familiar - streaming RPCs are implemented in a similar way on both sides. Here's where we call the server-side streaming method `list_features`, which returns an `Enumerable` of `Features` + +```ruby + resps = stub.list_features(LIST_FEATURES_RECT) + resps.each do |r| + p "- found '#{r.name}' at #{r.location.inspect}" + end +``` + +`The client-side streaming method `record_rout` is similar, except there in an `Enumerable`. + +```ruby + ... + reqs = RandomRoute.new(features, points_on_route) + resp = stub.record_route(reqs.each, deadline) + ... +``` + +Finally, let's look at our bidirectional streaming RPC `route_chat`. In this case, we pass `Enumerable` to the method and get back an `Enumerable`. + +```ruby + resps = stub.route_chat(ROUTE_CHAT_NOTES) + resps.each { |r| p "received #{r.inspect}" } +``` + +Although it's not shown well by this example, each enumerable is independent of the other - both the client and server can read and write in any order — the streams operate completely independently. + +## Try it out! + +Build client and server: + +```shell +$ # from grpc-common/ruby +$ gem install bundler && bundle install +``` +Run the server, which will listen on port 50051: +```shell +$ # from grpc-common/ruby +$ bundle exec route_guide/route_guide_server.rb ../node/route_guide/route_guide_db.json & +``` +Run the client (in a different terminal): +```shell +$ # from grpc-common/ruby +$ bundle exec route_guide/route_guide_client.rb ../node/route_guide/route_guide_db.json & +``` + From 94e38f6b03e69e996ee26f753a4f77deb01df235 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Thu, 26 Feb 2015 08:02:23 -0800 Subject: [PATCH 07/17] Corrects spelling, fixes grammar and re-word some sections --- ruby/route_guide/README.md | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/ruby/route_guide/README.md b/ruby/route_guide/README.md index 736a3809904..71003b52eb2 100644 --- a/ruby/route_guide/README.md +++ b/ruby/route_guide/README.md @@ -37,7 +37,7 @@ Our first step (as you'll know from [Getting started](https://github.com/grpc/gr To define a service, you specify a named `service` in your .proto file: -``` +```protobuf service RouteGuide { ... } @@ -46,13 +46,13 @@ service RouteGuide { Then you define `rpc` methods inside your service definition, specifying their request and response types. gRPC lets you define four kinds of service method, all of which are used in the `RouteGuide` service: - A *simple RPC* where the client sends a request to the server using the stub and waits for a response to come back, just like a normal function call. -``` +```protobuf // Obtains the feature at a given position. rpc GetFeature(Point) returns (Feature) {} ``` - A *server-side streaming RPC* where the client sends a request to the server and gets a stream to read a sequence of messages back. The client reads from the returned stream until there are no more messages. As you can see in our example, you specify a server-side streaming method by placing the `stream` keyword before the *response* type. -``` +```protobuf // Obtains the Features available within the given Rectangle. Results are // streamed rather than returned at once (e.g. in a response message with a // repeated field), as the rectangle may cover a large area and contain a @@ -61,21 +61,21 @@ Then you define `rpc` methods inside your service definition, specifying their r ``` - A *client-side streaming RPC* where the client writes a sequence of messages and sends them to the server, again using a provided stream. Once the client has finished writing the messages, it waits for the server to read them all and return its response. You specify a server-side streaming method by placing the `stream` keyword before the *request* type. -``` +```protobuf // Accepts a stream of Points on a route being traversed, returning a // RouteSummary when traversal is completed. rpc RecordRoute(stream Point) returns (RouteSummary) {} ``` - A *bidirectional streaming RPC* where both sides send a sequence of messages using a read-write stream. The two streams operate independently, so clients and servers can read and write in whatever order they like: for example, the server could wait to receive all the client messages before writing its responses, or it could alternately read a message then write a message, or some other combination of reads and writes. The order of messages in each stream is preserved. You specify this type of method by placing the `stream` keyword before both the request and the response. -``` +```protobuf // Accepts a stream of RouteNotes sent while a route is being traversed, // while receiving other RouteNotes (e.g. from other users). rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} ``` Our .proto file also contains protocol buffer message type definitions for all the request and response types used in our service methods - for example, here's the `Point` message type: -``` +```protobuf // Points are represented as latitude-longitude pairs in the E7 representation // (degrees multiplied by 10**7 and rounded to the nearest integer). // Latitudes should be in the range +/- 90 degrees and longitude should be in @@ -103,7 +103,7 @@ Running this command regenerates the following files in the lib directory: - `lib/route_guide.pb` defines a module `Examples::RouteGuide` - This contain all the protocol buffer code to populate, serialize, and retrieve our request and response message types - `lib/route_guide_services.pb`, extends `Examples::RouteGuide` with stub and service classes - - it adds a class `Service` that is to be used as a base class for define RouteGuide service implementations + - a class `Service` for use as a base class when defining RouteGuide service implementations - a class `Stub` that can be used to access remote RouteGuide instances @@ -138,7 +138,7 @@ class ServerImpl < RouteGuide::Service end ``` -The method is passed a _call for the RPC, the client's `Point` protocol buffer request, and returns `Feature` protocol buffer. In the method we create the `Feature` with the appropriate information, and then `return` it. +The method is passed a _call for the RPC, the client's `Point` protocol buffer request, and returns a `Feature` protocol buffer. In the method we create the `Feature` with the appropriate information, and then `return` it. Now let's look at something a bit more complicated - a streaming RPC. `ListFeatures` is a server-side streaming RPC, so we need to send back multiple `Feature`s to our client. @@ -148,10 +148,9 @@ Now let's look at something a bit more complicated - a streaming RPC. `ListFeatu def list_features(rectangle, _call) RectangleEnum.new(@feature_db, rectangle).each end - ``` -As you can see, here the request object is a `Rectangle` in which our client wants to find `Feature`s), but instead of returning a simple response we need to return an [Enumerator](http://ruby-doc.org//core-2.2.0/Enumerator.html) that yields the responses. In the method, we use a helper class `RectangleEnum`, to act as an Enumerator implementation. +As you can see, here the request object is a `Rectangle` in which our client wants to find `Feature`s, but instead of returning a simple response we need to return an [Enumerator](http://ruby-doc.org//core-2.2.0/Enumerator.html) that yields the responses. In the method, we use a helper class `RectangleEnum`, to act as an Enumerator implementation. Similarly, the client-side streaming method `record_route` uses an [Enumerable](http://ruby-doc.org//core-2.2.0/Enumerable.html), but here it's obtained from the call object, which we've ignored in the earlier examples. `call.each_remote_read` yields each message sent by the client in turn. @@ -177,7 +176,7 @@ Finally, let's look at our bidirectional streaming RPC `route_chat`. end ``` -Here the method receives an [Enumerable](http://ruby-doc.org//core-2.2.0/Enumerable.html), notes, but also returns an [Enumerator](http://ruby-doc.org//core-2.2.0/Enumerator.html) that yields the responses. The implementation demonstrates how to set these up so that the requests and responses can be handled concurrently. Although each side will always get the other's messages in the order they were written, both the client and server can read and write in any order — the streams operate completely independently. +Here the method receives an [Enumerable](http://ruby-doc.org//core-2.2.0/Enumerable.html), but also returns an [Enumerator](http://ruby-doc.org//core-2.2.0/Enumerator.html) that yields the responses. The implementation demonstrates how to set these up so that the requests and responses can be handled concurrently. Although each side will always get the other's messages in the order they were written, both the client and server can read and write in any order — the streams operate completely independently. ### Starting the server @@ -206,7 +205,7 @@ In this section, we'll look at creating a Rubyclient for our `RouteGuide` servic To call service methods, we first need to create a *stub*. -We use the `Stub` class of `RouteGuide` module generated from our .proto. +We use the `Stub` class of the `RouteGuide` module generated from our .proto. ```ruby stub = RouteGuide::Stub.new('localhost:50051') @@ -247,7 +246,7 @@ Now let's look at our streaming methods. If you've already read [Creating the se end ``` -`The client-side streaming method `record_rout` is similar, except there in an `Enumerable`. +The client-side streaming method `record_route` is similar, except there we pass the server an `Enumerable`. ```ruby ... From c8809b1d25abb62fba05b0c68e85ee4889785650 Mon Sep 17 00:00:00 2001 From: nmittler Date: Wed, 25 Feb 2015 11:02:03 -0800 Subject: [PATCH 08/17] Removing java examples from grpc-common --- java/pom.xml | 105 -- java/run_greeter_client.sh | 10 - java/run_greeter_server.sh | 9 - java/src/main/java/ex/grpc/GreeterClient.java | 55 - java/src/main/java/ex/grpc/GreeterGrpc.java | 172 ---- java/src/main/java/ex/grpc/GreeterImpl.java | 16 - java/src/main/java/ex/grpc/GreeterServer.java | 51 - java/src/main/java/ex/grpc/Helloworld.java | 951 ------------------ 8 files changed, 1369 deletions(-) delete mode 100644 java/pom.xml delete mode 100755 java/run_greeter_client.sh delete mode 100755 java/run_greeter_server.sh delete mode 100644 java/src/main/java/ex/grpc/GreeterClient.java delete mode 100644 java/src/main/java/ex/grpc/GreeterGrpc.java delete mode 100644 java/src/main/java/ex/grpc/GreeterImpl.java delete mode 100644 java/src/main/java/ex/grpc/GreeterServer.java delete mode 100644 java/src/main/java/ex/grpc/Helloworld.java diff --git a/java/pom.xml b/java/pom.xml deleted file mode 100644 index da0ee205f77..00000000000 --- a/java/pom.xml +++ /dev/null @@ -1,105 +0,0 @@ - - 4.0.0 - - - com.google.net.stubby - stubby-parent - 0.1.0-SNAPSHOT - - - grpc-hello-world - jar - - Hello gRPC World - - - - ${project.groupId} - stubby-core - ${project.version} - - - ${project.groupId} - stubby-netty - ${project.version} - - - ${project.groupId} - stubby-okhttp - ${project.version} - - - ${project.groupId} - stubby-stub - ${project.version} - - - ${project.groupId} - stubby-testing - ${project.version} - - - junit - junit - compile - - - org.mockito - mockito-core - compile - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - assemble-all - package - - single - - - - - - jar-with-dependencies - - - - - - com.internetitem - write-properties-file-maven-plugin - - - bootclasspath - prepare-package - - write-properties-file - - - bootclasspath.properties - ${project.build.directory} - - - bootclasspath - ${argLine.bootcp} - - - jar - ${project.build.directory}/${project.artifactId}-${project.version}-jar-with-dependencies.jar - - - - - - - - - diff --git a/java/run_greeter_client.sh b/java/run_greeter_client.sh deleted file mode 100755 index e86ab4ae891..00000000000 --- a/java/run_greeter_client.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -e -TARGET='Greeter Client' -TARGET_CLASS='ex.grpc.GreeterClient' -TARGET_ARGS="$@" - -cd "$(dirname "$0")" -mvn -q -nsu -am package -Dcheckstyle.skip=true -DskipTests -. target/bootclasspath.properties -echo "[INFO] Running: $TARGET ($TARGET_CLASS $TARGET_ARGS)" -exec java "$bootclasspath" -cp "$jar" "$TARGET_CLASS" $TARGET_ARGS diff --git a/java/run_greeter_server.sh b/java/run_greeter_server.sh deleted file mode 100755 index 836abc7f48a..00000000000 --- a/java/run_greeter_server.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -e -TARGET='Greeter Server' -TARGET_CLASS='ex.grpc.GreeterServer' - -cd "$(dirname "$0")" -mvn -q -nsu -am package -Dcheckstyle.skip=true -DskipTests -. target/bootclasspath.properties -echo "[INFO] Running: $TARGET ($TARGET_CLASS)" -exec java "$bootclasspath" -cp "$jar" "$TARGET_CLASS" diff --git a/java/src/main/java/ex/grpc/GreeterClient.java b/java/src/main/java/ex/grpc/GreeterClient.java deleted file mode 100644 index 9a4615132d6..00000000000 --- a/java/src/main/java/ex/grpc/GreeterClient.java +++ /dev/null @@ -1,55 +0,0 @@ -package ex.grpc; - -import com.google.net.stubby.ChannelImpl; -import com.google.net.stubby.stub.StreamObserver; -import com.google.net.stubby.transport.netty.NegotiationType; -import com.google.net.stubby.transport.netty.NettyChannelBuilder; - -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.concurrent.TimeUnit; - -public class GreeterClient { - private final Logger logger = Logger.getLogger( - GreeterClient.class.getName()); - private final ChannelImpl channel; - private final GreeterGrpc.GreeterBlockingStub blockingStub; - - public GreeterClient(String host, int port) { - channel = NettyChannelBuilder.forAddress(host, port) - .negotiationType(NegotiationType.PLAINTEXT) - .build(); - blockingStub = GreeterGrpc.newBlockingStub(channel); - } - - public void shutdown() throws InterruptedException { - channel.shutdown().awaitTerminated(5, TimeUnit.SECONDS); - } - - public void greet(String name) { - try { - logger.fine("Will try to greet " + name + " ..."); - Helloworld.HelloRequest req = - Helloworld.HelloRequest.newBuilder().setName(name).build(); - Helloworld.HelloReply reply = blockingStub.sayHello(req); - logger.info("Greeting: " + reply.getMessage()); - } catch (RuntimeException e) { - logger.log(Level.WARNING, "RPC failed", e); - return; - } - } - - public static void main(String[] args) throws Exception { - GreeterClient client = new GreeterClient("localhost", 50051); - try { - /* Access a service running on the local machine on port 50051 */ - String user = "world"; - if (args.length > 0) { - user = args[0]; /* Use the arg as the name to greet if provided */ - } - client.greet(user); - } finally { - client.shutdown(); - } - } -} diff --git a/java/src/main/java/ex/grpc/GreeterGrpc.java b/java/src/main/java/ex/grpc/GreeterGrpc.java deleted file mode 100644 index 080c3dfc434..00000000000 --- a/java/src/main/java/ex/grpc/GreeterGrpc.java +++ /dev/null @@ -1,172 +0,0 @@ -package ex.grpc; - -import static com.google.net.stubby.stub.Calls.createMethodDescriptor; -import static com.google.net.stubby.stub.Calls.asyncUnaryCall; -import static com.google.net.stubby.stub.Calls.asyncServerStreamingCall; -import static com.google.net.stubby.stub.Calls.asyncClientStreamingCall; -import static com.google.net.stubby.stub.Calls.duplexStreamingCall; -import static com.google.net.stubby.stub.Calls.blockingUnaryCall; -import static com.google.net.stubby.stub.Calls.blockingServerStreamingCall; -import static com.google.net.stubby.stub.Calls.unaryFutureCall; -import static com.google.net.stubby.stub.ServerCalls.createMethodDefinition; -import static com.google.net.stubby.stub.ServerCalls.asyncUnaryRequestCall; -import static com.google.net.stubby.stub.ServerCalls.asyncStreamingRequestCall; - -@javax.annotation.Generated("by gRPC proto compiler") -public class GreeterGrpc { - - private static final com.google.net.stubby.stub.Method METHOD_SAY_HELLO = - com.google.net.stubby.stub.Method.create( - com.google.net.stubby.MethodType.UNARY, "sayHello", - com.google.net.stubby.proto.ProtoUtils.marshaller(ex.grpc.Helloworld.HelloRequest.PARSER), - com.google.net.stubby.proto.ProtoUtils.marshaller(ex.grpc.Helloworld.HelloReply.PARSER)); - - public static GreeterStub newStub(com.google.net.stubby.Channel channel) { - return new GreeterStub(channel, CONFIG); - } - - public static GreeterBlockingStub newBlockingStub( - com.google.net.stubby.Channel channel) { - return new GreeterBlockingStub(channel, CONFIG); - } - - public static GreeterFutureStub newFutureStub( - com.google.net.stubby.Channel channel) { - return new GreeterFutureStub(channel, CONFIG); - } - - public static final GreeterServiceDescriptor CONFIG = - new GreeterServiceDescriptor(); - - @javax.annotation.concurrent.Immutable - public static class GreeterServiceDescriptor extends - com.google.net.stubby.stub.AbstractServiceDescriptor { - public final com.google.net.stubby.MethodDescriptor sayHello; - - private GreeterServiceDescriptor() { - sayHello = createMethodDescriptor( - "helloworld.Greeter", METHOD_SAY_HELLO); - } - - private GreeterServiceDescriptor( - java.util.Map> methodMap) { - sayHello = (com.google.net.stubby.MethodDescriptor) methodMap.get( - CONFIG.sayHello.getName()); - } - - @java.lang.Override - protected GreeterServiceDescriptor build( - java.util.Map> methodMap) { - return new GreeterServiceDescriptor(methodMap); - } - - @java.lang.Override - public com.google.common.collect.ImmutableList> methods() { - return com.google.common.collect.ImmutableList.>of( - sayHello); - } - } - - public static interface Greeter { - - public void sayHello(ex.grpc.Helloworld.HelloRequest request, - com.google.net.stubby.stub.StreamObserver responseObserver); - } - - public static interface GreeterBlockingClient { - - public ex.grpc.Helloworld.HelloReply sayHello(ex.grpc.Helloworld.HelloRequest request); - } - - public static interface GreeterFutureClient { - - public com.google.common.util.concurrent.ListenableFuture sayHello( - ex.grpc.Helloworld.HelloRequest request); - } - - public static class GreeterStub extends - com.google.net.stubby.stub.AbstractStub - implements Greeter { - private GreeterStub(com.google.net.stubby.Channel channel, - GreeterServiceDescriptor config) { - super(channel, config); - } - - @java.lang.Override - protected GreeterStub build(com.google.net.stubby.Channel channel, - GreeterServiceDescriptor config) { - return new GreeterStub(channel, config); - } - - @java.lang.Override - public void sayHello(ex.grpc.Helloworld.HelloRequest request, - com.google.net.stubby.stub.StreamObserver responseObserver) { - asyncUnaryCall( - channel.newCall(config.sayHello), request, responseObserver); - } - } - - public static class GreeterBlockingStub extends - com.google.net.stubby.stub.AbstractStub - implements GreeterBlockingClient { - private GreeterBlockingStub(com.google.net.stubby.Channel channel, - GreeterServiceDescriptor config) { - super(channel, config); - } - - @java.lang.Override - protected GreeterBlockingStub build(com.google.net.stubby.Channel channel, - GreeterServiceDescriptor config) { - return new GreeterBlockingStub(channel, config); - } - - @java.lang.Override - public ex.grpc.Helloworld.HelloReply sayHello(ex.grpc.Helloworld.HelloRequest request) { - return blockingUnaryCall( - channel.newCall(config.sayHello), request); - } - } - - public static class GreeterFutureStub extends - com.google.net.stubby.stub.AbstractStub - implements GreeterFutureClient { - private GreeterFutureStub(com.google.net.stubby.Channel channel, - GreeterServiceDescriptor config) { - super(channel, config); - } - - @java.lang.Override - protected GreeterFutureStub build(com.google.net.stubby.Channel channel, - GreeterServiceDescriptor config) { - return new GreeterFutureStub(channel, config); - } - - @java.lang.Override - public com.google.common.util.concurrent.ListenableFuture sayHello( - ex.grpc.Helloworld.HelloRequest request) { - return unaryFutureCall( - channel.newCall(config.sayHello), request); - } - } - - public static com.google.net.stubby.ServerServiceDefinition bindService( - final Greeter serviceImpl) { - return com.google.net.stubby.ServerServiceDefinition.builder("helloworld.Greeter") - .addMethod(createMethodDefinition( - METHOD_SAY_HELLO, - asyncUnaryRequestCall( - new com.google.net.stubby.stub.ServerCalls.UnaryRequestMethod< - ex.grpc.Helloworld.HelloRequest, - ex.grpc.Helloworld.HelloReply>() { - @java.lang.Override - public void invoke( - ex.grpc.Helloworld.HelloRequest request, - com.google.net.stubby.stub.StreamObserver responseObserver) { - serviceImpl.sayHello(request, responseObserver); - } - }))).build(); - } -} diff --git a/java/src/main/java/ex/grpc/GreeterImpl.java b/java/src/main/java/ex/grpc/GreeterImpl.java deleted file mode 100644 index 825ba8631ec..00000000000 --- a/java/src/main/java/ex/grpc/GreeterImpl.java +++ /dev/null @@ -1,16 +0,0 @@ -package ex.grpc; - -import com.google.net.stubby.stub.StreamObserver; - -public class GreeterImpl implements GreeterGrpc.Greeter { - - @Override - public void sayHello(Helloworld.HelloRequest req, - StreamObserver responseObserver) { - Helloworld.HelloReply reply = Helloworld.HelloReply.newBuilder().setMessage( - "Hello " + req.getName()).build(); - responseObserver.onValue(reply); - responseObserver.onCompleted(); - } - -} diff --git a/java/src/main/java/ex/grpc/GreeterServer.java b/java/src/main/java/ex/grpc/GreeterServer.java deleted file mode 100644 index bb05680b0a6..00000000000 --- a/java/src/main/java/ex/grpc/GreeterServer.java +++ /dev/null @@ -1,51 +0,0 @@ -package ex.grpc; - -import com.google.common.util.concurrent.MoreExecutors; -import com.google.net.stubby.ServerImpl; -import com.google.net.stubby.transport.netty.NettyServerBuilder; - -import java.util.concurrent.TimeUnit; - -/** - * Server that manages startup/shutdown of a {@code Greeter} server. - */ -public class GreeterServer { - /* The port on which the server should run */ - private int port = 50051; - private ServerImpl server; - - private void start() throws Exception { - server = NettyServerBuilder.forPort(port) - .addService(GreeterGrpc.bindService(new GreeterImpl())) - .build(); - server.startAsync(); - server.awaitRunning(5, TimeUnit.SECONDS); - System.out.println("Server started on port:" + port); - } - - private void stop() throws Exception { - server.stopAsync(); - server.awaitTerminated(); - System.out.println("Server shutting down ..."); - } - - /** - * Main launches the server from the command line. - */ - public static void main(String[] args) throws Exception { - final GreeterServer server = new GreeterServer(); - - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - try { - System.out.println("Shutting down"); - server.stop(); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - server.start(); - } -} diff --git a/java/src/main/java/ex/grpc/Helloworld.java b/java/src/main/java/ex/grpc/Helloworld.java deleted file mode 100644 index b25a63fca32..00000000000 --- a/java/src/main/java/ex/grpc/Helloworld.java +++ /dev/null @@ -1,951 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: helloworld.proto - -package ex.grpc; - -public final class Helloworld { - private Helloworld() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - } - public interface HelloRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:helloworld.HelloRequest) - com.google.protobuf.MessageOrBuilder { - - /** - * optional string name = 1; - */ - java.lang.String getName(); - /** - * optional string name = 1; - */ - com.google.protobuf.ByteString - getNameBytes(); - } - /** - * Protobuf type {@code helloworld.HelloRequest} - * - *
-   * The request message containing the user's name.
-   * 
- */ - public static final class HelloRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:helloworld.HelloRequest) - HelloRequestOrBuilder { - // Use HelloRequest.newBuilder() to construct. - private HelloRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private HelloRequest() { - name_ = ""; - } - - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); - } - private HelloRequest( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - this(); - int mutable_bitField0_ = 0; - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } - case 10: { - com.google.protobuf.ByteString bs = input.readBytes(); - - name_ = bs; - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return ex.grpc.Helloworld.internal_static_helloworld_HelloRequest_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return ex.grpc.Helloworld.internal_static_helloworld_HelloRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - ex.grpc.Helloworld.HelloRequest.class, ex.grpc.Helloworld.HelloRequest.Builder.class); - } - - public static final com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public HelloRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new HelloRequest(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - public static final int NAME_FIELD_NUMBER = 1; - private java.lang.Object name_; - /** - * optional string name = 1; - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - name_ = s; - } - return s; - } - } - /** - * optional string name = 1; - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (!getNameBytes().isEmpty()) { - output.writeBytes(1, getNameBytes()); - } - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (!getNameBytes().isEmpty()) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getNameBytes()); - } - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - public static ex.grpc.Helloworld.HelloRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static ex.grpc.Helloworld.HelloRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static ex.grpc.Helloworld.HelloRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static ex.grpc.Helloworld.HelloRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static ex.grpc.Helloworld.HelloRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static ex.grpc.Helloworld.HelloRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static ex.grpc.Helloworld.HelloRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static ex.grpc.Helloworld.HelloRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static ex.grpc.Helloworld.HelloRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static ex.grpc.Helloworld.HelloRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return new Builder(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(ex.grpc.Helloworld.HelloRequest prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code helloworld.HelloRequest} - * - *
-     * The request message containing the user's name.
-     * 
- */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:helloworld.HelloRequest) - ex.grpc.Helloworld.HelloRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return ex.grpc.Helloworld.internal_static_helloworld_HelloRequest_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return ex.grpc.Helloworld.internal_static_helloworld_HelloRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - ex.grpc.Helloworld.HelloRequest.class, ex.grpc.Helloworld.HelloRequest.Builder.class); - } - - // Construct using ex.grpc.Helloworld.HelloRequest.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - public Builder clear() { - super.clear(); - name_ = ""; - - return this; - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return ex.grpc.Helloworld.internal_static_helloworld_HelloRequest_descriptor; - } - - public ex.grpc.Helloworld.HelloRequest getDefaultInstanceForType() { - return ex.grpc.Helloworld.HelloRequest.getDefaultInstance(); - } - - public ex.grpc.Helloworld.HelloRequest build() { - ex.grpc.Helloworld.HelloRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public ex.grpc.Helloworld.HelloRequest buildPartial() { - ex.grpc.Helloworld.HelloRequest result = new ex.grpc.Helloworld.HelloRequest(this); - result.name_ = name_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof ex.grpc.Helloworld.HelloRequest) { - return mergeFrom((ex.grpc.Helloworld.HelloRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(ex.grpc.Helloworld.HelloRequest other) { - if (other == ex.grpc.Helloworld.HelloRequest.getDefaultInstance()) return this; - if (!other.getName().isEmpty()) { - name_ = other.name_; - onChanged(); - } - onChanged(); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - ex.grpc.Helloworld.HelloRequest parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (ex.grpc.Helloworld.HelloRequest) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - - private java.lang.Object name_ = ""; - /** - * optional string name = 1; - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - name_ = s; - } - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string name = 1; - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string name = 1; - */ - public Builder setName( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - - name_ = value; - onChanged(); - return this; - } - /** - * optional string name = 1; - */ - public Builder clearName() { - - name_ = getDefaultInstance().getName(); - onChanged(); - return this; - } - /** - * optional string name = 1; - */ - public Builder setNameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - - name_ = value; - onChanged(); - return this; - } - public final Builder setUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; - } - - public final Builder mergeUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; - } - - - // @@protoc_insertion_point(builder_scope:helloworld.HelloRequest) - } - - // @@protoc_insertion_point(class_scope:helloworld.HelloRequest) - private static final ex.grpc.Helloworld.HelloRequest defaultInstance;static { - defaultInstance = new ex.grpc.Helloworld.HelloRequest(); - } - - public static ex.grpc.Helloworld.HelloRequest getDefaultInstance() { - return defaultInstance; - } - - public ex.grpc.Helloworld.HelloRequest getDefaultInstanceForType() { - return defaultInstance; - } - - } - - public interface HelloReplyOrBuilder extends - // @@protoc_insertion_point(interface_extends:helloworld.HelloReply) - com.google.protobuf.MessageOrBuilder { - - /** - * optional string message = 1; - */ - java.lang.String getMessage(); - /** - * optional string message = 1; - */ - com.google.protobuf.ByteString - getMessageBytes(); - } - /** - * Protobuf type {@code helloworld.HelloReply} - * - *
-   * The response message containing the greetings
-   * 
- */ - public static final class HelloReply extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:helloworld.HelloReply) - HelloReplyOrBuilder { - // Use HelloReply.newBuilder() to construct. - private HelloReply(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private HelloReply() { - message_ = ""; - } - - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); - } - private HelloReply( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - this(); - int mutable_bitField0_ = 0; - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } - case 10: { - com.google.protobuf.ByteString bs = input.readBytes(); - - message_ = bs; - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return ex.grpc.Helloworld.internal_static_helloworld_HelloReply_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return ex.grpc.Helloworld.internal_static_helloworld_HelloReply_fieldAccessorTable - .ensureFieldAccessorsInitialized( - ex.grpc.Helloworld.HelloReply.class, ex.grpc.Helloworld.HelloReply.Builder.class); - } - - public static final com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public HelloReply parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new HelloReply(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - public static final int MESSAGE_FIELD_NUMBER = 1; - private java.lang.Object message_; - /** - * optional string message = 1; - */ - public java.lang.String getMessage() { - java.lang.Object ref = message_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - message_ = s; - } - return s; - } - } - /** - * optional string message = 1; - */ - public com.google.protobuf.ByteString - getMessageBytes() { - java.lang.Object ref = message_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - message_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (!getMessageBytes().isEmpty()) { - output.writeBytes(1, getMessageBytes()); - } - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (!getMessageBytes().isEmpty()) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getMessageBytes()); - } - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - public static ex.grpc.Helloworld.HelloReply parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static ex.grpc.Helloworld.HelloReply parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static ex.grpc.Helloworld.HelloReply parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static ex.grpc.Helloworld.HelloReply parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static ex.grpc.Helloworld.HelloReply parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static ex.grpc.Helloworld.HelloReply parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static ex.grpc.Helloworld.HelloReply parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static ex.grpc.Helloworld.HelloReply parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static ex.grpc.Helloworld.HelloReply parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static ex.grpc.Helloworld.HelloReply parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return new Builder(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(ex.grpc.Helloworld.HelloReply prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code helloworld.HelloReply} - * - *
-     * The response message containing the greetings
-     * 
- */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:helloworld.HelloReply) - ex.grpc.Helloworld.HelloReplyOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return ex.grpc.Helloworld.internal_static_helloworld_HelloReply_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return ex.grpc.Helloworld.internal_static_helloworld_HelloReply_fieldAccessorTable - .ensureFieldAccessorsInitialized( - ex.grpc.Helloworld.HelloReply.class, ex.grpc.Helloworld.HelloReply.Builder.class); - } - - // Construct using ex.grpc.Helloworld.HelloReply.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - public Builder clear() { - super.clear(); - message_ = ""; - - return this; - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return ex.grpc.Helloworld.internal_static_helloworld_HelloReply_descriptor; - } - - public ex.grpc.Helloworld.HelloReply getDefaultInstanceForType() { - return ex.grpc.Helloworld.HelloReply.getDefaultInstance(); - } - - public ex.grpc.Helloworld.HelloReply build() { - ex.grpc.Helloworld.HelloReply result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public ex.grpc.Helloworld.HelloReply buildPartial() { - ex.grpc.Helloworld.HelloReply result = new ex.grpc.Helloworld.HelloReply(this); - result.message_ = message_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof ex.grpc.Helloworld.HelloReply) { - return mergeFrom((ex.grpc.Helloworld.HelloReply)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(ex.grpc.Helloworld.HelloReply other) { - if (other == ex.grpc.Helloworld.HelloReply.getDefaultInstance()) return this; - if (!other.getMessage().isEmpty()) { - message_ = other.message_; - onChanged(); - } - onChanged(); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - ex.grpc.Helloworld.HelloReply parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (ex.grpc.Helloworld.HelloReply) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - - private java.lang.Object message_ = ""; - /** - * optional string message = 1; - */ - public java.lang.String getMessage() { - java.lang.Object ref = message_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - message_ = s; - } - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string message = 1; - */ - public com.google.protobuf.ByteString - getMessageBytes() { - java.lang.Object ref = message_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - message_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string message = 1; - */ - public Builder setMessage( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - - message_ = value; - onChanged(); - return this; - } - /** - * optional string message = 1; - */ - public Builder clearMessage() { - - message_ = getDefaultInstance().getMessage(); - onChanged(); - return this; - } - /** - * optional string message = 1; - */ - public Builder setMessageBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - - message_ = value; - onChanged(); - return this; - } - public final Builder setUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; - } - - public final Builder mergeUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; - } - - - // @@protoc_insertion_point(builder_scope:helloworld.HelloReply) - } - - // @@protoc_insertion_point(class_scope:helloworld.HelloReply) - private static final ex.grpc.Helloworld.HelloReply defaultInstance;static { - defaultInstance = new ex.grpc.Helloworld.HelloReply(); - } - - public static ex.grpc.Helloworld.HelloReply getDefaultInstance() { - return defaultInstance; - } - - public ex.grpc.Helloworld.HelloReply getDefaultInstanceForType() { - return defaultInstance; - } - - } - - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_helloworld_HelloRequest_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_helloworld_HelloRequest_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_helloworld_HelloReply_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_helloworld_HelloReply_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { - return descriptor; - } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; - static { - java.lang.String[] descriptorData = { - "\n\020helloworld.proto\022\nhelloworld\"\034\n\014HelloR" + - "equest\022\014\n\004name\030\001 \001(\t\"\035\n\nHelloReply\022\017\n\007me" + - "ssage\030\001 \001(\t2I\n\007Greeter\022>\n\010sayHello\022\030.hel" + - "loworld.HelloRequest\032\026.helloworld.HelloR" + - "eply\"\000B\t\n\007ex.grpcb\006proto3" - }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); - internal_static_helloworld_HelloRequest_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_helloworld_HelloRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_helloworld_HelloRequest_descriptor, - new java.lang.String[] { "Name", }); - internal_static_helloworld_HelloReply_descriptor = - getDescriptor().getMessageTypes().get(1); - internal_static_helloworld_HelloReply_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_helloworld_HelloReply_descriptor, - new java.lang.String[] { "Message", }); - } - - // @@protoc_insertion_point(outer_class_scope) -} From ff0591f8d5017afd8812593e2cfc6b097895c4a4 Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Thu, 26 Feb 2015 14:30:19 +0000 Subject: [PATCH 09/17] Updated to work with new Java example location/build --- README.md | 195 ++++++++++++++++++------------------------------------ 1 file changed, 65 insertions(+), 130 deletions(-) diff --git a/README.md b/README.md index d7860c63d9c..bd35e9dede4 100644 --- a/README.md +++ b/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 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 -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 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) ### 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. 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 `HelloRequest` 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"; -option java_package = "ex.grpc"; +option java_package = "io.grpc.examples"; 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 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 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 -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, -the instructions are in [`grpc-java`](https://github.com/grpc/grpc-java). +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: -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 +```shell +../gradlew build ``` -[need to update this once I get the plugin built] - -This generates the following classes, which contain all the generated code +This generates the following classes from our .proto, which contain all the generated code 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 `HelloRequest` and `HelloReply` message types -- [`GreeterGrpc.java`](java/src/main/java/ex/grpc/GreeterGrpc.java), -which contains (along with some other useful code): +- `GreeterGrpc.java`, which contains (along with some other useful code): - an interface for `Greeter` servers to implement ```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: -- a simple service implementation -[GreeterImpl.java](java/src/main/java/ex/grpc/GreeterImpl.java). +- a main server class that hosts the service implementation and allows access over the +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 -[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. As you can see, the class `GreeterImpl` implements the interface `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 - public void hello(Helloworld.HelloRequest req, - StreamObserver responseObserver) { - Helloworld.HelloReply reply = - Helloworld.HelloReply.newBuilder().setMessage( - "Hello " + req.getName()).build(); - responseObserver.onValue(reply); - responseObserver.onCompleted(); - } + @Override + public void sayHello(HelloRequest req, StreamObserver responseObserver) { + HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); + responseObserver.onValue(reply); + responseObserver.onCompleted(); + } ``` - `hello` takes two parameters: - - `Helloworld.HelloRequest`: the request - - `StreamObserver`: a response observer, which is + - `HelloRequest`: the request + - `StreamObserver`: a response observer, which is a special interface for the server to call with its response To return our response to the client and complete the call: 1. We construct and populate a `HelloReply` response object with our exciting message, as specified in our interface definition. -2. We use the`responseObserver` to return the `HelloReply` to the client -and then specify that we've finished dealing with the RPC +2. We return the `HelloReply` to the client and then specify that we've finished dealing with the RPC. #### 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 implementation available from the network. ```java + /* The port on which the server should run */ + private int port = 50051; private ServerImpl server; - ... + private void start() throws Exception { server = NettyServerBuilder.forPort(port) - .addService(GreeterGrpc.bindService(new GreeterImpl())) - .build(); - server.startAsync(); - server.awaitRunning(5, TimeUnit.SECONDS); + .addService(GreeterGrpc.bindService(new GreeterImpl())) + .build().start(); + logger.info("Server started, listening on " + port); + 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 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. - ### 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 GreeterGrpc.GreeterBlockingStub blockingStub; - public HelloClient(String host, int port) { - channel = NettyChannelBuilder.forAddress(host, port) - .negotiationType(NegotiationType.PLAINTEXT) - .build(); + public HelloWorldClient(String host, int port) { + channel = + NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT) + .build(); 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. 2. We call the stub's `hello()` RPC with our request and get a `HelloReply` -back, -from which we can get our greeting. +back, from which we can get our greeting. ```java - public void greet(String name) { - logger.debug("Will try to greet " + name + " ..."); - try { - Helloworld.HelloRequest request = - Helloworld.HelloRequest.newBuilder().setName(name).build(); - Helloworld.HelloReply reply = blockingStub.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. + HelloRequest req = HelloRequest.newBuilder().setName(name).build(); + HelloReply reply = blockingStub.sayHello(req); -``` -$ mvn package ``` ### Try it out! -We've added simple shell scripts to simplifying running the examples. Now -that they are built, you can run the server with: +Our [Gradle build file](https://github.com/grpc/grpc-java/blob/master/examples/build.gradle) simplifies building and running the examples. + +You can build and run the server from the `grpc-java` root folder with: ```sh -$ ./run_greeter_server.sh +$ ./gradlew :grpc-examples:helloWorldServer ``` and in another terminal window confirm that it receives a message. ```sh -$ ./run_greeter_client.sh +$ ./gradlew :grpc-examples:helloWorldClient ``` ### 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 in this repository, we've also generated and implemented `Greeter` in some of gRPC's other supported languages. Each service -and client uses interface code generated from [exactly the same -.proto](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto) +and client uses interface code generated from the same proto 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 [`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 From 4b8fbe2bb3e28ac469f77c143bf9d62eb53f2d74 Mon Sep 17 00:00:00 2001 From: LisaFC Date: Thu, 26 Feb 2015 14:35:18 +0000 Subject: [PATCH 10/17] Fixed a couple of small errors --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bd35e9dede4..2f6acfa59e4 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,7 @@ 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 defined in our `Greeting` service. -(If you didn't install the gRPC plugins and protoc on your system and are working along with +(If you didn't install the gRPC plugins and protoc on your system and are just reading along with the example, you can skip this step and move onto the next one where we examine the generated code.) @@ -327,7 +327,7 @@ how all this works in a bit more detail in our language-specific documentation. Client-side gRPC is pretty simple. In this step, we'll use the generated code to write a simple client that can access the `Greeter` server we created in the [previous section](#server). You can see the complete client code in -[GreeterClient.java](java/src/main/java/ex/grpc/GreeterClient.java). +[HelloWorldClient.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/HelloWorldClient.java). Again, we're not going to go into much detail about how to implement a client; we'll leave that for the tutorial. From 51d53cb10cb45ba6611c947e9f8272f486863ad9 Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Thu, 26 Feb 2015 14:41:47 +0000 Subject: [PATCH 11/17] Removed big diagram todo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f6acfa59e4..9adca9fc150 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ parameters and return types. On the server side, the server implements this interface and runs a gRPC server to handle client calls. On the client side, the client has a *stub* that provides exactly the same methods as the server. -##TODO: diagram? + gRPC clients and servers can run and talk to each other in a variety of environments - from servers inside Google to your own desktop - and can From 5d843ea3dc0d57187131f913a9245fbf21f6bdc6 Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Thu, 26 Feb 2015 14:44:22 +0000 Subject: [PATCH 12/17] small fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9adca9fc150..8e5d816a121 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ the client has a *stub* that provides exactly the same methods as the server. gRPC clients and servers can run and talk to each other in a variety of environments - from servers inside Google to your own desktop - and can -be written in any of gRPC's [supported languages](link to list). So, for +be written in any of gRPC's [supported languages](#quickstart). So, for example, you can easily create a gRPC server in Java with clients in Go, Python, or Ruby. In addition, the latest Google APIs will have gRPC versions of their interfaces, letting you easily build Google functionality into From b4da6621dbdcd4025c527b2d7667144d318eba3c Mon Sep 17 00:00:00 2001 From: Lisa Carey Date: Thu, 26 Feb 2015 14:53:08 +0000 Subject: [PATCH 13/17] updated with new example code location and build --- java/README.md | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/java/README.md b/java/README.md index 4c5e4c5902b..9dbe6786336 100644 --- a/java/README.md +++ b/java/README.md @@ -1,17 +1,13 @@ gRPC in 3 minutes (Java) ======================== -BACKGROUND -------------- -For this sample, we've already generated the server and client stubs from [helloworld.proto](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto). - PREREQUISITES ------------- - [Java 8](http://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html) - [Maven 3.2 or later](http://maven.apache.org/download.cgi). - - this is needed to install Netty5, a dependency of gRPC, and to build this sample + - this is needed to install Netty5, a dependency of gRPC INSTALL ------- @@ -29,30 +25,24 @@ $ cd grpc-java $ # follow the instructions in 'How to Build' ``` -3 Clone this repo, if you've not already done so. -```sh -$ cd -$ git clone https://github.com/grpc/grpc-common -$ cd grpc-common/java # switch to this directory -``` - -4 Build the samples -```sh -$ # from this directory -$ mvn package -``` - TRY IT! ------- -- Run the server +Our [Gradle build file](https://github.com/grpc/grpc-java/blob/master/examples/build.gradle) simplifies building and running the examples. + +You can build and run the Hello World server used in [Getting started](https://github.com/grpc/grpc-common) from the `grpc-java` root folder with: + ```sh -$ # from this directory -$ ./run_greeter_server.sh & +$ ./gradlew :grpc-examples:helloWorldServer ``` -- Run the client +and in another terminal window confirm that it receives a message. + ```sh -$ # from this directory -$ ./run_greeter_client.sh +$ ./gradlew :grpc-examples:helloWorldClient ``` + +TUTORIAL +-------- + +You can find a more detailed tutorial in [gRPC Basics: Java](https://github.com/grpc/grpc-common/blob/master/java/javatutorial.md). From f91954393a92e437217b67bda21e7cc7070ec36b Mon Sep 17 00:00:00 2001 From: LisaFC Date: Thu, 26 Feb 2015 15:12:26 +0000 Subject: [PATCH 14/17] fixed a couple of small typos/formatting weirdnesse --- node/route_guide/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/node/route_guide/README.md b/node/route_guide/README.md index 3e0549b19cc..02f312eb24a 100644 --- a/node/route_guide/README.md +++ b/node/route_guide/README.md @@ -27,7 +27,7 @@ Then change your current directory to `grpc-common/node/route_guide`: $ cd grpc-common/node/route_guide ``` -You also should have the relevant tools installed to generate the server and client interface code - if yofu don't already, follow the setup instructions in [the Node.js quick start guide](https://github.com/grpc/grpc-common/tree/master/node). +You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Node.js quick start guide](https://github.com/grpc/grpc-common/tree/master/node). ## Defining the service @@ -90,7 +90,7 @@ message Point { The Node.js library dynamically generates service descriptors and client stub definitions from `.proto` files loaded at runtime. -To load a `.proto` file, simply `require` the gRPC library, then use its `load()` method to load the proto file: +To load a `.proto` file, simply `require` the gRPC library, then use its `load()` method: ```node var grpc = require('grpc'); @@ -99,7 +99,7 @@ var protoDescriptor = grpc.load(__dirname + '/route_guide.proto'); var example = protoDescriptor.examples; ``` -Then, the stub constructor is in the examples namespace (`protoDescriptor.examples.RouteGuide`) and the service descriptor (which is used to create a server) is a property of the stub (`protoDescriptor.examples.RouteGuide.service`); +Once you've done this, the stub constructor is in the `examples` namespace (`protoDescriptor.examples.RouteGuide`) and the service descriptor (which is used to create a server) is a property of the stub (`protoDescriptor.examples.RouteGuide.service`); ## Creating the server @@ -146,7 +146,7 @@ function getFeature(call, callback) { } ``` -The method is passed a call object for the RPC, which has the `Point` parameter as a property, and a callback to be passed the resulting `Feature`. In the method we populate a `Feature` corresponding to the given point and pass it to the callback, with a null first parameter to indicate that there is no error. +The method is passed a call object for the RPC, which has the `Point` parameter as a property, and a callback to which we can pass our returned `Feature`. In the method body we populate a `Feature` corresponding to the given point and pass it to the callback, with a null first parameter to indicate that there is no error. Now let's look at something a bit more complicated - a streaming RPC. `listFeatures` is a server-side streaming RPC, so we need to send back multiple `Feature`s to our client. @@ -174,7 +174,7 @@ function listFeatures(call) { } ``` -As you can see, instead of getting the call object and callback in our method parameters, this time we get a call object that implements the `Writable` interface. In the method, we create as many `Feature` objects as we need to return, writing them to the `call` using its `write()` method. Finally, we call `call.end()` to indicate that we have sent all messages. +As you can see, instead of getting the call object and callback in our method parameters, this time we get a `call` object that implements the `Writable` interface. In the method, we create as many `Feature` objects as we need to return, writing them to the `call` using its `write()` method. Finally, we call `call.end()` to indicate that we have sent all messages. If you look at the client-side streaming method `RecordRoute` you'll see it's quite similar to the unary call, except this time the `call` parameter implements the `Reader` interface. The `call`'s `'data'` event fires every time there is new data, and the `'end'` event fires when all data has been read. Like the unary case, we respond by calling the callback From a320bc549c41fa7dfc920cb855f717fda696b8f0 Mon Sep 17 00:00:00 2001 From: LisaFC Date: Thu, 26 Feb 2015 15:14:31 +0000 Subject: [PATCH 15/17] Added link to new tutorial --- node/README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/node/README.md b/node/README.md index 3889d7355a1..c7a713c22e8 100644 --- a/node/README.md +++ b/node/README.md @@ -26,7 +26,7 @@ INSTALL ``` -Try it! +TRY IT! ------- - Run the server @@ -43,8 +43,13 @@ Try it! $ node ./greeter_client.js ``` -Note +NOTE ---- This directory has a copy of `helloworld.proto` because it currently depends on some Protocol Buffer 2.0 syntax that is deprecated in Protocol Buffer 3.0. + +TUTORIAL +-------- + +You can find a more detailed tutorial in [gRPC Basics: Node.js](https://github.com/grpc/grpc-common/blob/master/node/route_guide/README.md). From 04837cefe8a067a903f42f55b7c6b80019e2ec09 Mon Sep 17 00:00:00 2001 From: nmittler Date: Thu, 26 Feb 2015 07:21:15 -0800 Subject: [PATCH 16/17] Updating Java code in README.md --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8e5d816a121..f3e28f82e22 100644 --- a/README.md +++ b/README.md @@ -223,19 +223,16 @@ has all the protocol buffer code to populate, serialize, and retrieve our ```java public static interface Greeter { - - public void SayHello(ex.grpc.Helloworld.HelloRequest request, - com.google.net.stubby.stub.StreamObserver - responseObserver); + public void sayHello(io.grpc.examples.Helloworld.HelloRequest request, + io.grpc.stub.StreamObserver responseObserver); } ``` - _stub_ classes that clients can use to talk to a `Greeter` server. As you can see, they also implement the `Greeter` interface. ```java -public static class GreeterStub extends - com.google.net.stubby.stub.AbstractStub + public static class GreeterStub extends + io.grpc.stub.AbstractStub implements Greeter { ... } From e79b8d7d3c479ea52334a916fbffdaf8f119def5 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Thu, 26 Feb 2015 08:13:17 -0800 Subject: [PATCH 17/17] Corrects capitalization --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3e28f82e22..4548a896216 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ You can find quick start guides for each language, including installation instru * [C++](https://github.com/grpc/grpc-common/tree/master/cpp) * [Java](https://github.com/grpc/grpc-common/tree/master/java) * [Go](https://github.com/grpc/grpc-common/tree/master/go) -* [ruby](https://github.com/grpc/grpc-common/tree/master/ruby) +* [Ruby](https://github.com/grpc/grpc-common/tree/master/ruby) * [Node.js](https://github.com/grpc/grpc-common/tree/master/node) * [Android Java](https://github.com/grpc/grpc-common/tree/master/java/android) * [Python](https://github.com/grpc/grpc-common/tree/master/python/helloworld)