Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
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