Skip to content

Commit cb3c32b

Browse files
committed
added Location integration tests
1 parent a375af0 commit cb3c32b

File tree

5 files changed

+440
-67
lines changed

5 files changed

+440
-67
lines changed

javav2/example_code/location/src/main/java/com/example/location/DescribeKeys.java

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.example.location;
2+
3+
import com.example.location.scenario.LocationActions;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
7+
import software.amazon.awssdk.core.retry.RetryMode;
8+
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
9+
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
10+
import software.amazon.awssdk.regions.Region;
11+
import software.amazon.awssdk.services.location.LocationAsyncClient;
12+
import software.amazon.awssdk.services.location.LocationClient;
13+
import software.amazon.awssdk.services.location.model.DescribeKeyRequest;
14+
import software.amazon.awssdk.services.location.model.DescribeKeyResponse;
15+
import software.amazon.awssdk.services.location.model.ListGeofencesRequest;
16+
import software.amazon.awssdk.services.location.paginators.ListGeofencesPublisher;
17+
18+
import java.time.Duration;
19+
import java.util.concurrent.CompletableFuture;
20+
21+
public class HelloLocation {
22+
23+
private static LocationAsyncClient locationAsyncClient;
24+
private static final Logger logger = LoggerFactory.getLogger(HelloLocation.class);
25+
26+
// This Singleton pattern ensures that only one `LocationClient`
27+
// instance is used throughout the application.
28+
private static LocationAsyncClient getClient() {
29+
if (locationAsyncClient == null) {
30+
SdkAsyncHttpClient httpClient = NettyNioAsyncHttpClient.builder()
31+
.maxConcurrency(100)
32+
.connectionTimeout(Duration.ofSeconds(60))
33+
.readTimeout(Duration.ofSeconds(60))
34+
.writeTimeout(Duration.ofSeconds(60))
35+
.build();
36+
37+
ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder()
38+
.apiCallTimeout(Duration.ofMinutes(2))
39+
.apiCallAttemptTimeout(Duration.ofSeconds(90))
40+
.retryStrategy(RetryMode.STANDARD)
41+
.build();
42+
43+
locationAsyncClient = LocationAsyncClient.builder()
44+
.httpClient(httpClient)
45+
.overrideConfiguration(overrideConfig)
46+
.build();
47+
}
48+
return locationAsyncClient;
49+
}
50+
51+
public static void main(String[] args) {
52+
String colletionName = "ScottCollection30";
53+
listGeofences(colletionName);
54+
}
55+
56+
public static CompletableFuture<Void> listGeofences(String collectionName) {
57+
ListGeofencesRequest geofencesRequest = ListGeofencesRequest.builder()
58+
.collectionName(collectionName)
59+
.build();
60+
61+
ListGeofencesPublisher paginator = getClient().listGeofencesPaginator(geofencesRequest);
62+
CompletableFuture<Void> future = paginator.subscribe(response -> {
63+
response.entries().forEach(geofence ->
64+
logger.info("Geofence ID: " + geofence.geofenceId())
65+
);
66+
});
67+
return future;
68+
}
69+
70+
}

javav2/example_code/location/src/main/java/com/example/location/scenario/LocationActions.java

Lines changed: 198 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
import software.amazon.awssdk.services.location.model.CreateGeofenceCollectionRequest;
1919
import software.amazon.awssdk.services.location.model.CreateGeofenceCollectionResponse;
2020
import software.amazon.awssdk.services.location.model.CreateKeyRequest;
21-
import software.amazon.awssdk.services.location.model.CreateKeyResponse;
2221
import software.amazon.awssdk.services.location.model.CreateMapRequest;
23-
import software.amazon.awssdk.services.location.model.CreateMapResponse;
2422
import software.amazon.awssdk.services.location.model.CreateRouteCalculatorRequest;
2523
import software.amazon.awssdk.services.location.model.CreateRouteCalculatorResponse;
2624
import software.amazon.awssdk.services.location.model.CreateTrackerRequest;
27-
import software.amazon.awssdk.services.location.model.DescribeKeyRequest;
28-
import software.amazon.awssdk.services.location.model.DescribeKeyResponse;
25+
import software.amazon.awssdk.services.location.model.DeleteGeofenceCollectionRequest;
26+
import software.amazon.awssdk.services.location.model.DeleteKeyRequest;
27+
import software.amazon.awssdk.services.location.model.DeleteMapRequest;
28+
import software.amazon.awssdk.services.location.model.DeleteRouteCalculatorRequest;
29+
import software.amazon.awssdk.services.location.model.DeleteTrackerRequest;
2930
import software.amazon.awssdk.services.location.model.DevicePositionUpdate;
3031
import software.amazon.awssdk.services.location.model.GeofenceGeometry;
3132
import software.amazon.awssdk.services.location.model.CreateTrackerResponse;
@@ -75,6 +76,12 @@ private LocationAsyncClient getClient() {
7576
return locationAsyncClient;
7677
}
7778

79+
/**
80+
* Calculates the distance between two locations asynchronously.
81+
*
82+
* @param routeCalcName the name of the route calculator to use
83+
* @return a {@link CompletableFuture} that will complete with a {@link CalculateRouteResponse} containing the distance and estimated duration of the route
84+
*/
7885
public CompletableFuture<CalculateRouteResponse> calcDistanceAsync(String routeCalcName) {
7986
// Define coordinates for Seattle, WA and Vancouver, BC.
8087
List<Double> departurePosition = Arrays.asList(-122.3321, 47.6062);
@@ -174,7 +181,7 @@ public CompletableFuture<GetDevicePositionResponse> getDevicePosition(String tra
174181
* Updates the position of a device in the location tracking system.
175182
*
176183
* @param trackerName the name of the tracker associated with the device
177-
* @param deviceId the unique identifier of the device
184+
* @param deviceId the unique identifier of the device
178185
* @throws RuntimeException if an error occurs while updating the device position
179186
*/
180187
public CompletableFuture<BatchUpdateDevicePositionResponse> updateDevicePosition(String trackerName, String deviceId) {
@@ -213,6 +220,12 @@ public CompletableFuture<BatchUpdateDevicePositionResponse> updateDevicePosition
213220
});
214221
}
215222

223+
/**
224+
* Creates a new tracker resource in your AWS account, which you can use to track the location of devices.
225+
*
226+
* @param trackerName the name of the tracker to be created
227+
* @return a {@link CompletableFuture} that, when completed, will contain the Amazon Resource Name (ARN) of the created tracker
228+
*/
216229
public CompletableFuture<String> createTracker(String trackerName) {
217230
CreateTrackerRequest trackerRequest = CreateTrackerRequest.builder()
218231
.description("Created using the Java V2 SDK")
@@ -243,27 +256,14 @@ public CompletableFuture<String> createTracker(String trackerName) {
243256
*
244257
* @param collectionName the name of the geofence collection to list
245258
*/
246-
public CompletableFuture<Void> listGeofences(String collectionName) {
247-
ListGeofencesRequest geofencesRequest = ListGeofencesRequest.builder()
248-
.collectionName(collectionName)
249-
.build();
250-
251-
ListGeofencesPublisher paginator = locationAsyncClient.listGeofencesPaginator(geofencesRequest);
252-
CompletableFuture<Void> future = paginator.subscribe(response -> {
253-
response.entries().forEach(geofence ->
254-
logger.info("Geofence ID: " + geofence.geofenceId())
255-
);
256-
});
257-
return future;
258-
}
259259

260260
/**
261261
* Adds a new geofence to the specified collection.
262262
*
263263
* @param collectionName the name of the geofence collection to add the geofence to
264264
* @param geoId the unique identifier for the geofence
265265
*/
266-
CompletableFuture<PutGeofenceResponse> putGeofence(String collectionName, String geoId) {
266+
public CompletableFuture<PutGeofenceResponse> putGeofence(String collectionName, String geoId) {
267267
// Define the geofence geometry (polygon)
268268
GeofenceGeometry geofenceGeometry = GeofenceGeometry.builder()
269269
.polygon(List.of(
@@ -283,7 +283,6 @@ CompletableFuture<PutGeofenceResponse> putGeofence(String collectionName, String
283283
.geometry(geofenceGeometry)
284284
.build();
285285

286-
// Call the async API and handle response/exceptions
287286
return locationAsyncClient.putGeofence(geofenceRequest)
288287
.whenComplete((response, exception) -> {
289288
if (response != null) {
@@ -307,7 +306,7 @@ CompletableFuture<PutGeofenceResponse> putGeofence(String collectionName, String
307306
*
308307
* @param collectionName the name of the geofence collection to be created
309308
*/
310-
CompletableFuture<CreateGeofenceCollectionResponse> createGeofenceCollection(String collectionName) {
309+
public CompletableFuture<CreateGeofenceCollectionResponse> createGeofenceCollection(String collectionName) {
311310
CreateGeofenceCollectionRequest collectionRequest = CreateGeofenceCollectionRequest.builder()
312311
.collectionName(collectionName)
313312
.description("Created by using the AWS SDK for Java")
@@ -331,6 +330,14 @@ CompletableFuture<CreateGeofenceCollectionResponse> createGeofenceCollection(Str
331330
});
332331
}
333332

333+
/**
334+
* Creates a new API key with the specified name and restrictions.
335+
*
336+
* @param keyName the name of the API key to be created
337+
* @param mapArn the Amazon Resource Name (ARN) of the map resource to which the API key will be associated
338+
* @return a {@link CompletableFuture} that completes with the Amazon Resource Name (ARN) of the created API key,
339+
* or {@code null} if the operation failed
340+
*/
334341
public CompletableFuture<String> createKey(String keyName, String mapArn) {
335342
ApiKeyRestrictions keyRestrictions = ApiKeyRestrictions.builder()
336343
.allowActions("geo:GetMap*")
@@ -361,6 +368,18 @@ public CompletableFuture<String> createKey(String keyName, String mapArn) {
361368
}
362369
}).thenApply(response -> response != null ? response.keyArn() : null); // Return the key ARN
363370
}
371+
372+
/**
373+
* Creates a new map with the specified name and default configuration.
374+
*
375+
* @param mapName the name of the map to create
376+
* @return a {@link CompletableFuture} that resolves to the Amazon Resource Name (ARN) of the created map, or
377+
* {@code null} if the map creation failed
378+
* @throws CompletionException if an error occurs while creating the map
379+
* - if the requested resource was not found
380+
* - if an unknown error occurred
381+
* - if the map creation failed for any other reason
382+
*/
364383
public CompletableFuture<String> createMap(String mapName) {
365384
MapConfiguration configuration = MapConfiguration.builder()
366385
.style("VectorEsriNavigation")
@@ -389,4 +408,162 @@ public CompletableFuture<String> createMap(String mapName) {
389408
}
390409
}).thenApply(response -> response != null ? response.mapArn() : null); // Return the map ARN
391410
}
411+
412+
/**
413+
* Deletes a geofence collection asynchronously.
414+
*
415+
* @param collectionName the name of the geofence collection to be deleted
416+
* @return a {@link CompletableFuture} that completes when the geofence collection has been deleted
417+
*/
418+
public CompletableFuture<Void> deleteGeofenceCollectionAsync(String collectionName) {
419+
DeleteGeofenceCollectionRequest collectionRequest = DeleteGeofenceCollectionRequest.builder()
420+
.collectionName(collectionName)
421+
.build();
422+
423+
return getClient().deleteGeofenceCollection(collectionRequest)
424+
.whenComplete((response, exception) -> {
425+
if (response != null) {
426+
logger.info("The geofence collection {} was deleted.", collectionName);
427+
} else {
428+
if (exception == null) {
429+
throw new CompletionException("An unknown error occurred while deleting the geofence collection.", null);
430+
}
431+
432+
Throwable cause = exception.getCause();
433+
if (cause instanceof ResourceNotFoundException) {
434+
throw new CompletionException("The requested geofence collection was not found.", cause);
435+
}
436+
437+
throw new CompletionException("Failed to delete geofence collection: " + exception.getMessage(), exception);
438+
}
439+
}).thenApply(response -> null); // Ensures the method returns CompletableFuture<Void>
440+
}
441+
442+
/**
443+
* Deletes the specified key from the key-value store.
444+
*
445+
* @param keyName the name of the key to be deleted
446+
* @return a {@link CompletableFuture} that completes when the key has been deleted
447+
* @throws CompletionException if the key was not found or if an error occurred during the deletion process
448+
*/
449+
public CompletableFuture<Void> deleteKey(String keyName) {
450+
DeleteKeyRequest keyRequest = DeleteKeyRequest.builder()
451+
.keyName(keyName)
452+
.build();
453+
454+
return getClient().deleteKey(keyRequest)
455+
.whenComplete((response, exception) -> {
456+
if (response != null) {
457+
logger.info("The key {} was deleted.", keyName);
458+
} else {
459+
if (exception == null) {
460+
throw new CompletionException("An unknown error occurred while deleting the geofence collection.", null);
461+
}
462+
463+
Throwable cause = exception.getCause();
464+
if (cause instanceof ResourceNotFoundException) {
465+
throw new CompletionException("The key was not found.", cause);
466+
}
467+
468+
throw new CompletionException("Failed to delete key: " + exception.getMessage(), exception);
469+
}
470+
}).thenApply(response -> null); // Ensures the method returns CompletableFuture<Void>
471+
}
472+
473+
/**
474+
* Deletes a map with the specified name.
475+
*
476+
* @param mapName the name of the map to be deleted
477+
* @return a {@link CompletableFuture} that completes when the map deletion is successful, or throws a {@link CompletionException} if an error occurs
478+
*/
479+
public CompletableFuture<Void> deleteMap(String mapName) {
480+
DeleteMapRequest mapRequest = DeleteMapRequest.builder()
481+
.mapName(mapName)
482+
.build();
483+
484+
return getClient().deleteMap(mapRequest)
485+
.whenComplete((response, exception) -> {
486+
if (response != null) {
487+
logger.info("The map {} was deleted.", mapName);
488+
} else {
489+
if (exception == null) {
490+
throw new CompletionException("An unknown error occurred while deleting the map.", null);
491+
}
492+
493+
Throwable cause = exception.getCause();
494+
if (cause instanceof ResourceNotFoundException) {
495+
throw new CompletionException("The map was not found.", cause);
496+
}
497+
498+
throw new CompletionException("Failed to delete map: " + exception.getMessage(), exception);
499+
}
500+
}).thenApply(response -> null);
501+
}
502+
503+
/**
504+
* Deletes a tracker with the specified name.
505+
*
506+
* @param trackerName the name of the tracker to be deleted
507+
* @return a {@link CompletableFuture} that completes when the tracker has been deleted
508+
* @throws CompletionException if an error occurs while deleting the tracker
509+
* - if the tracker was not found, a {@link ResourceNotFoundException} is thrown wrapped in the CompletionException
510+
* - if any other error occurs, a generic CompletionException is thrown with the error message
511+
*/
512+
public CompletableFuture<Void> deleteTracker(String trackerName) {
513+
DeleteTrackerRequest trackerRequest = DeleteTrackerRequest.builder()
514+
.trackerName(trackerName)
515+
.build();
516+
517+
return getClient().deleteTracker(trackerRequest)
518+
.whenComplete((response, exception) -> {
519+
if (response != null) {
520+
logger.info("The tracker {} was deleted.", trackerName);
521+
} else {
522+
if (exception == null) {
523+
throw new CompletionException("An unknown error occurred while deleting the tracker.", null);
524+
}
525+
526+
Throwable cause = exception.getCause();
527+
if (cause instanceof ResourceNotFoundException) {
528+
throw new CompletionException("The tracker was not found.", cause);
529+
}
530+
531+
throw new CompletionException("Failed to delete the tracker: " + exception.getMessage(), exception);
532+
}
533+
}).thenApply(response -> null);
534+
}
535+
536+
/**
537+
* Deletes a route calculator from the system.
538+
*
539+
* @param calcName the name of the route calculator to delete
540+
* @return a {@link CompletableFuture} that completes when the route calculator has been deleted
541+
* @throws CompletionException if an error occurs while deleting the route calculator
542+
* - If the route calculator was not found, a {@link ResourceNotFoundException} will be thrown
543+
* - If any other error occurs, a generic {@link CompletionException} will be thrown
544+
*/
545+
public CompletableFuture<Void> deleteRouteCalculator(String calcName) {
546+
DeleteRouteCalculatorRequest calculatorRequest = DeleteRouteCalculatorRequest.builder()
547+
.calculatorName(calcName)
548+
.build();
549+
550+
return getClient().deleteRouteCalculator(calculatorRequest)
551+
.whenComplete((response, exception) -> {
552+
if (response != null) {
553+
logger.info("The route calculator {} was deleted.", calcName);
554+
} else {
555+
if (exception == null) {
556+
throw new CompletionException("An unknown error occurred while deleting the route calculator.", null);
557+
}
558+
559+
Throwable cause = exception.getCause();
560+
if (cause instanceof ResourceNotFoundException) {
561+
throw new CompletionException("The route calculator was not found.", cause);
562+
}
563+
564+
throw new CompletionException("Failed to delete the route calculator: " + exception.getMessage(), exception);
565+
}
566+
}).thenApply(response -> null);
567+
}
392568
}
569+

0 commit comments

Comments
 (0)