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
Let's get Spark installed and start working through our REST endpoints. We will explore the Google gson library for JSON serialization.
Gradle dependencies
compile 'com.sparkjava:spark-core:2.3'
compile 'com.google.code.gson:gson:2.5'
Learn more
- gson documentation uses private fields instead of getters and setters
- Understanding HATEOAS
- Make your voice heard on our future Java content!
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
All right, so we've got the ability
to add and to list courses and
0:00
store them to a JDBC
supported data stored.
0:04
Let's expose that functionality
to any outside application.
0:07
Whether it be a web app or a mobile app.
0:10
Now first we're gonna need to
get our server up and running.
0:13
So let's get cranking on that.
0:16
All right, so let's get Spark installed.
0:18
So the current version of Spark is 2.3.
0:20
So we're gonna do com.sparkjava and
the name of it is spark-core and
0:26
like I said it's 2.3, awesome.
0:30
We'll update Gradle over here.
0:34
All right, and now right off the root
here let's make a new class and
0:38
we can call this whatever we want but
let's call it Api.
0:41
That's what we're building,
why not call it that right?
0:44
Spark's pretty nice we can do
this all in one file, okay.
0:47
And then we're gonna add our
public static void main.
0:51
Public static void main and
were going to press tab.
0:53
Bam, there it is.
0:56
Okay so, in our main method here, let's
just go ahead and create our Sql2o object.
0:58
And then we'll instantiate our dao objects, so
1:03
that we can use it in all
of our methods right?
1:05
That's what we want to do, so let's go
ahead and create it first, it's a Sql2o.
1:07
We'll call it sql2o, and
then we're gonna say new Sql2o.
1:10
And so the connection string, we're
gonna say jdbc, and it's definitely h2,
1:19
but this time let's use a file, so
then we can restart our server.
1:23
Finally we can restart our server and,
the data will be there.
1:28
We're gonna use the same
init that we did before.
1:31
So we're gonna say INIT=RUNSCRIPT.
1:33
We're gonna say from and then we're gonna
put in exactly like we did before with
1:35
the class path because we put
it in resources:db/init.sql.
1:38
So that's gonna run that script
that will create the tables.
1:44
Now remember, if the database exists,
which it will after the first time we run
1:48
this, we have that create if exists so
it won't overwrite our tables.
1:52
Okay, so
now we're gonna code to the interface.
1:56
We're gonna do a CourseDao.
1:58
This way, if ever we wanted to
change it to not use Sql2o,
2:00
we wanted to use some other big
data database or something,
2:04
we could just switch out
our implementation, right?
2:08
So we're gonna code to the interface, but
2:10
what we're going to do is choose
the implementation, right?
2:13
So the interface on the left over here
on the right is the implementation.
2:17
That way we can switch this out whenever,
cool right.
2:22
So now any one of our
routes can use CourseDao.
2:26
And we'll do something similar later
with with our resources, okay.
2:30
So, let's get started.
2:34
So let's allow users of our
API to create a new course.
2:35
Now, how are they gonna do that?
2:39
Well, Rest Standards would
state that they make
2:40
a post request to the plural
name of the resource.
2:43
We're gonna post to courses.
2:46
Let's just do that.
2:49
The static method post has
an over ridden counterpart.
2:50
So we're going to post to courses, and
2:54
there's a parameter we
haven't touched on before.
2:56
And we're saying, if the request type
is application JSON, so it will match
2:59
anything that's a post to courses that
has the request type of application/json.
3:04
And then we're going to put in here,
3:09
we're going to put in our
little lambda of course.
3:10
Like we always do.
3:14
We're gonna say, return null, so it can
figure out what we're talking about here.
3:15
It has to return an object.
3:19
So let's go ahead and
let's statically import this post method.
3:21
Here we go.
3:27
Now it's happy.
3:28
All right.
3:28
So we need to get the JSON
that's being passed across.
3:29
So there is a method on the request
object called body so req.body.
3:34
And what that's going to do is that's
going to return the json that they've
3:38
sent across.
3:41
So we know that it's gonna be JSON, right?
3:41
Because we said it needs to come
across as json, so we know that.
3:44
So basically what we wanna do
is you wanna take this json and
3:49
we wanna create one of
our courses from it.
3:51
We're gonna create a brand new course
from the json that they're suggesting.
3:53
So, this is basically a form
of serialization, right?
3:56
So, we're gonna wanna consume the json and
3:58
then later when we communicate we're
gonna also wanna produce json.
4:00
So, we could write our own serializer, but
why would we go recreate the wheel, right?
4:04
There's tons of open source tools.
4:08
So, let's use one.
4:09
Google has one called gson here.
4:10
It's their repo is gson.
4:13
You scroll down you can
read a little bit about it.
4:15
We'll get some hands on
training here in a bit so.
4:17
And then if you come
here to Maven Central.
4:20
You can go to the downloads here and if
you scroll down here we are using Gradle.
4:22
So if you come here.
4:27
You can copy this.
4:28
Copy this and
we'll paste that over in our build.gradle.
4:30
We'll put that here.
4:35
I'm gonna go ahead and
refresh the Gradle project.
4:38
And now, let's go use it, so.
4:41
Okay so we want to make a new
course from our course.
4:48
And we're gonna use that that gson object.
4:53
So you know what all of these
are probably gonna use that.
4:56
So let's go ahead and let's put it up here
up in this in the beginning part of our
4:59
main method so the way that you
do that is Gson gson = new Gson.
5:02
That's kind of a play on json right so
there's.
5:07
Google and this is asking if
it's the course and it is.
5:10
Okay, so we have this is JSON
here is the string has JSON so
5:15
we want to say, gson.fromJson.
5:20
We're gonna get the, you pass
the first primary here's the string
5:24
which is string JSON and then you tell
it what class you wanna put it in.
5:26
So we wanna put it in a Course.class and
that's it.
5:30
Isn't that cool?
5:33
So, one thing I want to point out
here though is that gson is not
5:34
using the setter properties.
5:37
What it's doing is it's actually
using the private fields.
5:38
That's just something I wanted
to have you keep in mind.
5:41
I dropped some info in
the teacher's notes.
5:43
So now we have a course object and
we have our Dao object.
5:46
So we can pretty much do what
they're trying to do here, right?
5:49
What they're trying to do specifically
here is we're trying to add
5:53
a course right?
5:56
Cuz we're posting the courses so
we can say courseDao.add(course).
5:57
Look at that.
6:04
So remember that course is going to
set the the ID, when we do this,
6:05
so it's gonna modify this course,
it's gonna set the new ID, so
6:08
we should probably send it back to them,
right?
6:11
That's kind of the standard.
6:13
You add it and you send it back.
6:14
So, also being a good API citizen,
we should set our status, right?
6:15
We should say the status was
201 which is created, right?
6:18
And we should also let the caller know
that what's coming to them is JSON.
6:22
So we wanna say, our response
type is also application/json.
6:28
And then we want to return our course,
now wait a second.
6:37
How are they gonna read
just our JavaScript object?
6:42
That's right.
6:45
We need to transform that back to JSON.
6:45
So, the way that we do that
is actually pretty cool and
6:48
this is a method reference trick, okay?
6:51
So, there's a final parameter
here that these routes take and
6:54
it's called a response transformer.
6:57
And this is where we were putting
our template thing before but
7:00
you can actually just use
a method reference right?
7:02
All it needs is something that takes
an object and returns a string.
7:04
And so, guess what gson has that and
it is called toJson.
7:08
So what we're saying here is they're
saying on this gson object run toJson on
7:13
it and pass in this course.
7:17
So this is called a method reference,
so go ahead and
7:19
check the teacher's notes on that.
7:21
Since a response transform is
just a single abstract method,
7:24
we can pass anything here that
matches that method declaration.
7:27
And it just so happens that toJson does.
7:31
So we're basically just returning
a straight Json representation of our
7:33
course object.
7:36
If we wanted more fancy stuff we could
write a custom method here that would
7:37
do other things like ATOS or hyper media
as the engine of applications that.
7:40
Check the teacher notes, I don't want
to get too far from her task at hand.
7:44
So speaking of which, let's write the get
portion for the courses and point.
7:48
So this one,
we wanna return all the courses.
7:52
So, that would be using the same
courses end point, but on a get, right?
7:54
And so we wanna return application Json.
8:03
We only want to, if they make
the request with application Json,
8:06
we want to return application json.
8:09
And we're going to do req, res,
and we have that already don't we?
8:11
We have courseDao.findall().
8:18
And we can also can just turn that
right straight into Json right?
8:21
So method parameter there toJson right?
8:26
So well, there's a single line,
now wait a second.
8:30
We have this all on a single line,
so I can kick this down like this.
8:34
While this is all fitting on a single line
we forgot to set the type to be Json but
8:40
you know what everything that we send out
of our API here that is going to be Json.
8:46
So why don't we just use one of
those filters remember those.
8:50
So the filter, we'll run after
each one of these requests.
8:54
Let's go ahead and kick that up a bit.
8:58
So we're gonna say after,
in time after request response.
8:59
We wanna set res.type application/json,
9:06
and we will go ahead and,
it doesn't know what type is,
9:13
because it doesn't know what after is yet,
so once I do this, boom.
9:17
Okay, and we'll put a semicolon here.
9:22
So now we can remove this, right?
9:25
Because every single response that we
send is gonna have the, at the end.
9:26
It's gonna have application json, awesome.
9:30
Okay, you know what?
9:35
We should make it so
that we can find a specific course by ID.
9:37
So let's see let's start
at the end point first and
9:40
then we'll work our way backwards right?
9:43
So if we wanna find a course by id we
would do this we'd say get courses ID and
9:44
then again it's gonna be application/json.
9:51
And we're going to do req, res.
9:58
And we're definitely going to
transform whatever we get back so
10:06
let's just go ahead and
do that so gson toJson.
10:08
The lamda method reference there.
10:11
Okay.
10:14
So, remember you can pull these
things off from a thing called
10:15
req.params, and it's,
you put the name in there, right?
10:19
And, we'll return null so
it knows what we're talking about.
10:24
Okay, so we want to pull that off so
10:28
we will say int id = Integer.parseInt
then we'll pull out that.
10:32
Well, it's a little bit dangerous
because what if that's not an ID?
10:40
But, we can deal with that later.
10:44
All right, so then what we can do,
10:47
this is kind of the way of
designing an API backwards, right?
10:49
So we can say we want to get this thing,
10:52
we wanna get a course out, and
we know that we have this Dao object.
10:55
So we'd say courseDao.find.
10:59
Well, if we have find all,
let's do findById.
11:00
That makes sense, right?
11:03
And we'll pass in the id so
we'll do that and then we'll do course.
11:04
So now we have written this in point for
something that we don't even have yet.
11:07
You know what happens if it's not found?
11:11
Let's put it to do there.
11:13
Let's remember that to do just the,
what if this is not found?
11:14
Okay, so let's go ahead and
we'll experience the power of the id.
11:24
Let's make it do the work for us.
11:29
So, I'm gonna go ahead and use the action
here, say create method, find by Id.
11:30
So, here it is.
11:37
Well, that was exactly right.
11:38
Now let's pop over to the Sql2o
course Dao Implementation,
11:40
Sql2o of CourseDao pop in here.
11:45
And if we look it's squiggly red,
11:48
because we don't implement that new method
that just got created, so let's do it.
11:50
Let's say implement methods.
11:53
We wanna do the find by course.
11:55
Perfect, okay and
it has also taken in id, so
11:56
we need to do again we're gonna say try,
and
12:00
we'll pull Connection con = sql2o.open.
12:05
And again that will
automatically close it and so
12:12
we're going to return con.createQuery.
12:15
And it's very similar to the one above.
12:18
We're going to say select star
from courses where id is equal to.
12:19
And we're going to to do
a named parameter here and
12:25
that looks very familiar
to the other ones right?
12:27
And we're gonna continue here and
we're gonna say addParameter,
12:29
because that's how you name the parameter.
12:31
We're gonna say, anytime it says id,
pass in our id from above.
12:32
And then finally,
we're going to execute and fetch.
12:37
Now before we did executeAndFetch and
returnToList, but
12:41
there's one called first.
12:43
And that will just get the first one,
cuz that's what we want.
12:45
We want a specific one.
12:47
That's Course.class.
12:49
Sorry about that.
12:51
Everything's on top of it.
12:52
So executeAndFetchFirst(Course.class).
12:53
Boom.
And
12:56
I will get rid of this trailing
return at the bottom here.
12:57
So we've got executeAndFetchFirst.
13:00
So that looks like it should work.
13:01
So you know what?
13:03
While we're in here why don't we just
generate a test for this, right?
13:04
So we'll go to, we'll go to the test.
13:07
Just here and let's go ahead and
say, we'll make a new test.
13:11
New test method and we'll say
13:18
existingCoursesCanBeFoundById, all right.
13:23
So we'll do a course.
13:30
This is starting to feel
duplicative isn't it.
13:33
Course = new Course, yeah.
13:35
This is,
we need to do something about this.
13:39
Maybe somebody can help us out here,
test.com.
13:42
Cuz we are definitely repeating
ourselves every time we do that.
13:45
So we're gonna add the course
here in the set up,
13:47
we're gonna arrange,
add the course and then
13:49
the action that we're gonna do is we're
gonna try to use that method we just did.
13:52
We're gonna say foundCourse
= dao.findById and
13:56
we're gonna pass in that
course we created getId.
14:01
Cuz remember that gets set on this
add we're going to set that ID,
14:05
so then we'll just make sure
that the two are equal.
14:09
Now again it's using the object equals, so
14:12
it's checking that all of
the fields are the same.
14:15
Which is exactly what we want to do right?
14:17
Cuz it's gonna be two separate objects.
14:19
It's gonna be one that was created here,
and one that's returned and
14:20
populated from our Dao object, cool.
14:24
Okay so, that looks sane, so
let's go ahead, and we'll run that.
14:28
Okay, cool.
14:36
They all passed.
14:37
And, let's go ahead and take care of
that course creation thing, okay?
14:38
So, I'm gonna highlight over here,
14:43
I gonnas highlight this,
cuz this is just too much.
14:44
And, I wanna put that into its own method.
14:47
So, I'm gonna say refactor,
14:48
and do refactor this I'm going to
choose extract it to a method.
14:50
And let's not call it get test
let's call it newTestCourse.
14:55
Right that's that's a good name for it we
know what that means so I'll click Okay.
15:02
Look.
It found that there's two code fragments
15:05
that can be replaced which is
exactly what we're trying to do and
15:07
let's say yes and, we'll replace
that occurrence, and that one.
15:09
Yep, perfect and so,
now it follows exactly what we want.
15:14
We can run one more time.
15:18
We are following our best practices,
even in our tests.
15:19
Isn't that cool?
15:23
We don't want to repeat ourselves.
15:24
Awesome, everything's working.
15:25
Great job.
15:27
Wow, it feels so good to test and
know that things are working.
15:28
We really should test our
API both manually and then,
15:32
of course, functionally.
15:35
You know, so we can be rest
assured that all is working.
15:36
Why don't we take a swing at that
testing right after this short break?
15:40
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