I'm integrating with a payments processor and am trying to deal with the scenario where:
So I need to start an API call to the payment processor from within the HTTP call from the UI, then if it takes more than 60 seconds, end the HTTP call and return an error to the user, then if the API call to the payment processor eventually succeeds (say after 70 seconds), send an email to the admin team.
I'm thinking of something like this:
import javax.ws.rs.client.*;
import java.util.Timer;
import java.util.TimerTask;
...
boolean overThreshold = false;
int timeout = 60; // seconds
TimerTask task = new TimerTask() {
@Override
public void run() {
overThreshold = true;
// return a message to user here saying their payment could not be processed
}
};
new Timer(true).schedule(task, timeout * 1000);
Client client = ClientBuilder.newClient();
WebTarget webTarget
= client.target({url of payment processor});
Invocation.Builder builder = webTarget.request()
.header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON);
final Response response = builder.post(Entity.json(new Gson().toJson(request)));
if (overThreshold) {
// send alert email here
}
There are a few problems, e.g. the run()
method has void return value, error with overThreshold
as being accessed from a inner class. Is there a more elegant way of doing this?
Using Future.get(timeout) from an ExecutorService should handle this quite cleanly.
For example:
ExecutorService executor = Executors.newCachedThreadPool();
// ... set up builder as before ...
Future<Response> responseFuture = executor.submit(
() -> builder.post(Entity.json(new Gson().toJson(request))));
try {
Response response = responseFuture.get(timeout, TimeUnit.SECONDS);
// return normal response here
} catch (TimeoutException ex) {
executor.submit( () -> {
Response lateResponse = responseFuture.get();
// send overThreshold alert email here
// Dummy return - prefer Callable to Runnable here for exception handling
return null;
} );
// return a message to user here saying their payment could not be processed
}
The choice of ExecutorService
could be tuned to fit, or equally be a shared thread pool elsewhere in the application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With