Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed Build a REST API in Spark!
You have completed Build a REST API in Spark!
Preview
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.
This video doesn't have any notes.
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
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 trace 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 exc 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 things 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 gsn.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 it 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 upYou need to sign up for Treehouse in order to set up Workspace
Sign up