Custom ErrorHandlers and Lagom

Table of contents
Reading Time: 3 minutes

Hello everyone,

it’s been quite a while now since I started working on Lagom(java) and it was only recently when I came across a scenario wherein I was required to override the ErrorHandler provided by Play in my Lagom microservice. As you all already know that Lagom is built on top of Play and Akka, so there will be times when we’ll be required to override the behavior and functionality provided by these two.

In this blog, we are going to see how we can override the ErrorHandling provided by play, and since Lagom v1.4.x has recently been released and it uses Play 2.6.x by default so we’ll also see the difference in the implementation of ErrorHandling in Lagom v1.3 and Lagom v1.4.

First of all, we should be very clear why we need to override the Play Error Handling mechanism. In this era of microservices and API’s, many of us might have faced this situation when by mistake(or willingly) a client tries to hit a route which does not exist in our Service. What happens next is the default mechanism of Play’s Error Handling which renders an HTML page displaying your existing routes information. If you want to avoid such a scenario you should override the default Error handling mechanism of play. Well, not just this scenario but you can handle other scenarios as well which are specifically mentioned at Play documentation stating :

Play will in many circumstances automatically detect client errors – these include errors such as malformed header values, unsupported content types, and requests for resources that can’t be found.

We’ll be focusing on the requests for resources that can’t be found part here.

In Play, HttpErrorHandler interface is the component for handling the HTTP errors. Http errors could be a ClientError or a ServerError which would trigger the following methods respectively:

onClientError() // invoked when a client error occurs, that is an error in the 4xx series.

or an

onServerError() // invoked when a server error occurs.

The DefaultHttpErrorHandler class in play implements this interface and provides various methods to help us pass on our custom Error Handling logics overriding the default behavior of PLAY. In order to Override the default Error Handling we need to perform the following steps:

Step1: Create your own ErrorHandler class extending the DefaultHttpErrorHandler class, this class is intended to be extended to allow reusing Play’s default error handling functionality.

Step2: Override the default OnNotFound() method of the DefaultHttpErrorHandler class, providing your custom error messages that should be sent to the client instead of the generall HTML page.

Step3: In your application.conf add the following to make the flow go to your custom ErrorHandler class whenever a request for a non-existent resource is received.

play.http.errorHandler = {packageName}.{YourErrorHandlerClassName}

That is pretty much the same for both Lagom v1.3.x and Lagom v1.4.x, the only difference is that Lagom 1.3 supported play 2.5 whereas Lagom v1.4 is on Play 2.6, so we need to be careful as a lot many methods have been marked deprecated in Play 2.6.

Let’s just quickly go through the actual implementation of the same, you can clone the code from here for Lagom v1.3.x and Play 2.5.x

Here’s the errorHandler class, please note that I have tried to make it as simple as possible by just passing back an errorString response saying The requested resource does not exist. to the client, you can respond with your Error Classes as well so as to maintain the error response structure of your API.



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


@Singleton
public class ErrorHandler extends DefaultHttpErrorHandler {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Inject
public ErrorHandler(Configuration configuration, Environment environment,
OptionalSourceMapper sourceMapper, Provider<Router> routes) {
super(configuration, environment, sourceMapper, routes);
}
@Override
protected CompletionStage<Result> onNotFound(Http.RequestHeader request, String message) {
String errorResponse="The requested resource does not exist.";
JsonNode jsonNode = OBJECT_MAPPER.valueToTree(errorResponse);
return CompletableFuture.completedFuture(Results.notFound(jsonNode));
}
}

and for Lagom v1.4.x (you can clone it from here lagom 1.4.4 and Play 2.6) we have the same ErrorHandler class as:



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


@Singleton
public class ErrorHandler extends DefaultHttpErrorHandler {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Inject
public ErrorHandler(Config configuration, Environment environment,
OptionalSourceMapper sourceMapper, Provider<Router> routes) {
super(configuration, environment, sourceMapper, routes);
}
@Override
protected CompletionStage<Result> onNotFound(Http.RequestHeader request, String message) {
String errorResponse = "The requested resource does not exist.";
JsonNode jsonNode = OBJECT_MAPPER.valueToTree(errorResponse);
return CompletableFuture.completedFuture(Results.notFound(jsonNode));
}
}

please take note of the Configuration and Config objects injected in the constructor of the Handler, in Lagom 1.4 we rely on com.typesafe.config.Config since the play.Configuration class was deprecated.

The return statement:

 return CompletableFuture.completedFuture(Results.notFound(jsonNode));

will return back our string error message to the client whenever the ErrorHandler class is triggered.

Once you have created your own application(or cloned mine), start the service by issuing the command:

mvn clean lagom:runAll

now when you hit any route which is not present in the service you will find out that instead of the HTML page you are now getting an informative error response stating The resource was not found.

Caution: Please make sure you don’t hit localhost:9000/randomUrl to see the ErrorHandler working you would need to hit the URL:

0.0.0.0:/randomUrl 

for example hit 0.0.0.0:57797/someRandomURL, where 57797 is the port on which the service was running on my local. You can always check the port on which your service is running by hitting:

  1. localhost:9008/services if you are using Lagom V1.4.x
  2. localhost:8000/services if you are using Lagom V1.3.x

I hope this helps in understanding how we can write our custom Error Handlers in Lagom, please feel free to share your inputs, suggestions, queries in the comments and like if this is helpful.

Thanks 🙂 🙂
Happy Blogging and Happy reading. 🙂

knoldus-advt-sticker

References:

  1. https://www.lagomframework.com/documentation/1.4.x/java/Migration14.html
  2. https://www.playframework.com/documentation/2.6.x/JavaErrorHandling

Written by 

Prashant is a Senior Software Consultant having experience more than 5 years, both in service development and client interaction. He is familiar with Object-Oriented Programming Paradigms and has worked with Java and Scala-based technologies and has experience working with the reactive technology stack, following the agile methodology. He's currently involved in creating reactive microservices some of which are already live and running successfully in production, he has also worked upon scaling of these microservices by implementing the best practices of APIGEE-Edge. He is a good team player, and currently managing a team of 4 people. He's always eager to learn new and advance concepts in order to expand his horizon and apply them in project development with his skills. His hobbies include Teaching, Playing Sports, Cooking, watching Sci-Fi movies and traveling with friends.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading