1 00:00:00,540 --> 00:00:04,560 All right, so we've got the ability to add and to list courses and 2 00:00:04,560 --> 00:00:07,470 store them to a JDBC supported data stored. 3 00:00:07,470 --> 00:00:10,830 Let's expose that functionality to any outside application. 4 00:00:10,830 --> 00:00:12,600 Whether it be a web app or a mobile app. 5 00:00:13,690 --> 00:00:16,080 Now first we're gonna need to get our server up and running. 6 00:00:16,080 --> 00:00:17,080 So let's get cranking on that. 7 00:00:18,560 --> 00:00:20,830 All right, so let's get Spark installed. 8 00:00:20,830 --> 00:00:26,011 So the current version of Spark is 2.3. 9 00:00:26,011 --> 00:00:30,564 So we're gonna do com.sparkjava and the name of it is spark-core and 10 00:00:30,564 --> 00:00:32,970 like I said it's 2.3, awesome. 11 00:00:34,320 --> 00:00:35,550 We'll update Gradle over here. 12 00:00:38,632 --> 00:00:41,922 All right, and now right off the root here let's make a new class and 13 00:00:41,922 --> 00:00:44,710 we can call this whatever we want but let's call it Api. 14 00:00:44,710 --> 00:00:47,670 That's what we're building, why not call it that right? 15 00:00:47,670 --> 00:00:49,550 Spark's pretty nice we can do this all in one file, okay. 16 00:00:51,220 --> 00:00:53,820 And then we're gonna add our public static void main. 17 00:00:53,820 --> 00:00:56,620 Public static void main and were going to press tab. 18 00:00:56,620 --> 00:00:57,510 Bam, there it is. 19 00:00:58,890 --> 00:01:03,500 Okay so, in our main method here, let's just go ahead and create our Sql2o object. 20 00:01:03,500 --> 00:01:05,690 And then we'll instantiate our dao objects, so 21 00:01:05,690 --> 00:01:07,510 that we can use it in all of our methods right? 22 00:01:07,510 --> 00:01:10,230 That's what we want to do, so let's go ahead and create it first, it's a Sql2o. 23 00:01:10,230 --> 00:01:16,540 We'll call it sql2o, and then we're gonna say new Sql2o. 24 00:01:19,290 --> 00:01:23,830 And so the connection string, we're gonna say jdbc, and it's definitely h2, 25 00:01:23,830 --> 00:01:28,490 but this time let's use a file, so then we can restart our server. 26 00:01:28,490 --> 00:01:31,290 Finally we can restart our server and, the data will be there. 27 00:01:31,290 --> 00:01:33,250 We're gonna use the same init that we did before. 28 00:01:33,250 --> 00:01:35,730 So we're gonna say INIT=RUNSCRIPT. 29 00:01:35,730 --> 00:01:38,980 We're gonna say from and then we're gonna put in exactly like we did before with 30 00:01:38,980 --> 00:01:44,390 the class path because we put it in resources:db/init.sql. 31 00:01:44,390 --> 00:01:48,040 So that's gonna run that script that will create the tables. 32 00:01:48,040 --> 00:01:52,020 Now remember, if the database exists, which it will after the first time we run 33 00:01:52,020 --> 00:01:56,180 this, we have that create if exists so it won't overwrite our tables. 34 00:01:56,180 --> 00:01:58,680 Okay, so now we're gonna code to the interface. 35 00:01:58,680 --> 00:02:00,930 We're gonna do a CourseDao. 36 00:02:00,930 --> 00:02:04,590 This way, if ever we wanted to change it to not use Sql2o, 37 00:02:04,590 --> 00:02:08,110 we wanted to use some other big data database or something, 38 00:02:08,110 --> 00:02:10,940 we could just switch out our implementation, right? 39 00:02:10,940 --> 00:02:13,080 So we're gonna code to the interface, but 40 00:02:13,080 --> 00:02:17,950 what we're going to do is choose the implementation, right? 41 00:02:17,950 --> 00:02:22,650 So the interface on the left over here on the right is the implementation. 42 00:02:22,650 --> 00:02:26,140 That way we can switch this out whenever, cool right. 43 00:02:26,140 --> 00:02:30,400 So now any one of our routes can use CourseDao. 44 00:02:30,400 --> 00:02:34,470 And we'll do something similar later with with our resources, okay. 45 00:02:34,470 --> 00:02:35,850 So, let's get started. 46 00:02:35,850 --> 00:02:39,230 So let's allow users of our API to create a new course. 47 00:02:39,230 --> 00:02:40,710 Now, how are they gonna do that? 48 00:02:40,710 --> 00:02:43,390 Well, Rest Standards would state that they make 49 00:02:43,390 --> 00:02:46,830 a post request to the plural name of the resource. 50 00:02:46,830 --> 00:02:49,570 We're gonna post to courses. 51 00:02:49,570 --> 00:02:50,770 Let's just do that. 52 00:02:50,770 --> 00:02:54,600 The static method post has an over ridden counterpart. 53 00:02:54,600 --> 00:02:56,990 So we're going to post to courses, and 54 00:02:56,990 --> 00:02:59,290 there's a parameter we haven't touched on before. 55 00:02:59,290 --> 00:03:04,310 And we're saying, if the request type is application JSON, so it will match 56 00:03:04,310 --> 00:03:09,270 anything that's a post to courses that has the request type of application/json. 57 00:03:09,270 --> 00:03:10,100 And then we're going to put in here, 58 00:03:10,100 --> 00:03:14,590 we're going to put in our little lambda of course. 59 00:03:14,590 --> 00:03:15,170 Like we always do. 60 00:03:15,170 --> 00:03:19,290 We're gonna say, return null, so it can figure out what we're talking about here. 61 00:03:19,290 --> 00:03:21,280 It has to return an object. 62 00:03:21,280 --> 00:03:23,885 So let's go ahead and let's statically import this post method. 63 00:03:27,250 --> 00:03:28,090 Here we go. 64 00:03:28,090 --> 00:03:28,900 Now it's happy. 65 00:03:28,900 --> 00:03:29,780 All right. 66 00:03:29,780 --> 00:03:34,230 So we need to get the JSON that's being passed across. 67 00:03:34,230 --> 00:03:38,340 So there is a method on the request object called body so req.body. 68 00:03:38,340 --> 00:03:41,290 And what that's going to do is that's going to return the json that they've 69 00:03:41,290 --> 00:03:41,871 sent across. 70 00:03:41,871 --> 00:03:44,373 So we know that it's gonna be JSON, right? 71 00:03:44,373 --> 00:03:49,060 Because we said it needs to come across as json, so we know that. 72 00:03:49,060 --> 00:03:51,730 So basically what we wanna do is you wanna take this json and 73 00:03:51,730 --> 00:03:53,360 we wanna create one of our courses from it. 74 00:03:53,360 --> 00:03:56,060 We're gonna create a brand new course from the json that they're suggesting. 75 00:03:56,060 --> 00:03:58,930 So, this is basically a form of serialization, right? 76 00:03:58,930 --> 00:04:00,960 So, we're gonna wanna consume the json and 77 00:04:00,960 --> 00:04:04,160 then later when we communicate we're gonna also wanna produce json. 78 00:04:04,160 --> 00:04:08,120 So, we could write our own serializer, but why would we go recreate the wheel, right? 79 00:04:08,120 --> 00:04:09,870 There's tons of open source tools. 80 00:04:09,870 --> 00:04:10,780 So, let's use one. 81 00:04:10,780 --> 00:04:13,290 Google has one called gson here. 82 00:04:13,290 --> 00:04:15,710 It's their repo is gson. 83 00:04:15,710 --> 00:04:17,520 You scroll down you can read a little bit about it. 84 00:04:17,520 --> 00:04:20,660 We'll get some hands on training here in a bit so. 85 00:04:20,660 --> 00:04:22,890 And then if you come here to Maven Central. 86 00:04:22,890 --> 00:04:27,710 You can go to the downloads here and if you scroll down here we are using Gradle. 87 00:04:27,710 --> 00:04:28,820 So if you come here. 88 00:04:28,820 --> 00:04:30,540 You can copy this. 89 00:04:30,540 --> 00:04:33,198 Copy this and we'll paste that over in our build.gradle. 90 00:04:35,256 --> 00:04:36,170 We'll put that here. 91 00:04:38,292 --> 00:04:41,590 I'm gonna go ahead and refresh the Gradle project. 92 00:04:41,590 --> 00:04:44,451 And now, let's go use it, so. 93 00:04:48,170 --> 00:04:53,428 Okay so we want to make a new course from our course. 94 00:04:53,428 --> 00:04:56,830 And we're gonna use that that gson object. 95 00:04:56,830 --> 00:04:59,360 So you know what all of these are probably gonna use that. 96 00:04:59,360 --> 00:05:02,990 So let's go ahead and let's put it up here up in this in the beginning part of our 97 00:05:02,990 --> 00:05:07,600 main method so the way that you do that is Gson gson = new Gson. 98 00:05:07,600 --> 00:05:10,590 That's kind of a play on json right so there's. 99 00:05:10,590 --> 00:05:15,120 Google and this is asking if it's the course and it is. 100 00:05:15,120 --> 00:05:20,817 Okay, so we have this is JSON here is the string has JSON so 101 00:05:20,817 --> 00:05:24,280 we want to say, gson.fromJson. 102 00:05:24,280 --> 00:05:26,930 We're gonna get the, you pass the first primary here's the string 103 00:05:26,930 --> 00:05:30,300 which is string JSON and then you tell it what class you wanna put it in. 104 00:05:30,300 --> 00:05:33,440 So we wanna put it in a Course.class and that's it. 105 00:05:33,440 --> 00:05:34,490 Isn't that cool? 106 00:05:34,490 --> 00:05:37,160 So, one thing I want to point out here though is that gson is not 107 00:05:37,160 --> 00:05:38,760 using the setter properties. 108 00:05:38,760 --> 00:05:41,180 What it's doing is it's actually using the private fields. 109 00:05:41,180 --> 00:05:43,360 That's just something I wanted to have you keep in mind. 110 00:05:43,360 --> 00:05:44,710 I dropped some info in the teacher's notes. 111 00:05:46,260 --> 00:05:49,990 So now we have a course object and we have our Dao object. 112 00:05:49,990 --> 00:05:53,301 So we can pretty much do what they're trying to do here, right? 113 00:05:53,301 --> 00:05:56,600 What they're trying to do specifically here is we're trying to add 114 00:05:56,600 --> 00:05:57,215 a course right? 115 00:05:57,215 --> 00:06:04,010 Cuz we're posting the courses so we can say courseDao.add(course). 116 00:06:04,010 --> 00:06:05,450 Look at that. 117 00:06:05,450 --> 00:06:08,730 So remember that course is going to set the the ID, when we do this, 118 00:06:08,730 --> 00:06:11,470 so it's gonna modify this course, it's gonna set the new ID, so 119 00:06:11,470 --> 00:06:13,160 we should probably send it back to them, right? 120 00:06:13,160 --> 00:06:14,070 That's kind of the standard. 121 00:06:14,070 --> 00:06:15,220 You add it and you send it back. 122 00:06:15,220 --> 00:06:18,750 So, also being a good API citizen, we should set our status, right? 123 00:06:18,750 --> 00:06:22,670 We should say the status was 201 which is created, right? 124 00:06:22,670 --> 00:06:28,790 And we should also let the caller know that what's coming to them is JSON. 125 00:06:28,790 --> 00:06:34,659 So we wanna say, our response type is also application/json. 126 00:06:37,100 --> 00:06:42,780 And then we want to return our course, now wait a second. 127 00:06:42,780 --> 00:06:45,310 How are they gonna read just our JavaScript object? 128 00:06:45,310 --> 00:06:45,920 That's right. 129 00:06:45,920 --> 00:06:48,190 We need to transform that back to JSON. 130 00:06:48,190 --> 00:06:51,110 So, the way that we do that is actually pretty cool and 131 00:06:51,110 --> 00:06:54,180 this is a method reference trick, okay? 132 00:06:54,180 --> 00:06:57,820 So, there's a final parameter here that these routes take and 133 00:06:57,820 --> 00:07:00,140 it's called a response transformer. 134 00:07:00,140 --> 00:07:02,120 And this is where we were putting our template thing before but 135 00:07:02,120 --> 00:07:04,280 you can actually just use a method reference right? 136 00:07:04,280 --> 00:07:08,180 All it needs is something that takes an object and returns a string. 137 00:07:08,180 --> 00:07:13,190 And so, guess what gson has that and it is called toJson. 138 00:07:13,190 --> 00:07:17,848 So what we're saying here is they're saying on this gson object run toJson on 139 00:07:17,848 --> 00:07:19,850 it and pass in this course. 140 00:07:19,850 --> 00:07:21,478 So this is called a method reference, so go ahead and 141 00:07:21,478 --> 00:07:22,625 check the teacher's notes on that. 142 00:07:24,130 --> 00:07:27,473 Since a response transform is just a single abstract method, 143 00:07:27,473 --> 00:07:31,020 we can pass anything here that matches that method declaration. 144 00:07:31,020 --> 00:07:33,220 And it just so happens that toJson does. 145 00:07:33,220 --> 00:07:36,590 So we're basically just returning a straight Json representation of our 146 00:07:36,590 --> 00:07:37,280 course object. 147 00:07:37,280 --> 00:07:40,140 If we wanted more fancy stuff we could write a custom method here that would 148 00:07:40,140 --> 00:07:44,800 do other things like ATOS or hyper media as the engine of applications that. 149 00:07:44,800 --> 00:07:47,420 Check the teacher notes, I don't want to get too far from her task at hand. 150 00:07:48,460 --> 00:07:52,190 So speaking of which, let's write the get portion for the courses and point. 151 00:07:52,190 --> 00:07:54,430 So this one, we wanna return all the courses. 152 00:07:54,430 --> 00:08:03,490 So, that would be using the same courses end point, but on a get, right? 153 00:08:03,490 --> 00:08:06,500 And so we wanna return application Json. 154 00:08:06,500 --> 00:08:09,720 We only want to, if they make the request with application Json, 155 00:08:09,720 --> 00:08:11,870 we want to return application json. 156 00:08:11,870 --> 00:08:18,220 And we're going to do req, res, and we have that already don't we? 157 00:08:18,220 --> 00:08:19,954 We have courseDao.findall(). 158 00:08:21,430 --> 00:08:26,250 And we can also can just turn that right straight into Json right? 159 00:08:26,250 --> 00:08:30,690 So method parameter there toJson right? 160 00:08:30,690 --> 00:08:33,390 So well, there's a single line, now wait a second. 161 00:08:34,750 --> 00:08:39,300 We have this all on a single line, so I can kick this down like this. 162 00:08:40,730 --> 00:08:46,690 While this is all fitting on a single line we forgot to set the type to be Json but 163 00:08:46,690 --> 00:08:50,890 you know what everything that we send out of our API here that is going to be Json. 164 00:08:50,890 --> 00:08:54,500 So why don't we just use one of those filters remember those. 165 00:08:54,500 --> 00:08:58,290 So the filter, we'll run after each one of these requests. 166 00:08:58,290 --> 00:08:59,500 Let's go ahead and kick that up a bit. 167 00:08:59,500 --> 00:09:04,270 So we're gonna say after, in time after request response. 168 00:09:06,890 --> 00:09:13,059 We wanna set res.type application/json, 169 00:09:13,059 --> 00:09:17,054 and we will go ahead and, it doesn't know what type is, 170 00:09:17,054 --> 00:09:22,250 because it doesn't know what after is yet, so once I do this, boom. 171 00:09:22,250 --> 00:09:25,050 Okay, and we'll put a semicolon here. 172 00:09:25,050 --> 00:09:26,600 So now we can remove this, right? 173 00:09:26,600 --> 00:09:30,630 Because every single response that we send is gonna have the, at the end. 174 00:09:30,630 --> 00:09:33,980 It's gonna have application json, awesome. 175 00:09:35,430 --> 00:09:37,400 Okay, you know what? 176 00:09:37,400 --> 00:09:40,040 We should make it so that we can find a specific course by ID. 177 00:09:40,040 --> 00:09:43,090 So let's see let's start at the end point first and 178 00:09:43,090 --> 00:09:44,560 then we'll work our way backwards right? 179 00:09:44,560 --> 00:09:51,610 So if we wanna find a course by id we would do this we'd say get courses ID and 180 00:09:51,610 --> 00:09:58,670 then again it's gonna be application/json. 181 00:09:58,670 --> 00:10:06,350 And we're going to do req, res. 182 00:10:06,350 --> 00:10:08,930 And we're definitely going to transform whatever we get back so 183 00:10:08,930 --> 00:10:11,780 let's just go ahead and do that so gson toJson. 184 00:10:11,780 --> 00:10:13,060 The lamda method reference there. 185 00:10:14,060 --> 00:10:14,560 Okay. 186 00:10:15,580 --> 00:10:19,935 So, remember you can pull these things off from a thing called 187 00:10:19,935 --> 00:10:24,320 req.params, and it's, you put the name in there, right? 188 00:10:24,320 --> 00:10:28,200 And, we'll return null so it knows what we're talking about. 189 00:10:28,200 --> 00:10:32,105 Okay, so we want to pull that off so 190 00:10:32,105 --> 00:10:40,090 we will say int id = Integer.parseInt then we'll pull out that. 191 00:10:40,090 --> 00:10:44,870 Well, it's a little bit dangerous because what if that's not an ID? 192 00:10:44,870 --> 00:10:47,970 But, we can deal with that later. 193 00:10:47,970 --> 00:10:49,930 All right, so then what we can do, 194 00:10:49,930 --> 00:10:52,790 this is kind of the way of designing an API backwards, right? 195 00:10:52,790 --> 00:10:55,430 So we can say we want to get this thing, 196 00:10:55,430 --> 00:10:59,420 we wanna get a course out, and we know that we have this Dao object. 197 00:10:59,420 --> 00:11:00,750 So we'd say courseDao.find. 198 00:11:00,750 --> 00:11:03,770 Well, if we have find all, let's do findById. 199 00:11:03,770 --> 00:11:04,660 That makes sense, right? 200 00:11:04,660 --> 00:11:07,780 And we'll pass in the id so we'll do that and then we'll do course. 201 00:11:07,780 --> 00:11:11,750 So now we have written this in point for something that we don't even have yet. 202 00:11:11,750 --> 00:11:13,930 You know what happens if it's not found? 203 00:11:13,930 --> 00:11:14,650 Let's put it to do there. 204 00:11:14,650 --> 00:11:22,170 Let's remember that to do just the, what if this is not found? 205 00:11:24,200 --> 00:11:29,370 Okay, so let's go ahead and we'll experience the power of the id. 206 00:11:29,370 --> 00:11:30,720 Let's make it do the work for us. 207 00:11:30,720 --> 00:11:36,060 So, I'm gonna go ahead and use the action here, say create method, find by Id. 208 00:11:37,350 --> 00:11:38,690 So, here it is. 209 00:11:38,690 --> 00:11:40,470 Well, that was exactly right. 210 00:11:40,470 --> 00:11:45,707 Now let's pop over to the Sql2o course Dao Implementation, 211 00:11:45,707 --> 00:11:48,130 Sql2o of CourseDao pop in here. 212 00:11:48,130 --> 00:11:50,260 And if we look it's squiggly red, 213 00:11:50,260 --> 00:11:53,640 because we don't implement that new method that just got created, so let's do it. 214 00:11:53,640 --> 00:11:55,060 Let's say implement methods. 215 00:11:55,060 --> 00:11:56,148 We wanna do the find by course. 216 00:11:56,148 --> 00:12:00,764 Perfect, okay and it has also taken in id, so 217 00:12:00,764 --> 00:12:05,257 we need to do again we're gonna say try, and 218 00:12:05,257 --> 00:12:10,010 we'll pull Connection con = sql2o.open. 219 00:12:12,667 --> 00:12:15,567 And again that will automatically close it and so 220 00:12:15,567 --> 00:12:18,290 we're going to return con.createQuery. 221 00:12:18,290 --> 00:12:19,890 And it's very similar to the one above. 222 00:12:19,890 --> 00:12:25,220 We're going to say select star from courses where id is equal to. 223 00:12:25,220 --> 00:12:27,130 And we're going to to do a named parameter here and 224 00:12:27,130 --> 00:12:29,440 that looks very familiar to the other ones right? 225 00:12:29,440 --> 00:12:31,570 And we're gonna continue here and we're gonna say addParameter, 226 00:12:31,570 --> 00:12:32,900 because that's how you name the parameter. 227 00:12:32,900 --> 00:12:37,530 We're gonna say, anytime it says id, pass in our id from above. 228 00:12:37,530 --> 00:12:41,640 And then finally, we're going to execute and fetch. 229 00:12:41,640 --> 00:12:43,750 Now before we did executeAndFetch and returnToList, but 230 00:12:43,750 --> 00:12:45,710 there's one called first. 231 00:12:45,710 --> 00:12:47,410 And that will just get the first one, cuz that's what we want. 232 00:12:47,410 --> 00:12:49,160 We want a specific one. 233 00:12:49,160 --> 00:12:51,760 That's Course.class. 234 00:12:51,760 --> 00:12:52,970 Sorry about that. 235 00:12:52,970 --> 00:12:53,790 Everything's on top of it. 236 00:12:53,790 --> 00:12:56,710 So executeAndFetchFirst(Course.class). 237 00:12:56,710 --> 00:12:57,220 Boom. And 238 00:12:57,220 --> 00:13:00,020 I will get rid of this trailing return at the bottom here. 239 00:13:00,020 --> 00:13:01,500 So we've got executeAndFetchFirst. 240 00:13:01,500 --> 00:13:03,350 So that looks like it should work. 241 00:13:03,350 --> 00:13:04,590 So you know what? 242 00:13:04,590 --> 00:13:07,720 While we're in here why don't we just generate a test for this, right? 243 00:13:07,720 --> 00:13:10,140 So we'll go to, we'll go to the test. 244 00:13:11,760 --> 00:13:18,990 Just here and let's go ahead and say, we'll make a new test. 245 00:13:18,990 --> 00:13:23,265 New test method and we'll say 246 00:13:23,265 --> 00:13:30,292 existingCoursesCanBeFoundById, all right. 247 00:13:30,292 --> 00:13:33,670 So we'll do a course. 248 00:13:33,670 --> 00:13:35,800 This is starting to feel duplicative isn't it. 249 00:13:35,800 --> 00:13:39,800 Course = new Course, yeah. 250 00:13:39,800 --> 00:13:42,040 This is, we need to do something about this. 251 00:13:42,040 --> 00:13:45,845 Maybe somebody can help us out here, test.com. 252 00:13:45,845 --> 00:13:47,980 Cuz we are definitely repeating ourselves every time we do that. 253 00:13:47,980 --> 00:13:49,840 So we're gonna add the course here in the set up, 254 00:13:49,840 --> 00:13:52,650 we're gonna arrange, add the course and then 255 00:13:52,650 --> 00:13:56,520 the action that we're gonna do is we're gonna try to use that method we just did. 256 00:13:56,520 --> 00:14:01,340 We're gonna say foundCourse = dao.findById and 257 00:14:01,340 --> 00:14:05,480 we're gonna pass in that course we created getId. 258 00:14:05,480 --> 00:14:09,060 Cuz remember that gets set on this add we're going to set that ID, 259 00:14:09,060 --> 00:14:12,550 so then we'll just make sure that the two are equal. 260 00:14:12,550 --> 00:14:15,130 Now again it's using the object equals, so 261 00:14:15,130 --> 00:14:17,960 it's checking that all of the fields are the same. 262 00:14:17,960 --> 00:14:19,315 Which is exactly what we want to do right? 263 00:14:19,315 --> 00:14:20,950 Cuz it's gonna be two separate objects. 264 00:14:20,950 --> 00:14:24,990 It's gonna be one that was created here, and one that's returned and 265 00:14:24,990 --> 00:14:28,920 populated from our Dao object, cool. 266 00:14:28,920 --> 00:14:30,960 Okay so, that looks sane, so let's go ahead, and we'll run that. 267 00:14:36,260 --> 00:14:37,370 Okay, cool. 268 00:14:37,370 --> 00:14:38,830 They all passed. 269 00:14:38,830 --> 00:14:43,070 And, let's go ahead and take care of that course creation thing, okay? 270 00:14:43,070 --> 00:14:44,680 So, I'm gonna highlight over here, 271 00:14:44,680 --> 00:14:47,220 I gonnas highlight this, cuz this is just too much. 272 00:14:47,220 --> 00:14:48,980 And, I wanna put that into its own method. 273 00:14:48,980 --> 00:14:50,170 So, I'm gonna say refactor, 274 00:14:50,170 --> 00:14:55,380 and do refactor this I'm going to choose extract it to a method. 275 00:14:55,380 --> 00:15:02,380 And let's not call it get test let's call it newTestCourse. 276 00:15:02,380 --> 00:15:05,720 Right that's that's a good name for it we know what that means so I'll click Okay. 277 00:15:05,720 --> 00:15:07,710 Look. It found that there's two code fragments 278 00:15:07,710 --> 00:15:09,890 that can be replaced which is exactly what we're trying to do and 279 00:15:09,890 --> 00:15:14,500 let's say yes and, we'll replace that occurrence, and that one. 280 00:15:14,500 --> 00:15:18,450 Yep, perfect and so, now it follows exactly what we want. 281 00:15:18,450 --> 00:15:19,630 We can run one more time. 282 00:15:19,630 --> 00:15:23,690 We are following our best practices, even in our tests. 283 00:15:23,690 --> 00:15:24,480 Isn't that cool? 284 00:15:24,480 --> 00:15:25,710 We don't want to repeat ourselves. 285 00:15:25,710 --> 00:15:27,060 Awesome, everything's working. 286 00:15:27,060 --> 00:15:28,530 Great job. 287 00:15:28,530 --> 00:15:31,400 Wow, it feels so good to test and know that things are working. 288 00:15:32,740 --> 00:15:35,900 We really should test our API both manually and then, 289 00:15:35,900 --> 00:15:36,770 of course, functionally. 290 00:15:36,770 --> 00:15:39,910 You know, so we can be rest assured that all is working. 291 00:15:40,960 --> 00:15:43,650 Why don't we take a swing at that testing right after this short break?