This quickstart shows how to solve the VRP example by sending an RPC request to the Cloud Fleet Routing service using the API Client Library for Java. This example uses the Google Geo Distance Matrix.
Before you begin
Follow these instructions to set up your Java development environment.
Download the Cloud Fleet Routing API Client Library
To send requests to the API by using the API Client Library for Java, you need to download it from the Cloud Fleet Routing's Cloud Storage bucket. To do so, enter the following command:
gcloud storage cp gs://api-client-staging/cloudoptimization-java-v1-20211110.tar.gz SAVE_TO_LOCATION
Install the Cloud Fleet Routing API Client Library
After you have downloaded the API Client Library tarball, install it with the following command:
tar -xzpf cloudoptimization-java-v1-20211110.tar.gz -C /path/to/library
cd /path/to/library
./gradlew clean install
Java code to send a synchronous request
The following code sends the protobuf request in the file request.textproto
to the Cloud Fleet Routing synchronous API (optimizeTours).
package com.google.cloud; import com.google.cloud.optimization.v1.FleetRoutingClient; import com.google.cloud.optimization.v1.OptimizeToursRequest; import com.google.cloud.optimization.v1.OptimizeToursResponse; import com.google.protobuf.Duration; import com.google.protobuf.TextFormat; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; /** * This is an example to send a request to Cloud Fleet Routing synchronous API via Java API Client. */ public class App { private static int TIMEOUT_SECONDS = 100; private static final String PROJECT_PARENT = "projects/{YOUR_GCP_PROJECT_ID}"; private static final String MODEL_PATH = "request.textproto"; public static void main(String[] args) throws Exception { InputStream modelInputstream = new FileInputStream(MODEL_PATH); Reader modelInputStreamReader = new InputStreamReader(modelInputstream); OptimizeToursRequest.Builder requestBuilder = OptimizeToursRequest.newBuilder() .setTimeout(Duration.newBuilder().setSeconds(TIMEOUT_SECONDS).build()) .setParent(PROJECT_PARENT); TextFormat.getParser().merge(modelInputStreamReader, requestBuilder); FleetRoutingClient fleetRoutingClient = FleetRoutingClient.create(); OptimizeToursResponse response = fleetRoutingClient.optimizeTours(requestBuilder.build()); System.out.println(response.toString()); } }
# proto-file: google3/google/cloud/optimization/v1/fleet_routing.proto # proto-message: OptimizeToursRequest model { shipments { pickups { arrival_location { latitude: 48.874507 longitude: 2.30361 } time_windows { start_time { seconds: 1000 } end_time { seconds: 2000 } } duration { seconds: 150 } } deliveries { arrival_location { latitude: 48.880942 longitude: 2.323866 } time_windows { start_time { seconds: 3000 } end_time { seconds: 4000 } } duration: { seconds: 250 } } load_demands { key: "weight" value: { amount: 10 } } } shipments { pickups { arrival_location { latitude: 48.880943 longitude: 2.323867 } time_windows { start_time { seconds: 1001 } end_time { seconds: 2001 } } duration { seconds: 151 } } deliveries { arrival_location { latitude: 48.880940 longitude: 2.323844 } time_windows { start_time { seconds: 3001 } end_time { seconds: 4001 } } duration { seconds: 251 } } load_demands { key: "weight" value: { amount: 20 } } } vehicles { start_location { latitude: 48.863102 longitude: 2.341204 } end_location { latitude: 48.863110 longitude: 2.341205 } load_limits { key: "weight" value: { max_load: 50 } } } vehicles { start_location { latitude: 48.863112 longitude: 2.341214 } end_location { latitude: 48.863120 longitude: 2.341215 } load_limits { key: "weight" value: { max_load: 60 } } } }
Send a synchronous request with a long timeout
When a request might take a longer time to solve, we recommend using the asynchronous API. However, if you prefer, you can still send a synchronous request with a long timeout.
If you run the client on a Compute Engine virtual machine (VM), the firewall will end
connections that are idle for a long time.
The keep-alive setting enforces the client to ping the API server to keep the connection alive.
We recommend a five-minutes keep-alive setting, but you can adjust this value based on your use case.
As an example, the following code sends the same protobuf request in the request.textproto
file
to the Cloud Fleet Routing Synchronous API while setting up the checks to keep the connection alive.
package com.google.cloud; import com.google.cloud.optimization.v1.FleetRoutingSettings; import com.google.cloud.optimization.v1.FleetRoutingClient; import com.google.cloud.optimization.v1.OptimizeToursRequest; import com.google.cloud.optimization.v1.OptimizeToursResponse; import com.google.protobuf.Duration; import com.google.protobuf.TextFormat; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; /** * This is an example to send a request to Cloud Fleet Routing synchronous API via Java API Client. */ public class App { private static int TIMEOUT_SECONDS = 100; private static final String PROJECT_PARENT = "projects/{YOUR_GCP_PROJECT_ID}"; private static final String MODEL_PATH = "request.textproto"; public static void main(String[] args) throws Exception { InputStream modelInputstream = new FileInputStream(MODEL_PATH); Reader modelInputStreamReader = new InputStreamReader(modelInputstream); OptimizeToursRequest.Builder requestBuilder = OptimizeToursRequest.newBuilder() .setTimeout(Duration.newBuilder().setSeconds(TIMEOUT_SECONDS).build()) .setParent(PROJECT_PARENT); TextFormat.getParser().merge(modelInputStreamReader, requestBuilder); // Checks the gRPC connection every 5 mins and keeps it alive. FleetRoutingClient fleetRoutingClientClient = FleetRoutingClient.create( FleetRoutingSettings .newBuilder() .setTransportChannelProvider( FleetRoutingSettings. defaultGrpcTransportProviderBuilder() .setKeepAliveTime( org.threeten.bp.Duration.ofSeconds(300)).build()).build()); OptimizeToursResponse response = fleetRoutingClientClient.optimizeTours(requestBuilder.build()); System.out.println(response.toString()); } }
# proto-file: google3/google/cloud/optimization/v1/fleet_routing.proto # proto-message: OptimizeToursRequest model { shipments { pickups { arrival_location { latitude: 48.874507 longitude: 2.30361 } time_windows { start_time { seconds: 1000 } end_time { seconds: 2000 } } duration { seconds: 150 } } deliveries { arrival_location { latitude: 48.880942 longitude: 2.323866 } time_windows { start_time { seconds: 3000 } end_time { seconds: 4000 } } duration: { seconds: 250 } } load_demands { key: "weight" value: { amount: 10 } } } shipments { pickups { arrival_location { latitude: 48.880943 longitude: 2.323867 } time_windows { start_time { seconds: 1001 } end_time { seconds: 2001 } } duration { seconds: 151 } } deliveries { arrival_location { latitude: 48.880940 longitude: 2.323844 } time_windows { start_time { seconds: 3001 } end_time { seconds: 4001 } } duration { seconds: 251 } } load_demands { key: "weight" value: { amount: 20 } } } vehicles { start_location { latitude: 48.863102 longitude: 2.341204 } end_location { latitude: 48.863110 longitude: 2.341205 } load_limits { key: "weight" value: { max_load: 50 } } } vehicles { start_location { latitude: 48.863112 longitude: 2.341214 } end_location { latitude: 48.863120 longitude: 2.341215 } load_limits { key: "weight" value: { max_load: 60 } } } }
Run the code
To run the Java Code:
Create a Maven project by running the following command:
- Add the following dependency in
POM.xml
under yourfleet-routing
directory: - Copy the preceding Java code into a file named
fleet-routing/src/main/java/com/google/cloud/App.java
, and save the textproto file asrequest.textproto
in yourfleet-routing
directory. - Move the service account key file you downloaded when you
created a service account to your
fleet-routing
directory, and rename the key file tomy_keyfile.json
. - In the command line, run the following command:
export GOOGLE_APPLICATION_CREDENTIALS="[PATH to my_keyfile.json]".
- Replace the value of
PROJECT_PARENT
with your Google Cloud project. - Replace the value of
MODEL_PATH
with the path of your request.textproto file. - At the command line, navigate to your fleet-routing directory and enter the following commands:
mvn archetype:generate -DgroupId=com.google.cloud -DartifactId=fleet-routing -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
<dependency> <groupId>com.google.cloud</groupId> <artifactId>gapic-google-cloud-optimization-v1-java</artifactId> <version>0.0.0-SNAPSHOT</version> </dependency>
mvn package
mvn exec:java -D exec.mainClass=com.google.cloud.App
Response
The following is the response to the request.
routes { vehicle_start_time { seconds: 35 } vehicle_end_time { seconds: 4302 } visits { is_pickup: true start_time { seconds: 1000 } demands { type: "weight" value: 10 } detour { } arrival_loads { type: "weight" } load_demands { key: "weight" value { amount: 10 } } } visits { shipment_index: 1 is_pickup: true start_time { seconds: 1660 } demands { type: "weight" value: 20 } detour { seconds: 756 } arrival_loads { type: "weight" value: 10 } load_demands { key: "weight" value { amount: 20 } } } visits { start_time { seconds: 3000 } demands { type: "weight" value: -10 } detour { seconds: 1340 } arrival_loads { type: "weight" value: 30 } load_demands { key: "weight" value { amount: -10 } } } visits { shipment_index: 1 start_time { seconds: 3250 } demands { type: "weight" value: -20 } detour { seconds: 1439 } arrival_loads { type: "weight" value: 20 } load_demands { key: "weight" value { amount: -20 } } } transitions { travel_duration { seconds: 965 } travel_distance_meters: 4244.0 total_duration { seconds: 965 } start_time { seconds: 35 } vehicle_loads { key: "weight" value { } } } transitions { travel_duration { seconds: 510 } travel_distance_meters: 2479.0 total_duration { seconds: 510 } start_time { seconds: 1150 } vehicle_loads { key: "weight" value { amount: 10 } } } transitions { travel_duration { } wait_duration { seconds: 1189 } total_duration { seconds: 1189 } start_time { seconds: 1811 } vehicle_loads { key: "weight" value { amount: 30 } } } transitions { travel_duration { } total_duration { } start_time { seconds: 3250 } vehicle_loads { key: "weight" value { amount: 20 } } } transitions { travel_duration { seconds: 801 } travel_distance_meters: 3111.0 total_duration { seconds: 801 } start_time { seconds: 3501 } vehicle_loads { key: "weight" value { } } } metrics { performed_shipment_count: 2 travel_duration { seconds: 2276 } wait_duration { seconds: 1189 } delay_duration { } break_duration { } visit_duration { seconds: 802 } total_duration { seconds: 4267 } travel_distance_meters: 9834.0 max_loads { key: "weight" value { amount: 30 } } } end_loads { type: "weight" } travel_steps { duration { seconds: 965 } distance_meters: 4244.0 } travel_steps { duration { seconds: 510 } distance_meters: 2479.0 } travel_steps { duration { } } travel_steps { duration { } } travel_steps { duration { seconds: 801 } distance_meters: 3111.0 } vehicle_detour { seconds: 4267 } } routes { vehicle_index: 1 } metrics { aggregated_route_metrics { performed_shipment_count: 2 travel_duration { seconds: 2276 } wait_duration { seconds: 1189 } delay_duration { } break_duration { } visit_duration { seconds: 802 } total_duration { seconds: 4267 } travel_distance_meters: 9834.0 max_loads { key: "weight" value { amount: 30 } } } used_vehicle_count: 1 earliest_vehicle_start_time { seconds: 35 } latest_vehicle_end_time { seconds: 4302 } }
For a description of the response, see Response to the request in the VRP example page.
Java code to send an asynchronous request
The following code sends the protobuf request in the file request.textproto
to the Cloud Fleet Routing Asynchronous API.
package com.google.cloud; import com.google.api.gax.longrunning.OperationFuture; import com.google.cloud.optimization.v1.AsyncModelMetadata; import com.google.cloud.optimization.v1.BatchOptimizeToursRequest; import com.google.cloud.optimization.v1.BatchOptimizeToursResponse; import com.google.cloud.optimization.v1.FleetRoutingClient; import com.google.protobuf.TextFormat; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; /** * This is an example to send a request to Cloud Fleet Routing asynchronous API via Java API Client. */ public class App { private static final String PROJECT_PARENT = "projects/{YOUR_GCP_PROJECT_ID}"; private static final String REQUEST_PATH = "request.textproto"; public static void main(String[] args) throws Exception { InputStream modelInputstream = new FileInputStream(REQUEST_PATH); Reader modelInputStreamReader = new InputStreamReader(modelInputstream); BatchOptimizeToursRequest.Builder requestBuilder = BatchOptimizeToursRequest.newBuilder().setParent(PROJECT_PARENT); TextFormat.getParser().merge(modelInputStreamReader, requestBuilder); FleetRoutingClient fleetRoutingClient = FleetRoutingClient.create(); OperationFuture<BatchOptimizeToursResponse, AsyncModelMetadata> response = fleetRoutingClient.batchOptimizeToursAsync(requestBuilder.build()); // Block to wait for the job to finish. response.getPollingFuture().get(); if (response.getMetadata().get().getState() == AsyncModelMetadata.State.SUCCEEDED) { // Code to do your stuff } else { System.out.println("Job failed with message:" + response.getPollingFuture().get().getErrorMessage()); } } }
# proto-file: google3/google/cloud/optimization/v1/fleet_routing.proto # proto-message: BatchOptimizeToursRequest model_configs { input_config { gcs_source: { uri: "${REQUEST_MODEL_GCS_PATH}" } data_format: JSON } output_config: { gcs_destination { uri: "${MODEL_SOLUTION_GCS_PATH}" } data_format: JSON } } model_configs { input_config { gcs_source: { uri: "${REQUEST_MODEL_GCS_PATH}" } data_format: JSON } output_config: { gcs_destination { uri: "${MODEL_SOLUTION_GCS_PATH}" } data_format: JSON } } model_configs { input_config { gcs_source: { uri: "${REQUEST_MODEL_GCS_PATH}" } data_format: JSON } output_config: { gcs_destination { uri: "${MODEL_SOLUTION_GCS_PATH}" } data_format: JSON } }
{ "parent":"${YOUR_GCP_PROJECT_ID}", "allowLargeDeadlineDespiteInterruptionRisk":true, "model":{ "shipments":[ { "deliveries":[ { "arrivalLocation":{ "latitude":48.880941999999997, "longitude":2.3238660000000002 }, "duration":"250s", "timeWindows":[ { "endTime":"1970-01-01T01:06:40Z", "startTime":"1970-01-01T00:50:00Z" } ] } ], "loadDemands": { "weight": { "amount": "10" } }, "pickups":[ { "arrivalLocation":{ "latitude":48.874507000000001, "longitude":2.3036099999999999 }, "duration":"150s", "timeWindows":[ { "endTime":"1970-01-01T00:33:20Z", "startTime":"1970-01-01T00:16:40Z" } ] } ] }, { "deliveries":[ { "arrivalLocation":{ "latitude":48.880940000000002, "longitude":2.3238439999999998 }, "duration":"251s", "timeWindows":[ { "endTime":"1970-01-01T01:06:41Z", "startTime":"1970-01-01T00:50:01Z" } ] } ], "loadDemands": { "weight": { "amount": "20" } }, "pickups":[ { "arrivalLocation":{ "latitude":48.880943000000002, "longitude":2.3238669999999999 }, "duration":"151s", "timeWindows":[ { "endTime":"1970-01-01T00:33:21Z", "startTime":"1970-01-01T00:16:41Z" } ] } ] } ], "vehicles":[ { "loadLimits": { "weight": { "maxLoad": 50 } }, "endLocation":{ "latitude":48.863109999999999, "longitude":2.341205 }, "startLocation":{ "latitude":48.863101999999998, "longitude":2.3412039999999998 } }, { "loadLimits": { "weight": { "maxLoad": 60 } }, "endLocation":{ "latitude":48.863120000000002, "longitude":2.341215 }, "startLocation":{ "latitude":48.863112000000001, "longitude":2.3412139999999999 } } ] } }
Run the code
To run the Java code:
Create a Maven project by running the following command:
- Add the following dependency in
POM.xml
underfleet-routing/
: - Copy the preceding Java code into a file named
fleet-routing/src/main/java/com/google/cloud/App.java
, and save the textproto file asrequest.textproto
in yourfleet-routing
directory. - Move the service account key file you downloaded when you
created a service account to your
fleet-routing
directory, and rename your key file tomy_keyfile.json
. - Create three files on your Cloud Storage bucket with the content of the
request_model.json
. In this file, replace the${YOUR_GCP_PROJECT_ID}
with your Google Cloud project ID and replace the${YOUR_GCP_API_KEY}
with your Google Cloud project API key generated in the "Before you begin" section. - In the
request.textproto
file, replace${REQUEST_MODEL_GCS_PATH}
with the paths of the files you just created on your Cloud Storage bucket. Replace the${MODEL_SOLUTION_GCS_PATH}
with the three different paths for the model solutions. - In the command line, run the following command:
export GOOGLE_APPLICATION_CREDENTIALS="[PATH to my_keyfile.json]".
- Replace the value of
PROJECT_PARENT
with your Google Cloud project ID. - Replace the value of
MODEL_PATH
with the path of yourrequest.textproto
file. - At the command line, navigate to your
fleet-routing
directory and enter the following commands:
mvn archetype:generate -DgroupId=com.google.cloud -DartifactId=fleet-routing -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
<dependency> <groupId>com.google.cloud</groupId> <artifactId>gapic-google-cloud-optimization-v1-java</artifactId> <version>0.0.0-SNAPSHOT</version> </dependency>
mvn package
mvn exec:java -D exec.mainClass=com.google.cloud.App
Response
After a couple of seconds, check your files in ${MODEL_SOLUTION_GCS_PATH}
.
Each file should have the following response.
{ "metrics": { "aggregatedRouteMetrics": { "breakDuration": "0s", "delayDuration": "0s", "maxLoads": { "weight": { "amount": "30" } }, "performedShipmentCount": 2, "totalDuration": "4267s", "travelDistanceMeters": 9834, "travelDuration": "2276s", "visitDuration": "802s", "waitDuration": "1189s" }, "earliestVehicleStartTime": "1970-01-01T00:00:35Z", "latestVehicleEndTime": "1970-01-01T01:11:42Z", "usedVehicleCount": 1 }, "routes": [ { "endLoads": [ { "type": "weight" } ], "metrics": { "breakDuration": "0s", "delayDuration": "0s", "maxLoads": { "weight": { "amount": "30" } }, "performedShipmentCount": 2, "totalDuration": "4267s", "travelDistanceMeters": 9834, "travelDuration": "2276s", "visitDuration": "802s", "waitDuration": "1189s" }, "transitions": [ { "startTime": "1970-01-01T00:00:35Z", "totalDuration": "965s", "travelDistanceMeters": 4244, "travelDuration": "965s", "vehicleLoads": { "weight": {} } }, { "startTime": "1970-01-01T00:19:10Z", "totalDuration": "510s", "travelDistanceMeters": 2479, "travelDuration": "510s", "vehicleLoads": { "weight": { "amount": "10" } } }, { "startTime": "1970-01-01T00:30:11Z", "totalDuration": "1189s", "travelDuration": "0s", "vehicleLoads": { "weight": { "amount": "30" } }, "waitDuration": "1189s" }, { "startTime": "1970-01-01T00:54:10Z", "totalDuration": "0s", "travelDuration": "0s", "vehicleLoads": { "weight": { "amount": "20" } } }, { "startTime": "1970-01-01T00:58:21Z", "totalDuration": "801s", "travelDistanceMeters": 3111, "travelDuration": "801s", "vehicleLoads": { "weight": {} } } ], "travelSteps": [ { "distanceMeters": 4244, "duration": "965s" }, { "distanceMeters": 2479, "duration": "510s" }, { "duration": "0s" }, { "duration": "0s" }, { "distanceMeters": 3111, "duration": "801s" } ], "vehicleDetour": "4267s", "vehicleEndTime": "1970-01-01T01:11:42Z", "vehicleStartTime": "1970-01-01T00:00:35Z", "visits": [ { "arrivalLoads": [ { "type": "weight" } ], "demands": [ { "type": "weight", "value": "10" } ], "detour": "0s", "isPickup": true, "loadDemands": { "weight": { "amount": "10" } }, "startTime": "1970-01-01T00:16:40Z" }, { "arrivalLoads": [ { "type": "weight", "value": "10" } ], "demands": [ { "type": "weight", "value": "20" } ], "detour": "756s", "isPickup": true, "loadDemands": { "weight": { "amount": "20" } }, "shipmentIndex": 1, "startTime": "1970-01-01T00:27:40Z" }, { "arrivalLoads": [ { "type": "weight", "value": "30" } ], "demands": [ { "type": "weight", "value": "-10" } ], "detour": "1340s", "loadDemands": { "weight": { "amount": "-10" } }, "startTime": "1970-01-01T00:50:00Z" }, { "arrivalLoads": [ { "type": "weight", "value": "20" } ], "demands": [ { "type": "weight", "value": "-20" } ], "detour": "1439s", "loadDemands": { "weight": { "amount": "-20" } }, "shipmentIndex": 1, "startTime": "1970-01-01T00:54:10Z" } ] }, { "vehicleIndex": 1 } ] }
For a description of the response, see Response to the request in the VRP example page.