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  }