Exercise 9: Keep Your World Moving
- Deadline: 19 April 2024, Friday, 23:59, SGT
- Late submission (without penalty) accepted until: 23 April 2024, Tuesday, 23:59, SGT
- Difficult Level: 9
Prerequisite
- Caught up to Unit 39 of Lecture Notes
Problem Description
We have a Web API online for querying bus services and bus stops in Singapore. You can go ahead and try:
- https://cs2030-bus-api.herokuapp.com/bus_services/96 returns the list of bus stops (id followed by description) served by Bus 96.
- https://cs2030-bus-api.herokuapp.com/bus_stops/16189 returns the description of the stop followed by a list of bus services that serve the stop.
(note: our database is 2-years old -- don't rely on this for your daily commute!)
In this lab, we will write a program that uses the Web API to do the following: Given the current stop S
, and a search string Q
, returns the list of buses serving S
that also serves any stop with a description containing Q
. For instance, given 16189
and Clementi
, the program will output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
The pairs of S
and Q
can be either entered through the standard input or given to the program in a text file, with every pair of S
and Q
in a separate line.
A program to query the bus API and given a query has been written. Study the program carefully to understand what it does and how it works.
The given program, however, is written synchronously. Every query to the Web API is done one-by-one, and the program has to wait until one query completes before it can continue the execution of the program. As a result, the program is slower than it should.
Your task, for this lab, is to change the given program so that it executes asynchronously. Doing so can significantly speed up the program.
The root of synchronous Web API access can be found in the method httpGet
in BusAPI.java
, in which the invocation of method send from the class HttpClient is done synchronously (i.e., it blocks until the response returns).
HttpClient
also provides an asynchronous version of send
called sendAsync, which is the same as send
excepts that it is asynchronous and returns a CompletableFuture<HttpResponse<T>>
instead of HttpResponse<T>
. (You do not need to get into the nitty-gritty details of the HttpClient
and HttpResponse
for this lab -- but they are good to know, read up about them at your leisure).
To make the program asynchronous, you should first change the invocation of send
in BusAPI
to sendAsync
. All other changes will be triggered by this. The list of things you should change are:
BusAPI::getBusStopsServedBy
now returns aCompletableFuture<String>
BusAPI::getBusServicesAt
now returns aCompletableFuture<String>
BusStop::getBusServices
now returns aCompletableFuture<Set<BusService>>
BusService::getBusStops
now returns aCompletableFuture<Set<BusStop>>
BusService::findStopsWith
now returns aCompletableFuture<Set<BusStop>>
BusRoutes
now stores aCompletableFuture<Set<BusStop>>
instead.BusRoutes::description
now returns aCompletableFuture<String>
(hint: usethenCombine
)BusSg::findBusServicesBetween
now returns aCompletableFuture<BusRoutes>
It is important that at no point in any of the code above, you call CompletableFuture::join
(or get
) on any of the CompletableFuture
, so everything that has been done so far, from the lower-level Web API calls to the higher-level logic of searching for bus services, is done asynchronously.
For this lab, the only place where you should join
is in main()
, where you now have multiple CompletableFuture
objects, one from each call to findBusServicesBetween
. As the final step, you should change main()
so that it waits for all the CompletableFuture
objects to complete using allOf
and join
, followed by printing out the description of the bus routes found.
The speed up your would experience for the asynchronous version depends on the complexity of the inputs. For the following test input:
1 2 3 4 5 6 |
|
Your code should produce the exact same set of bus routes as the synchronous version, although it can be in a different order.
1 2 3 4 |
|
Following CS2030S Style Guide
You should make sure that your code follows the given Java style guide and the give Java documentation guide.