Play Framework - throw an exception to return an HTTP response
Hmm, when I write out the title, the idea seems pretty gross. But it makes some boilerplate-type things really nice.
Take, for example, a user profile page. The endpoint looks like fancyapp.com/users/{userId}/
. If the user doesn’t exist, you’ll want to throw a 404. And chances are, you’ll be doing the same thing for other models.
Here is something that you might need something like:
public Result viewProfile(long userId) {
User user = User.repository.byId(userId);
if (user == null) {
return notFound("User does not exist!");
}
return ok("user profile!");
}
Wouldn’t it be great if you had, like, a getUserOr404
method? Then you could just do…
public Result viewProfile(long userId) throws ImmediateHttpResponse {
User user = getUserOr404(userId);
return ok("user profile!");
}
What if I told you that such a method exists? All you have to do is believe in yourself.
I mean, it only saves 3 lines here, but think of the possibilities. You could probably even gussy that up a little more…pass in the class that you’re looking for…make it more generic…
Here’s your ErrorHandler
class (docs):
public class ErrorHandler extends DefaultHttpErrorHandler {
@Override
public CompletionStage<Result> onServerError(RequestHeader request, Throwable exception) {
if (exception instanceof ImmediateHttpResponse) {
return CompletableFuture.supplyAsync(() -> {return (ImmediateHttpResponse) exception;})
.thenApply(immediateHttpResponse -> immediateHttpResponse.getResponse());
}
return super.onServerError(request, exception);
}
}
I know that some of that code isn’t too great (my IDE told me so). I’ll fix it up later when I’m feelin’ all learny n stuff.
And then your ImmediateHttpResponse:
public class ImmediateHttpResponse extends Exception {
private Result response;
public ImmediateHttpResponse(Result response) {
this.response = response;
}
public Result getResponse() {
return this.response;
}
}
I actually stole this from CodeIgniter. There aren't many things that I like about that framework, but I did like this. And then the example was something that Django does, but I forget how it's implemented. I don't think it's with an exception.
And there you have it.