55
66import org .slf4j .Logger ;
77import org .slf4j .LoggerFactory ;
8+ import software .amazon .awssdk .services .geoplaces .GeoPlacesAsyncClient ;
89import software .amazon .awssdk .core .client .config .ClientOverrideConfiguration ;
910import software .amazon .awssdk .core .retry .RetryMode ;
1011import software .amazon .awssdk .http .async .SdkAsyncHttpClient ;
1112import software .amazon .awssdk .http .nio .netty .NettyNioAsyncHttpClient ;
13+ import software .amazon .awssdk .services .geoplaces .model .GetPlaceRequest ;
14+ import software .amazon .awssdk .services .geoplaces .model .ReverseGeocodeRequest ;
15+ import software .amazon .awssdk .services .geoplaces .model .ReverseGeocodeResponse ;
16+ import software .amazon .awssdk .services .geoplaces .model .SearchNearbyRequest ;
17+ import software .amazon .awssdk .services .geoplaces .model .SearchNearbyResponse ;
18+ import software .amazon .awssdk .services .geoplaces .model .SearchTextRequest ;
19+ import software .amazon .awssdk .services .geoplaces .model .SearchTextResponse ;
1220import software .amazon .awssdk .services .location .LocationAsyncClient ;
1321import software .amazon .awssdk .services .location .model .ApiKeyRestrictions ;
1422import software .amazon .awssdk .services .location .model .BatchUpdateDevicePositionRequest ;
4553import software .amazon .awssdk .services .location .paginators .ListGeofencesPublisher ;
4654import java .time .Duration ;
4755import java .time .Instant ;
56+ import java .util .ArrayList ;
4857import java .util .Arrays ;
4958import java .util .List ;
5059import java .util .concurrent .CompletableFuture ;
5160import java .util .concurrent .CompletionException ;
5261
62+ // snippet-start:[location.java2.actions.main]
5363public class LocationActions {
5464
5565 private static LocationAsyncClient locationAsyncClient ;
66+
67+ private static GeoPlacesAsyncClient geoPlacesAsyncClient ;
5668 private static final Logger logger = LoggerFactory .getLogger (LocationActions .class );
5769
5870 // This Singleton pattern ensures that only one `LocationClient`
@@ -80,6 +92,140 @@ private LocationAsyncClient getClient() {
8092 return locationAsyncClient ;
8193 }
8294
95+ private static GeoPlacesAsyncClient getGeoPlacesClient () {
96+ if (geoPlacesAsyncClient == null ) {
97+ SdkAsyncHttpClient httpClient = NettyNioAsyncHttpClient .builder ()
98+ .maxConcurrency (100 )
99+ .connectionTimeout (Duration .ofSeconds (60 ))
100+ .readTimeout (Duration .ofSeconds (60 ))
101+ .writeTimeout (Duration .ofSeconds (60 ))
102+ .build ();
103+
104+ ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration .builder ()
105+ .apiCallTimeout (Duration .ofMinutes (2 ))
106+ .apiCallAttemptTimeout (Duration .ofSeconds (90 ))
107+ .retryStrategy (RetryMode .STANDARD )
108+ .build ();
109+
110+ geoPlacesAsyncClient = GeoPlacesAsyncClient .builder ()
111+ .httpClient (httpClient )
112+ .overrideConfiguration (overrideConfig )
113+ .build ();
114+ }
115+ return geoPlacesAsyncClient ;
116+ }
117+
118+ public void searchNearBy () {
119+ double latitude = 37.7749 ; // San Francisco
120+ double longitude = -122.4194 ;
121+ List <Double > queryPosition = List .of (longitude , latitude );
122+
123+ // Set up the request for searching nearby places
124+ SearchNearbyRequest request = SearchNearbyRequest .builder ()
125+ .queryPosition (queryPosition ) // Set the position (latitude, longitude)
126+ .queryRadius (1000L ) // Radius in meters (1000 meters = 1 km)
127+ .build ();
128+
129+ CompletableFuture <SearchNearbyResponse > futureResponse = getGeoPlacesClient ().searchNearby (request );
130+
131+ futureResponse .whenComplete ((response , exception ) -> {
132+ if (exception != null ) {
133+ throw new RuntimeException ("Error performing nearby search" , exception );
134+ }
135+
136+ // Process the response and print the results
137+ response .resultItems ().forEach (result -> {
138+ System .out .println ("Place Name: " + result .placeType ().name ());
139+ System .out .println ("Address: " + result .address ().label ());
140+ System .out .println ("Distance: " + result .distance () + " meters" );
141+ System .out .println ("-------------------------" );
142+ });
143+ }).join (); // Ensures the main thread waits for completion
144+ }
145+
146+
147+ public void searchText (String searchQuery ) {
148+ double latitude = 37.7749 ; // San Francisco
149+ double longitude = -122.4194 ;
150+ List <Double > queryPosition = List .of (longitude , latitude );
151+
152+ SearchTextRequest request = SearchTextRequest .builder ()
153+ .queryText (searchQuery ) // Search for "coffee shop"
154+ .biasPosition (queryPosition )
155+ .build ();
156+
157+ // Asynchronous search request
158+ CompletableFuture <SearchTextResponse > futureResponse = getGeoPlacesClient ().searchText (request );
159+
160+ futureResponse .whenComplete ((response , exception ) -> {
161+ if (exception != null ) {
162+ throw new RuntimeException ("Error performing place search" , exception );
163+ }
164+
165+ // Process the response and fetch detailed information about the place
166+ response .resultItems ().stream ().findFirst ().ifPresent (result -> {
167+ String placeId = result .placeId (); // Get Place ID
168+ System .out .println ("Found Place with id: " + placeId );
169+
170+ // Fetch detailed info using getPlace()
171+ GetPlaceRequest getPlaceRequest = GetPlaceRequest .builder ()
172+ .placeId (placeId )
173+ .build ();
174+
175+ getGeoPlacesClient ().getPlace (getPlaceRequest )
176+ .whenComplete ((placeResponse , placeException ) -> {
177+ if (placeException != null ) {
178+ throw new CompletionException ("Error fetching place details" , placeException );
179+ }
180+
181+ // Print detailed place information
182+ System .out .println ("Detailed Place Information:" );
183+ System .out .println ("Name: " + placeResponse .placeType ().name ());
184+ System .out .println ("Address: " + placeResponse .address ().label ());
185+
186+ // Print each food type (if any)
187+ if (placeResponse .foodTypes () != null && !placeResponse .foodTypes ().isEmpty ()) {
188+ System .out .println ("Food Types:" );
189+ placeResponse .foodTypes ().forEach (foodType -> {
190+ System .out .println (" - " + foodType );
191+ });
192+ } else {
193+ System .out .println ("No food types available." );
194+ }
195+
196+ System .out .println ("-------------------------" );
197+ }).join (); // Waits for getPlace response
198+ });
199+ }).join (); // Ensures main thread waits for completion
200+ }
201+
202+
203+ public void reverseGeocode () {
204+ double latitude = 37.7749 ; // San Francisco
205+ double longitude = -122.4194 ;
206+ System .out .println ("Use latitude 37.7749 and longitude -122.4194" );
207+
208+ // AWS expects [longitude, latitude]
209+ List <Double > queryPosition = List .of (longitude , latitude );
210+ ReverseGeocodeRequest request = ReverseGeocodeRequest .builder ()
211+ .queryPosition (queryPosition )
212+ .build ();
213+ CompletableFuture <ReverseGeocodeResponse > futureResponse =
214+ getGeoPlacesClient ().reverseGeocode (request );
215+
216+ futureResponse .whenComplete ((response , exception ) -> {
217+ if (exception != null ) {
218+ throw new CompletionException ("Error performing reverse geocoding" , exception );
219+ }
220+
221+ response .resultItems ().forEach (result ->
222+ System .out .println ("The address is: " + result .address ().label ())
223+ );
224+ }).join (); // Ensures main thread waits for completion
225+ }
226+
227+
228+ // snippet-start:[location.java2.calc.distance.main]
83229 /**
84230 * Calculates the distance between two locations asynchronously.
85231 *
@@ -103,7 +249,7 @@ public CompletableFuture<CalculateRouteResponse> calcDistanceAsync(String routeC
103249 .whenComplete ((response , exception ) -> {
104250 if (response != null ) {
105251 logger .info ("Total Distance: " + response .summary ().distance () + " km" );
106- logger .info ("Estimated Duration: " + response .summary ().durationSeconds () / 60 + " minutes" );
252+ logger .info ("Estimated Duration by car is : " + response .summary ().durationSeconds () / 60 + " minutes" );
107253 } else {
108254 if (exception == null ) {
109255 throw new CompletionException ("An unknown error occurred while calculating route." , null );
@@ -118,7 +264,9 @@ public CompletableFuture<CalculateRouteResponse> calcDistanceAsync(String routeC
118264 }
119265 });
120266 }
267+ // snippet-end:[location.java2.calc.distance.main]
121268
269+ // snippet-start:[location.java2.create.calculator.main]
122270 /**
123271 * Creates a new route calculator with the specified name and data source.
124272 *
@@ -148,7 +296,9 @@ public CompletableFuture<CreateRouteCalculatorResponse> createRouteCalculator(St
148296 }
149297 });
150298 }
299+ // snippet-end:[location.java2.create.calculator.main]
151300
301+ // snippet-start:[location.java2.get.device.position.main]
152302 /**
153303 * Retrieves the position of a device using the provided LocationClient.
154304 *
@@ -180,7 +330,9 @@ public CompletableFuture<GetDevicePositionResponse> getDevicePosition(String tra
180330 }
181331 });
182332 }
333+ // snippet-end:[location.java2.get.device.position.main]
183334
335+ // snippet-start:[location.java2.update.device.position.main]
184336 /**
185337 * Updates the position of a device in the location tracking system.
186338 *
@@ -223,7 +375,9 @@ public CompletableFuture<BatchUpdateDevicePositionResponse> updateDevicePosition
223375 }
224376 });
225377 }
378+ // snippet-end:[location.java2.update.device.position.main]
226379
380+ // snippet-start:[location.java2.create.tracker.main]
227381 /**
228382 * Creates a new tracker resource in your AWS account, which you can use to track the location of devices.
229383 *
@@ -254,13 +408,9 @@ public CompletableFuture<String> createTracker(String trackerName) {
254408 }
255409 }).thenApply (CreateTrackerResponse ::trackerArn ); // Return tracker ARN
256410 }
411+ // snippet-start:[location.java2.create.tracker.main]
257412
258- /**
259- * Lists the geofences in the specified collection.
260- *
261- * @param collectionName the name of the geofence collection to list
262- */
263-
413+ // snippet-start:[location.java2.put.geo.main]
264414 /**
265415 * Adds a new geofence to the specified collection.
266416 *
@@ -304,7 +454,9 @@ public CompletableFuture<PutGeofenceResponse> putGeofence(String collectionName,
304454 }
305455 });
306456 }
457+ // snippet-end:[location.java2.put.geo.main]
307458
459+ // snippet-start:[location.java2.create.collection.main]
308460 /**
309461 * Creates a new geofence collection.
310462 *
@@ -333,7 +485,9 @@ public CompletableFuture<CreateGeofenceCollectionResponse> createGeofenceCollect
333485 }
334486 });
335487 }
488+ // snippet-end:[location.java2.create.collection.main]
336489
490+ // snippet-start:[location.java2.create.key.main]
337491 /**
338492 * Creates a new API key with the specified name and restrictions.
339493 *
@@ -372,7 +526,9 @@ public CompletableFuture<String> createKey(String keyName, String mapArn) {
372526 }
373527 }).thenApply (response -> response != null ? response .keyArn () : null ); // Return the key ARN
374528 }
529+ // snippet-end:[location.java2.create.key.main]
375530
531+ // snippet-start:[location.java2.create.map.main]
376532 /**
377533 * Creates a new map with the specified name and configuration.
378534 *
@@ -408,7 +564,9 @@ public CompletableFuture<String> createMap(String mapName) {
408564 }
409565 }).thenApply (response -> response != null ? response .mapArn () : null ); // Return the map ARN
410566 }
567+ // snippet-end:[location.java2.create.map.main]
411568
569+ // snippet-start:[location.java2.delete.collection.main]
412570 /**
413571 * Deletes a geofence collection asynchronously.
414572 *
@@ -438,7 +596,9 @@ public CompletableFuture<Void> deleteGeofenceCollectionAsync(String collectionNa
438596 }
439597 }).thenApply (response -> null ); // Ensures the method returns CompletableFuture<Void>
440598 }
599+ // snippet-end:[location.java2.delete.collection.main]
441600
601+ // snippet-start:[location.java2.delete.key.main]
442602 /**
443603 * Deletes the specified key from the key-value store.
444604 *
@@ -469,7 +629,9 @@ public CompletableFuture<Void> deleteKey(String keyName) {
469629 }
470630 }).thenApply (response -> null ); // Ensures the method returns CompletableFuture<Void>
471631 }
632+ // snippet-end:[location.java2.delete.key.main]
472633
634+ // snippet-start:[location.java2.delete.map.main]
473635 /**
474636 * Deletes a map with the specified name.
475637 *
@@ -499,7 +661,9 @@ public CompletableFuture<Void> deleteMap(String mapName) {
499661 }
500662 }).thenApply (response -> null );
501663 }
664+ // snippet-end:[location.java2.delete.map.main]
502665
666+ // snippet-start:[location.java2.delete.tracker.main]
503667 /**
504668 * Deletes a tracker with the specified name.
505669 *
@@ -532,7 +696,9 @@ public CompletableFuture<Void> deleteTracker(String trackerName) {
532696 }
533697 }).thenApply (response -> null );
534698 }
699+ // snippet-end:[location.java2.delete.tracker.main]
535700
701+ // snippet-start:[location.java2.delete.calculator.main]
536702 /**
537703 * Deletes a route calculator from the system.
538704 *
@@ -565,5 +731,6 @@ public CompletableFuture<Void> deleteRouteCalculator(String calcName) {
565731 }
566732 }).thenApply (response -> null );
567733 }
734+ // snippet-end:[location.java2.delete.calculator.main]
568735}
569-
736+ // snippet-end:[location.java2.actions.main]
0 commit comments