I have a method that returns a CompletionStage<>
at various points, but it appears that doing so from within a try-catch block causes an "Incompatible types" error:
Incompatible types
Required: CompletionStage<com.foo.Response>
Found: CompletableFuture<? extends com.foo.Response>
Here's the code. I've simplified it as much as possible without potentially removing the culprit:
public CompletionStage<Response> example(final Optional<String> idMaybe) {
return idMaybe.map(id -> {
if (true) { // Simplified example.
if (!NumberUtils.isNumber(id)) {
return CompletableFuture.completedFuture(Response.forStatus(Status.BAD_REQUEST));
}
final SomeServiceInterface service;
try {
service = someClient.getServiceInterface(SomeServiceInterface.class);
} catch (SomeException e) {
LOG.error("Error retrieving SomeServiceInterface.", e);
return CompletableFuture.completedFuture(Response.forStatus(Status.INTERNAL_SERVER_ERROR));
}
final Page page;
try {
page = someService.getSomethingByStatement(statementBuilder.toStatement());
} catch (RemoteException e) {
LOG.error("Error retrieving a thing by statement", e);
return CompletableFuture.completedFuture(Response.forStatus(Status.INTERNAL_SERVER_ERROR));
}
if (page.getResults() == null || page.getTotalResultSetSize() == 0) {
return CompletableFuture.completedFuture(Response.forStatus(Status.NOT_FOUND));
}
if (page.getTotalResultSetSize() != 1) {
// There should be only one result.
return CompletableFuture.completedFuture(Response.forStatus(Status.INTERNAL_SERVER_ERROR));
}
}
return CompletableFuture.completedFuture(Response.ok());
}).orElse(CompletableFuture.completedFuture(Response.forStatus(Status.BAD_REQUEST)));
}
To narrow the issue down, I removed the failure-case return
s one by one, backwards. So first, removed this:
if (page.getTotalResultSetSize() != 1) {
// There should be only one result.
return CompletableFuture.completedFuture(Response.forStatus(Status.INTERNAL_SERVER_ERROR));
}
Still the same error. So then, removed this:
if (page.getResults() == null || page.getTotalResultSetSize() == 0) {
return CompletableFuture.completedFuture(Response.forStatus(Status.NOT_FOUND));
}
Still the same error. So then, removed this:
final Page page;
try {
page = someService.getSomethingByStatement(statementBuilder.toStatement());
} catch (RemoteException e) {
LOG.error("Error retrieving a thing by statement", e);
return CompletableFuture.completedFuture(Response.forStatus(Status.INTERNAL_SERVER_ERROR));
}
Still the same error. So then, removed this:
final SomeServiceInterface service;
try {
service = someClient.getServiceInterface(SomeServiceInterface.class);
} catch (SomeException e) {
LOG.error("Error retrieving SomeServiceInterface.", e);
return CompletableFuture.completedFuture(Response.forStatus(Status.INTERNAL_SERVER_ERROR));
}
That removed the error. (I double-checked that it wasn't because it caused an error anywhere else; it compiles.)
What is different about returning a completable future from within a try-catch block? Or, what's happening that gives it the appearance of being so? And how can I fix the original code?