github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/example/routeguide/java/RouteGuideClient.java (about) 1 /* 2 * Copyright 2015 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package example.routeguide.java; 18 19 import com.google.common.annotations.VisibleForTesting; 20 import com.google.protobuf.Message; 21 import io.grpc.ManagedChannel; 22 import io.grpc.ManagedChannelBuilder; 23 import io.grpc.Status; 24 import io.grpc.StatusRuntimeException; 25 import io.grpc.stub.StreamObserver; 26 import java.io.IOException; 27 import java.util.concurrent.CountDownLatch; 28 import java.util.concurrent.TimeUnit; 29 import java.util.Iterator; 30 import java.util.List; 31 import java.util.logging.Level; 32 import java.util.logging.Logger; 33 import java.util.Random; 34 35 import example.routeguide.Feature; 36 import example.routeguide.Point; 37 import example.routeguide.Rectangle; 38 import example.routeguide.RouteGuideGrpc; 39 import example.routeguide.RouteGuideGrpc.RouteGuideBlockingStub; 40 import example.routeguide.RouteGuideGrpc.RouteGuideStub; 41 import example.routeguide.RouteNote; 42 import example.routeguide.RouteSummary; 43 44 /** 45 * Sample client code that makes gRPC calls to the server. 46 */ 47 public class RouteGuideClient { 48 private static final Logger logger = Logger.getLogger(RouteGuideClient.class.getName()); 49 50 private final ManagedChannel channel; 51 private final RouteGuideBlockingStub blockingStub; 52 private final RouteGuideStub asyncStub; 53 54 private Random random = new Random(); 55 private TestHelper testHelper; 56 57 /** Construct client for accessing RouteGuide server at {@code host:port}. */ 58 public RouteGuideClient(String host, int port) { 59 this(ManagedChannelBuilder.forAddress(host, port).usePlaintext()); 60 } 61 62 /** Construct client for accessing RouteGuide server using the existing channel. */ 63 public RouteGuideClient(ManagedChannelBuilder<?> channelBuilder) { 64 channel = channelBuilder.build(); 65 blockingStub = RouteGuideGrpc.newBlockingStub(channel); 66 asyncStub = RouteGuideGrpc.newStub(channel); 67 } 68 69 public void shutdown() throws InterruptedException { 70 channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); 71 } 72 73 /** 74 * Blocking unary call example. Calls getFeature and prints the response. 75 */ 76 public void getFeature(int lat, int lon) { 77 info("*** GetFeature: lat={0} lon={1}", lat, lon); 78 79 Point request = Point.newBuilder().setLatitude(lat).setLongitude(lon).build(); 80 81 Feature feature; 82 try { 83 feature = blockingStub.getFeature(request); 84 if (testHelper != null) { 85 testHelper.onMessage(feature); 86 } 87 } catch (StatusRuntimeException e) { 88 warning("RPC failed: {0}", e.getStatus()); 89 if (testHelper != null) { 90 testHelper.onRpcError(e); 91 } 92 System.exit(1); 93 return; 94 } 95 if (RouteGuideUtil.exists(feature)) { 96 info("Found feature called \"{0}\" at {1}, {2}", 97 feature.getName(), 98 RouteGuideUtil.getLatitude(feature.getLocation()), 99 RouteGuideUtil.getLongitude(feature.getLocation())); 100 } else { 101 info("Found no feature at {0}, {1}", 102 RouteGuideUtil.getLatitude(feature.getLocation()), 103 RouteGuideUtil.getLongitude(feature.getLocation())); 104 } 105 } 106 107 /** 108 * Blocking server-streaming example. Calls listFeatures with a rectangle of interest. Prints each 109 * response feature as it arrives. 110 */ 111 public void listFeatures(int lowLat, int lowLon, int hiLat, int hiLon) { 112 info("*** ListFeatures: lowLat={0} lowLon={1} hiLat={2} hiLon={3}", lowLat, lowLon, hiLat, 113 hiLon); 114 115 Rectangle request = 116 Rectangle.newBuilder() 117 .setLo(Point.newBuilder().setLatitude(lowLat).setLongitude(lowLon).build()) 118 .setHi(Point.newBuilder().setLatitude(hiLat).setLongitude(hiLon).build()).build(); 119 Iterator<Feature> features; 120 try { 121 features = blockingStub.listFeatures(request); 122 for (int i = 1; features.hasNext(); i++) { 123 Feature feature = features.next(); 124 info("Result #" + i + ": {0}", feature); 125 if (testHelper != null) { 126 testHelper.onMessage(feature); 127 } 128 } 129 } catch (StatusRuntimeException e) { 130 warning("RPC failed: {0}", e.getStatus()); 131 if (testHelper != null) { 132 testHelper.onRpcError(e); 133 } 134 System.exit(1); 135 } 136 } 137 138 /** 139 * Async client-streaming example. Sends {@code numPoints} randomly chosen points from {@code 140 * features} with a variable delay in between. Prints the statistics when they are sent from the 141 * server. 142 */ 143 public void recordRoute(List<Feature> features, int numPoints) throws InterruptedException { 144 info("*** RecordRoute"); 145 final CountDownLatch finishLatch = new CountDownLatch(1); 146 StreamObserver<RouteSummary> responseObserver = new StreamObserver<RouteSummary>() { 147 @Override 148 public void onNext(RouteSummary summary) { 149 info("Finished trip with {0} points. Passed {1} features. " 150 + "Travelled {2} meters. It took {3} seconds.", summary.getPointCount(), 151 summary.getFeatureCount(), summary.getDistance(), summary.getElapsedTime()); 152 if (testHelper != null) { 153 testHelper.onMessage(summary); 154 } 155 } 156 157 @Override 158 public void onError(Throwable t) { 159 warning("RecordRoute Failed: {0}", Status.fromThrowable(t)); 160 if (testHelper != null) { 161 testHelper.onRpcError(t); 162 } 163 System.exit(1); 164 finishLatch.countDown(); 165 } 166 167 @Override 168 public void onCompleted() { 169 info("Finished RecordRoute"); 170 finishLatch.countDown(); 171 } 172 }; 173 174 StreamObserver<Point> requestObserver = asyncStub.recordRoute(responseObserver); 175 try { 176 // Send numPoints points randomly selected from the features list. 177 for (int i = 0; i < numPoints; ++i) { 178 int index = random.nextInt(features.size()); 179 Point point = features.get(index).getLocation(); 180 info("Visiting point {0}, {1}", RouteGuideUtil.getLatitude(point), 181 RouteGuideUtil.getLongitude(point)); 182 requestObserver.onNext(point); 183 // Sleep for a bit before sending the next one. 184 Thread.sleep(random.nextInt(1000) + 500); 185 if (finishLatch.getCount() == 0) { 186 // RPC completed or errored before we finished sending. 187 // Sending further requests won't error, but they will just be thrown away. 188 return; 189 } 190 } 191 } catch (RuntimeException e) { 192 // Cancel RPC 193 requestObserver.onError(e); 194 throw e; 195 } 196 // Mark the end of requests 197 requestObserver.onCompleted(); 198 199 // Receiving happens asynchronously 200 if (!finishLatch.await(1, TimeUnit.MINUTES)) { 201 warning("recordRoute can not finish within 1 minutes"); 202 } 203 } 204 205 /** 206 * Bi-directional example, which can only be asynchronous. Send some chat messages, and print any 207 * chat messages that are sent from the server. 208 */ 209 public CountDownLatch routeChat() { 210 info("*** RouteChat"); 211 final CountDownLatch finishLatch = new CountDownLatch(1); 212 StreamObserver<RouteNote> requestObserver = 213 asyncStub.routeChat(new StreamObserver<RouteNote>() { 214 @Override 215 public void onNext(RouteNote note) { 216 info("Got message \"{0}\" at {1}, {2}", note.getMessage(), note.getLocation() 217 .getLatitude(), note.getLocation().getLongitude()); 218 if (testHelper != null) { 219 testHelper.onMessage(note); 220 } 221 } 222 223 @Override 224 public void onError(Throwable t) { 225 warning("RouteChat Failed: {0}", Status.fromThrowable(t)); 226 if (testHelper != null) { 227 testHelper.onRpcError(t); 228 } 229 System.exit(1); 230 finishLatch.countDown(); 231 } 232 233 @Override 234 public void onCompleted() { 235 info("Finished RouteChat"); 236 finishLatch.countDown(); 237 } 238 }); 239 240 try { 241 RouteNote[] requests = 242 {newNote("First message", 0, 0), newNote("Second message", 0, 1), 243 newNote("Third message", 1, 0), newNote("Fourth message", 1, 1)}; 244 245 for (RouteNote request : requests) { 246 info("Sending message \"{0}\" at {1}, {2}", request.getMessage(), request.getLocation() 247 .getLatitude(), request.getLocation().getLongitude()); 248 requestObserver.onNext(request); 249 } 250 } catch (RuntimeException e) { 251 // Cancel RPC 252 requestObserver.onError(e); 253 throw e; 254 } 255 // Mark the end of requests 256 requestObserver.onCompleted(); 257 258 // return the latch while receiving happens asynchronously 259 return finishLatch; 260 } 261 262 /** Issues several different requests and then exits. */ 263 public static void main(String[] args) throws InterruptedException { 264 List<Feature> features; 265 try { 266 features = RouteGuideUtil.parseFeatures(RouteGuideUtil.getDefaultFeaturesFile()); 267 } catch (IOException ex) { 268 ex.printStackTrace(); 269 return; 270 } 271 272 int port = 50074; 273 String serverPort = System.getenv("SERVER_PORT"); 274 if (serverPort != null && !serverPort.isEmpty()) { 275 port = Integer.parseInt(serverPort); 276 } 277 278 RouteGuideClient client = new RouteGuideClient("localhost", port); 279 try { 280 // Looking for a valid feature 281 client.getFeature(409146138, -746188906); 282 283 // Feature missing. 284 client.getFeature(0, 0); 285 286 // Looking for features between 40, -75 and 42, -73. 287 client.listFeatures(400000000, -750000000, 420000000, -730000000); 288 289 // Record a few randomly selected points from the features file. 290 client.recordRoute(features, 10); 291 292 // Send and receive some notes. 293 CountDownLatch finishLatch = client.routeChat(); 294 295 if (!finishLatch.await(1, TimeUnit.MINUTES)) { 296 client.warning("routeChat can not finish within 1 minutes"); 297 } 298 } finally { 299 client.shutdown(); 300 } 301 } 302 303 private void info(String msg, Object... params) { 304 logger.log(Level.INFO, msg, params); 305 } 306 307 private void warning(String msg, Object... params) { 308 logger.log(Level.WARNING, msg, params); 309 } 310 311 private RouteNote newNote(String message, int lat, int lon) { 312 return RouteNote.newBuilder().setMessage(message) 313 .setLocation(Point.newBuilder().setLatitude(lat).setLongitude(lon).build()).build(); 314 } 315 316 /** 317 * Only used for unit test, as we do not want to introduce randomness in unit test. 318 */ 319 @VisibleForTesting 320 void setRandom(Random random) { 321 this.random = random; 322 } 323 324 /** 325 * Only used for helping unit test. 326 */ 327 @VisibleForTesting 328 interface TestHelper { 329 /** 330 * Used for verify/inspect message received from server. 331 */ 332 void onMessage(Message message); 333 334 /** 335 * Used for verify/inspect error received from server. 336 */ 337 void onRpcError(Throwable exception); 338 } 339 340 @VisibleForTesting 341 void setTestHelper(TestHelper testHelper) { 342 this.testHelper = testHelper; 343 } 344 }