Errors6:58 with Craig Dennis
An often overlooked task in designing an API is what to do when errors happen. Let's use Spark's exception handling to make sure we pass user friendly information.
One of the most commonly overlooked parts of designing an API is 0:00 proper error messaging. 0:04 We all get excited to get our API out the door and we forget to take 0:05 care of informing callers of our API about errors that they might encounter. 0:08 One of the reasons for this is because we as JAVA developers get so 0:13 used to letting exceptions take care of the, well, 0:17 exceptional things that could happen in our code. 0:20 Now the problem is, clients don't get the benefit of reading our stack trays or 0:23 the error messages, they make no sense out of context. 0:27 Let's see what we can do about better communicating when things go south. 0:30 Okay, so remember Spark has a pretty handy way to handle specific exceptions. 0:34 So let's go ahead and create our own exception and have Spark capture it and 0:39 send out a client-friendly error message. 0:43 It's kind of the best practice here, right? 0:45 First, let's go ahead and make a new exception class. 0:48 So in this exe folder here, which is for exception, let's make one called APIError. 0:51 It'll kinda be the parent class for all this. 0:57 So ApiError is going to extend a Runtime exception. 1:00 And what that's gonna allow us to do is make sure that we don't need to 1:05 declare it on places where the ApiError might be thrown. 1:09 We can throw it wherever because it really is a Runtime error. 1:12 So one of the things we want to make sure is that a status is stored. 1:16 So, we'll do a final int status and we're going to 1:20 make a new ApiError here and we'll pass in a status and 1:26 we'll also pass in a message and that will be the message from API. 1:31 So first thing's first, we're gonna call upCall 1:37 to the RuntimeExceptions constructor, and it only takes one message and 1:40 that's msg so we'll do super(msg) and that will setup everything. 1:44 And then we'll say this.status = status. 1:48 Okay, and then let's go ahead and add a getter. 1:53 For that one status bit. 1:56 So now we have an exception here that we can throw wherever we want. 1:58 So over in our API, let's scroll down here to the bottom and right before after, 2:04 let's make one for exception. 2:09 Order doesn't really matter. 2:11 I just think it's kinda nice to try to find it there. 2:12 So remember the way that this works is you say when this error happens, 2:14 something of this ApiError.class happens, 2:19 we are going to get back an exception, a request and a response. 2:24 And so that lambda there Is going to here, adhere to this. 2:31 So what we're gonna want to do is we're going to 2:38 cast that exception that comes in here to an APIError. 2:43 By default, it's just an exception but because we've extended it we can do this. 2:48 So we're gonna cast it so that we can get to the meat of the stuff we want there. 2:51 So let's go ahead, and we'll build a map just like we did before. 2:55 We're gonna build a map of string and object this time. 2:58 Because one's gonna be a string, and one's gonna be an integer, right? 3:02 So we're gonna make a jsonMap, and we're gonna call it new_HashMap. 3:07 We're gonna use the diamond method there to not redeclare. 3:12 And that's what we have. 3:17 Okay. 3:19 So inside that map, we want to put a couple of things, right? 3:20 We want to put the status, 3:23 which we can get from our getter because our error has a get status. 3:26 Right. 3:30 And we also want to put in here our message. 3:33 And we will put that in. 3:37 Let's call the field errorMessage in the json, right? 3:40 And we'll put err.getMessage, and 3:42 that was inherited, of course, from runtime exception. 3:45 Now unfortunately, here in the exception handler the after doesn't run. 3:51 So we should probably make sure that we set the type to be application, 3:56 except with two p's. 4:02 Application json and also we should set the status. 4:03 That way they can not only use the message, but 4:09 they could also just use the status codes. 4:11 One more time we're gonna use that to get status. 4:13 Cool. 4:17 And then remember we're gonna need to return this out but 4:20 it doesn't have a response transformer the exception handler doesn't. 4:23 So we're gonna say res.body and we're gonna call our gson,toJson and 4:26 we're gonna pass in our json/Map so 4:32 that will return a json string to the body and it knows that it's application json. 4:36 Okay, so, we have an API error class, 4:41 every time we throw it and we pass at a status code and 4:44 with a message it's gonna get caught here and return and pretty json. 4:47 Let's add one, so this to do here. 4:52 What if this is not found? 4:54 Let's go ahead and let's take care of that cause, what if, that's not found, so 4:56 we'll do that, so let's say if Course is null. 5:00 You want to throw a new ApiError. 5:05 And that's a 404, right? 5:10 We can say, Could not find course with id. 5:11 Very nice message, right? 5:19 Whatever they passed in there. 5:21 Cool. So let's flip over to postman. 5:22 Cool. So 5:27 we actually have left up here before this course for before it was returning a null. 5:29 I'm gonna go ahead. I'm gonna send that again. 5:33 And remember the thing about the server. 5:36 You need to restart the server, facepalm, so I am going to stop the server here. 5:40 Close All and I am going to run API here. 5:48 Okay so the server's running. 5:57 Let's go ahead and click send and boom here we go. 5:58 We got a 404. 6:01 It couldn't be found and that's very pretty. 6:03 Could not find course with id of 42, status 404. 6:06 Excellent, alright, you know what else? 6:09 Our test should pass too, right? 6:12 So, let's flip back over to our tests. 6:14 We'll say run all tests, all in course reviews. 6:18 We'll run it, and bam. 6:23 Missing course returns not found status is passing. 6:25 Awesome. 6:29 Now we know that whenever we see an exceptional bit, 6:30 we can just toss an API error, and they will be sent to the API user. 6:32 We can also properly test them. 6:36 Wouldn't it be so great to have one of the exception handlers in real life? 6:38 Like you could make a mistake and something would catch it and 6:42 explain why the mistake happened. 6:44 It would solve so many arguments. 6:46 You know what? 6:48 Why don't we practice a little recall by building out the reviews 6:49 portion of the API. 6:52 If you can't locate the knowledge, let's just have you throw out a 404 error. 6:53 Knowledge not found 6:57
You need to sign up for Treehouse in order to download course files.Sign up