Full Stack Development with Java Spring Boot, React, and MongoDB – Full Course

Full Stack Development with Java Spring Boot, React, and MongoDB – Full Course


Full Stack Development with Java Spring Boot, React, and MongoDB – Full Course

In this full stack development course, you will learn how to create an application using MongoDb for the database, Java and Spring Boot for the backend, and React for the frontend.

You will learn to develop a movie review application that will feature a separation of concerns between the client code and the server code. By implementing this loosely coupled architecture, these two parts (implemented using different technologies) can evolve in parallel and independently from one another.

✏️ Farhan Hasin Chowdhury teaches the backend section.
✏️ Gavin Lon teaches the frontend section. @GavinLon

💻 Backend Code: https://github.com/fhsinchy/movieist
💻 Frontend Code: https://github.com/GavinLonDigital/mo

🔗 Spring Initializr - https://start.spring.io/
🔗 JDK Download Page: https://www.oracle.com/java/technolog
🔗 IntelliJ IDEA Download Page: https://www.jetbrains.com/idea/download/
🔗 Postman Download Page: https://www.postman.com/downloads/

🏗 MongoDB provided a grant to make this course possible.

⭐️ Contents ⭐️
⌨️ (0:00:00) Course Introduction
⌨️ (0:01:48) JDK and IntelliJ IDEA Installation
⌨️ (0:06:13) MongoDB Atlas
⌨️ (0:20:35) Project Initialization
⌨️ (0:27:03) Project Structure
⌨️ (0:29:13) Running The Project
⌨️ (0:32:41) Writing The First Endpoint
⌨️ (0:35:33) Database Configuration
⌨️ (0:38:49) Installing Additional Dependencies
⌨️ (0:44:48) Setting Up Environment Variables
⌨️ (0:47:20) Movies and Reviews Endpoints
⌨️ (1:31:46) Testing
⌨️ (1:35:42) Backend Conclusion

⌨️ (1:36:45) Frontend Introduction
⌨️ (1:38:32) Create the React Project
⌨️ (1:43:49) Applying Bootstrap to our React application
⌨️ (1:52:47) Implementing the Use State and Use Effect Hooks
⌨️ (1:58:04) Create Home and Hero Component
⌨️ (2:06:56) Style the Carousel
⌨️ (2:15:21) Create Header Component (Navigation)
⌨️ (2:21:55) Create Trailer Component with react-player
⌨️ (2:28:46) Create Movie Reviews Functionality
⌨️ (2:34:43) Add and Get Reviews with HTTP Requests
⌨️ (2:40:33) Course Wrap Up

🎉 Thanks to our Champion and Sponsor supporters:
👾 Nattira Maneerat
👾 Heather Wcislo
👾 Serhiy Kalinets
👾 Erdeniz Unvan
👾 Justin Hual
👾 Agustín Kussrow
👾 Otis Morgan



Learn to code for free and get a developer job: https://www.freecodecamp.org

Read hundreds of articles on programming: https://freecodecamp.org/news


Content

0 -> In this course, you will learn how to create a full stack
2.61 -> application using MongoDB for the database, Java and Spring
7.17 -> Boot for the back end and react for the front end. Farhan Hasin
11.85 -> Chaudry teaches the back end section of this course. And
15 -> Gavin Lon teaches the front end section of the course. Both
18.42 -> these instructors are very experienced and have created
21.48 -> many popular courses. The project featured in this course
24.93 -> is a great example of the creation of a separation of
28.17 -> concerns between the client code and the server code. By
32.4 -> implementing a loosely coupled architecture. These two parts
36.66 -> implemented using different technologies can evolve in
40.14 -> parallel and independently from one another. So let's start
43.83 -> learning from Farhan. Hello, everyone. Welcome to the Java
47.88 -> with MongoDB course on the freeCodeCamp YouTube channel.
52.17 -> I am for Han has ensured three one of the instructors in this
55.11 -> course and I will teach you all about developing a back end API
59.67 -> using Java EE Spring Boot, and MongoDB. The other half of the
64.14 -> course will be taught by Katherine lOn. Hi, I'm Gavin
67.53 -> lOn. I'm a full stack developer and have over 20 years
71.22 -> experience working as a software developer. In this course, I'm
75.12 -> going to be playing the role of a front end developer. And my
78.24 -> responsibility will be to demonstrate building a front end
82.41 -> using React js. The Spy application that we are going to
86.52 -> create will use HTTP GET requests to appropriately
90.57 -> retrieve data from a remote server through communicating
94.14 -> with the relevant API's endpoints. And HTTP POST
98.31 -> requests will also be made to the relevant endpoints to
101.55 -> appropriately save data on the server side. Of course, our data
106.32 -> will be stored within a MongoDB database on the relevant remote
110.46 -> server. So without further ado, let's jump in and start working
115.05 -> on our API. In the beginning of the course, you will have to
118.89 -> download two new software's from the internet. The first one
122.37 -> being Java Development Kit, or JDK. If you already have JDK
127.62 -> installed on your system, you should be good to go with that.
130.68 -> But just in case you do not have it installed, I'd suggest you
134.37 -> navigate to oracle.com/java/technologies/downloads
140.13 -> The link will be in description. Once you have landed on the
143.64 -> download page for Java, you may find multiple versions of JDK
148.14 -> available as of the recording of this course there. The latest
152.52 -> version is Java 19. And the latest LTS version is Java 17.
157.83 -> lts C stands for long term support and JDK 17 will receive
162.93 -> updates until September 2020 For
168.27 -> JDK 19 On the other hand, will receive updates only until March
172.74 -> 2023 and will be superseded by JDK 20. In many cases, when you
177.42 -> are deploying a Java application on a production server, it's
180.27 -> suggested that you use LTS release for better stability.
185.52 -> And for this course I will stick to Java 17 Since that's the
189.3 -> latest LTS. Now depending on when you're watching this
193.74 -> course, there may be a new LTS release so feel free to download
197.43 -> and install that. So I've switched to Java 17 And since I
200.88 -> am on Windows, I will go to windows and the 64 bit
204.39 -> installer. As you can see, it's only 150 2.85 megabytes and
209.19 -> depending on your internet connection, you it may take a
212.1 -> few minutes to download.
214.5 -> Once you have downloaded the installer, make sure you have
216.99 -> installed it on your system like any other software you have done
220.14 -> before. And since the instruction is so
222.9 -> straightforward, I will not spend a lot of time showing you
226.26 -> the entire process.
229.86 -> After you have finished installing JDK on your computer,
232.77 -> open up your terminal window and write Java C space double dash
239.58 -> barsha.
241.26 -> And if you don't get any errors from this command, this is a
245.76 -> positive sign and as it says Java C 17 point 0.5 which
250.44 -> indicates that I have successfully installed seven
254.31 -> point 17 point 0.5 version of the JDK. Now Java C is the short
258.18 -> for Java compiler which you may or may not have already guessed.
262.32 -> Apart from this command, you can also use Java double dash
266.31 -> version to check the version of your Java Runtime Environment
270.69 -> and as you can see it says 17 point 0.5 lts which means we are
275.1 -> good to go.
277.83 -> Since you have successfully installed the jdk on your
280.56 -> computer Next up you will need a good code editor or IDE. When it
286.47 -> comes to Java, there are plenty of options out there. You can go
289.68 -> into Eclipse or maybe configure Visual Studio code. But I would
294.3 -> suggest that you go with IntelliJ IDEA. Now the people at
299.55 -> Jet
300 -> Ian's are known for making really good IDE s and when it
303.81 -> comes to Java IntelliJ IDEA is pretty much the industry
307.68 -> standard.
309.36 -> Although the ultimate version can cost you some money, there
312.81 -> is also a free version available by the name of Community
316.35 -> Edition. Or to download IntelliJ IDEA, navigate to
320.97 -> jetbrains.com/ideas/download. Again, the link could be in
325.41 -> description and look for the Community Edition. This is the
329.1 -> flag download button here. And depending on your platform, ie
333.42 -> Windows, Mac OS or Linux, you may get a different format. For
337.92 -> example, if you're on Mac OS, you will get a DMG image. And if
342.33 -> you're on Linux, you will get a tar file. So I'm on Windows and
346.29 -> I want to download the exe installer and not the zip one.
349.56 -> So I'll select exe, and then hit download. Now the IDE is a bit
356.28 -> larger than the JDK in size at 649 megabytes. But again,
362.1 -> depending on your internet connection, it may take a few
364.98 -> minutes to download. Once you have downloaded the software,
367.86 -> please go ahead and install it like any other software that you
370.92 -> have done before.
374.76 -> Congratulations on you're getting the JDK and IntelliJ
378.87 -> IDEA getting installed. Next up, you will need an account at
383.01 -> MongoDB Atlas. Now you may or may not already know that
387.27 -> MongoDB Atlas is a platform from MongoDB themselves that allows
392.88 -> you to spin up MongoDB servers on the cloud.
398.37 -> So in order to use MongoDB Atlas, you will have to maybe
401.64 -> get to mongodb.com/atlas/database.
406.05 -> Again, the link will be in description and use the Sign In
409.35 -> button.
414.09 -> Once in the sign in page, you can either use your Google or
417.63 -> GitHub account to log in or you can sign up with your other
421.11 -> email addresses for a new account. Now, I already have an
425.13 -> account on MongoDB Atlas. So I will just use those credentials
429.84 -> to log into my account off screen. As you can see, I have
433.29 -> successfully logged into my account. And For first time
437.25 -> users, you may have to set up a new organization of sore just
442.47 -> just put any name as the organization name and you should
446.25 -> be good to go. Since we are using these for just our
449.88 -> development purposes, it's okay to just use any data that you
453.87 -> have. So once you have set up your organization, you can
458.91 -> create new projects. So I will hit the New Project button here.
464.79 -> And I have to give my project a name. Now since you are creating
468.96 -> an API that is related to movie I'll just call my movie API. And
475.35 -> hit Next
477.72 -> I will just go ahead and create project since I don't have any
481.53 -> other member to add.
493.74 -> Extra now we are inside our movie API project. And we are
498.45 -> ready to create a new database. So you can use the builder
502.56 -> Database button here to create a new MongoDB database on MongoDB
506.25 -> Atlas. So just go ahead and click this button.
510.75 -> And there are three different categories there is server list
514.83 -> there is dedicated and there is shared. Now for development
518.4 -> purposes, our shared server should be fine and it's
521.64 -> completely free. But if you're working on an application that
526.26 -> that has some user and have some real life usage, you may go with
531.66 -> dedicated Serverless is something else and maybe we can
534.84 -> talk about it in a different course some other day. So select
540.03 -> Share, and hit create.
545.76 -> Okay, next up, they will ask you about which provider you want to
549.3 -> use, I always go with AWS. Since AWS has a server on Mumbai,
554.7 -> which is near Bangladesh and has the lowest ping for me, but if
559.8 -> you like you can go with Google Cloud or Azure. Now select
564.27 -> whatever region is the nearest to you to make sure that you are
568.77 -> getting the lowest amount of being possible. Next, you can
573.48 -> choose a dear.
575.85 -> Again, for free usage, we use the aim zero sandboxed here it
581.55 -> will give us 512 megabytes of RAM which is more than enough
586.47 -> for our usage we will have a very small amount of data to be
590.01 -> honest. And then next step there are additional settings you
594.9 -> don't have to touch them and the cluster name. Now you can
598.29 -> customize the cluster name if you
600 -> Wish but I will just leave it as cluster zero since I like it
604.2 -> that way, then hit Create cluster
611.07 -> Okay, next up, you will have to create a new user for this
615.39 -> cluster. You can also use an SSH certificate, but I will just go
620.52 -> with the old trusty username thing. So I will name my
625.59 -> usernames Solid Snake since I'm a Metal Gear Solid fan, but you
630.78 -> can name it anything you want. Now, when it comes to password,
634.41 -> make sure you are always choosing a very strong password
637.98 -> and not ones that are easy to remember. Use a password manager
643.26 -> maybe but always use hard to guess passwords. So I will just
647.4 -> use the auto generated secure password.
650.79 -> And I will also make sure that I am copying my password to the
654.42 -> clipboard, since I will be needing this later on. But then
657.87 -> hit the Create User button.
662.4 -> It shows Solid Snake and the password.
666.24 -> And finally, you will have to set up some IP access list. So
671.01 -> the way it works, once you have set up a new database, you will
675 -> have to allow a set number of IP addresses that can access that
679.77 -> server. You know opening up a database server to the world is
684 -> not a good idea. Security wise, so you should always use your
689.64 -> current IP address here.
692.49 -> But since this is just a course, and we are using this database
696.66 -> for development, I will open up the server for all the IP
700.53 -> addresses out there. And to do that, you can write 0.0 dot 0.0
705.96 -> slash zero and in the description, you can just write
712.17 -> a view
714.3 -> and hit Add Entry. See that that's there. And then click on
719.4 -> finish and close.
721.53 -> Okay, they will congratulate you and whatnot Hi quickstart guide
725.04 -> Yes, go to database
730.98 -> disclose it.
733.26 -> Excellent. Now we have a database up and running on
737.25 -> MongoDB Atlas. And we can use this database ganache to eat
741.48 -> read and write data from and to eat.
744.69 -> And using just like a local database that you may have used
748.14 -> in your computers, you see MongoDB Atlas is a very
751.5 -> beautiful service. I have used it for development as well as
755.25 -> for production in the past and I have never had any bad
760.14 -> experiences with it.
763.17 -> So next up, you can use some sort of database client to
767.22 -> connect to this database, maybe something like MongoDB compass,
772.32 -> so you can go ahead and click on Connect.
777 -> And MongoDB will give you multiple options that you can
780.9 -> choose from. So first, you can connect to your database server
784.47 -> using MongoDB shell, you can connect to the MongoDB server
787.92 -> using your application that you're working on right now, you
792.66 -> can connect to MongoDB server using MongoDB compass which is
797.49 -> MongoDB own graphical user interface for working with
800.94 -> databases and I will just show you that. Finally you can also
805.38 -> connect using VS code. And let's be connect using MongoDB compass
809.88 -> for now.
812.52 -> And I do not have MongoDB compass on my computer. So I
817.8 -> will be Windows 64 bit
824.82 -> and I will just hit download compass.
829.41 -> Once you have downloaded and installed MongoDB compass on
832.71 -> your computer, you can start the software from your start menu or
837.21 -> desktop. Once you start MongoDB compass it looks something like
841.17 -> this where they are giving you the option to connect to a new
846.99 -> database by using this kind of URI. Now where do you get this
853.68 -> URI. If you come back to MongoDB Atlas, you will see that they
859.2 -> are actually giving that URI right here.
863.28 -> Just use this copy button to copy the entire URI and go back
869.4 -> to MongoDB compass. Now remove this localhost URI from here and
875.28 -> paste it yours. Now as you can see it says MongoDB plus SRV
880.53 -> Benue username, followed by a colon and then it's looking for
886.53 -> a password right. So what we are going to do, we will use the
891.03 -> password that we created earlier and paste it in here. And then
896.49 -> we'll leave everything as is and we
900 -> He can say Save and connect. You can name it anything. So I'm
905.46 -> naming it V Avi,
908.55 -> you can change its color if you want to, and say Save and
911.85 -> connect.
914.37 -> Okay, so it took a few seconds. And as you can see, we have
918.18 -> successfully connected to our moving API cluster. Now, as you
922.41 -> can see, there are two databases, one of them is called
926.16 -> admin. And the other one is called Local. Now, we do not
930.51 -> have to do anything with these, these come by default with all
935.79 -> the clusters out there. So just leave them be and we will create
940.32 -> new databases very soon. To create a new database, you can
944.1 -> always go and click this plus sign.
948.87 -> And inside database name,
952.29 -> let's put b
956.13 -> What really, let's call it movie,
960.9 -> API deep.
963.6 -> And inside collection them. Now if you're new to databases, like
969.6 -> like MongoDB, or document based database, you may or may not
974.7 -> know that collections are like tables in case of relational
980.64 -> database systems. So in something like MySQL, or Oracle
985.17 -> database system, you have databases, and inside those
989.61 -> databases, you have tables. Now, in case of MongoDB, and other
996.09 -> non relational databases, you have the database name first,
1000.14 -> and then collections. For example, in our cases, we will
1006.08 -> have a collection of movies where we will save information
1011.06 -> about different movies. So we can say movies and in create
1018.5 -> database. So as you can see, we have a new database sitting here
1023.45 -> movie API dv, and there is a collection called movies. So
1027.59 -> right now, there is no data at all.
1033.11 -> Now in order to work with our API, it would be convenient if
1036.77 -> we have a bunch of data in our collections. And if you navigate
1041.42 -> to github.com/ach, si n ch y, which is my username and slash
1047.6 -> movies, you will get the entire code for this API already
1052.16 -> written. And inside that repository, you will see a
1055.19 -> folder that says underscore data. Now inside this folder,
1060.26 -> there is a JSON file that you can use as a source of data for
1065.6 -> the collection we have just created. So I would suggest you
1070.01 -> go into this JSON file, then select raw,
1075.05 -> and then hit CTRL S and say this JSON file somewhere on your
1079.88 -> computer.
1082.94 -> So once you have downloaded the file, you can then import it to
1086.78 -> your collection. To do so, come back to MongoDB compass. And
1092.75 -> while you have the movies collection selected, you can
1096.89 -> click on this Import Data button or this Add Data button. Then
1101.75 -> select Import File. And our format is JSON. And we'll select
1107.45 -> the file from our downloads and movies dot JSON. And you can
1112.58 -> also take a stop on errors, then hit import, wait a few moment.
1118.28 -> It done. And viola, we have the information of n different
1124.34 -> movies on our database. So as you can see,
1128.9 -> each of this movie is a document Okay, as it as it says documents
1135.35 -> then. So inside the collection, each of this movie are a single
1141.17 -> document. And what do we have inside these documents? Well, we
1146.09 -> have an ID we have the IMDB ID for this title whose inputs, we
1152.54 -> have the release date, which is a string, we have the link for a
1156.5 -> trailer on YouTube. Then we have an array of genres. So this
1162.53 -> particular movie belongs to five genres. Then we have a link to
1168.83 -> our poster.
1171.56 -> We have linked to end backdrops that will be later utilized in
1176.84 -> the front end application as you can see, finally, we have an
1181.88 -> empty array for review IDs. Now, this will come into play later
1186.38 -> on in this course, so just be patient with me for now.
1191.39 -> Okay, so one thing that I'd like to mention right here I am using
1196.22 -> the tmdb.org API for this
1200 -> images are TMDb is an excellent website. And they provide a free
1206.09 -> to use API for developers as long as you are giving them
1210.83 -> credit. So I do, so I will be using the API for portraying the
1216.05 -> images. So now that we have created a new database on
1220.37 -> MongoDB. Plus, we have set up a new collection, we have imported
1225.77 -> some data into it, it's time for us to start working on our API
1231.92 -> code.
1235.25 -> Now the first step to writing our API using Spring Boot, is to
1239.36 -> initialize it first. To do that, navigate to start.spring.io.
1245.15 -> Again, links will be in the description. And let's start
1248.45 -> initializing our project. First, we'll have to pick a programming
1253.19 -> language, which is going to Java in this case. But if you're
1256.88 -> familiar with groovy or Kotlin, you may go with them, then we
1261.86 -> will have to pick a project autumn build automation tool.
1265.28 -> And the initializer supports both Gradle and Maven which are
1270.56 -> not the most popular build automation tool for Java, I am
1273.83 -> doing with Maven, simply because I have more experience working
1277.64 -> with this then Gradle. Next up, picking up the Spring Boot
1282.41 -> version 3.0. Point one is the latest stable version. And we
1286.91 -> will be using that throughout the course. But if you would
1290.42 -> like to try out some more bleeding edge features, you can
1293.78 -> use the snapshots once you have become more familiar with the
1297.8 -> framework.
1300.05 -> After that, we will have to fill up the project metadata.
1305.21 -> Now the group is usually written in reverse domain format. So for
1310.58 -> example, my website is Farhan dot Dev. And I would like to
1316.79 -> name my group date dot for her. So if you do not have a domain
1322.91 -> of yourself, you can name it anything you like, as long as
1327.86 -> that package group is not referring to someone else's
1331.97 -> project
1334.01 -> nextra that artifact name, the artifact name is simply the name
1338.63 -> of the project. So in this case, I will be putting movies in
1343.55 -> here, but feel free to call in something else if you feel like
1348.08 -> that.
1349.64 -> Next there is a description field and you can put something
1353.18 -> like
1361.07 -> after that, we will have to pick up packaging for now java is a
1365.69 -> very popular packaging format for Java and it stands for Java
1370.79 -> archive wire. On the other hand, it stands for web archive. And
1375.41 -> you may think that will wire is more suited for this project
1379.28 -> since it's going to be a web application, right? Maybe yes,
1383.72 -> but since jar is more widely used than where I will be going
1388.79 -> with.
1390.5 -> Next speaking the Java version, obviously, I'm going to pick 17,
1394.64 -> since we just spent quite some time setting up Java 17 on our
1399.5 -> computers. Once you are done with the left column, let's
1403.25 -> focus on the right column. In this one, you will have to pick
1408.29 -> the dependencies that you would like to use in your project. So
1412.7 -> use this add button, and you will be presented with a long,
1417.32 -> very long list of dependencies. And the first one that we are
1420.86 -> going to use in our project is Lombok, it's an additional
1425.27 -> library that saves you from writing a lot of boilerplate
1429.11 -> code. And you will see what I mean in action very soon. So
1434.99 -> please be patient. Since we are going to pick multiple
1440.6 -> dependencies, you will have to keep pressing either Ctrl on
1446.27 -> Windows or Linux and command on Mac. In fact, it says here,
1451.01 -> right on the right corner press Control to multiple apps. Okay
1455.15 -> for multiple ads, so I'm pressing down on control and I
1458.9 -> will pick Lombok
1461.36 -> Lombok has been picked. Next up spring web.
1466.79 -> And finally,
1470 -> let's see.
1472.46 -> No nada SQL under no SQL, we will need Spring Data MongoDB
1480.32 -> Yeah, that's that's pretty much it. You can also search for
1485.48 -> things here, for example, dev tools, and let's add that as
1490.13 -> well. Once done, you can exit out of this selector by pressing
1494.75 -> Escape on your keyboard and have a look at the list of
1497.93 -> dependencies and make sure you have the
1500 -> Everything. Now there are other dependencies that you may learn
1504.74 -> about later on, such as the reactive web,
1509.57 -> or Graph QL, or rest repositories or something like
1514.76 -> maybe spring security, which can be used for authentication and
1518.51 -> authorization. There is more to client if you're into auth, and
1522.2 -> things like that. But since we will not be getting into
1525.59 -> authentication and authorization in this course, we will stay out
1529.61 -> from the
1531.23 -> get go. Once you are happy with the configuration in this
1534.41 -> initializer to go ahead and click Generate.
1541.28 -> It will take a few seconds to generate the SIP archive, and it
1545.57 -> will start downloading automatically. Once downloaded,
1549.14 -> you have to extract these movies dot zip or whatever you have
1553.85 -> named your artifact dot c file to somewhere in your computer
1559.16 -> easily accessible.
1563.36 -> After you have extracted the downloaded zip file somewhere on
1567.41 -> your computer, you can go ahead and open it in your favorite IDE
1572.3 -> or code editor. In my case, it's IntelliJ IDEA and I have
1577.04 -> extracted my project on my D drive.
1580.49 -> So I will go ahead and click on open first.
1585.98 -> Then come to the folder where I have extracted the project and I
1592.7 -> will pick it up.
1594.98 -> Okay, so IntelliJ IDEA will ask whether you actually just this
1599.15 -> project or not. This is a safety feature to save you from
1602.15 -> malicious code from running on your computer. So since we are
1605.66 -> writing it ourself, I just pick trust project.
1612.65 -> And give ideas some time for resolving all the dependencies.
1618.17 -> And once it's ready, you are free to go.
1625.58 -> Let's try to understand the project structure first. So
1629.42 -> ignore the dot env and folder, it's managed by Maven. So you
1633.77 -> don't have to worry about it right now. There is the src
1637.58 -> folder, which is short for source. And it will contain your
1642.41 -> program source code as well as the test code. So we are not
1645.5 -> going to write any tests. So let's jump into the main folder.
1649.82 -> So inside main there is Java and resources, we will have to work
1654.05 -> inside both of these directories. So let's go inside
1657.74 -> Java. And as you can see, here is the name of our project after
1661.37 -> 400 movies, it it may be different in your computer
1665.63 -> depends on what you have chosen in the initializer. But it
1669.44 -> should be something similar.
1671.84 -> Then there is a class that represents your applications
1675.41 -> names. So since I have named my artifact movies, it says movies
1680.45 -> application, which is pretty appropriate to be honest.
1686.33 -> In other movies application class contains around 10 lines
1690.11 -> of code minus spaces in between. So let's try to understand what
1695.96 -> it's doing. The first line is actually declaring a package
1700.19 -> which is pretty self explanatory. Next, there are two
1705.05 -> input statements. The first one is a class called Spring
1709.76 -> application. Now this particular class contains a method called
1715.37 -> Run. And to start your Spring application, you actually have
1720.71 -> to call this run method, and then pass your application class
1725.6 -> to it. And then you can also pass some command line arguments
1730.76 -> which we are not going to touch
1733.76 -> the second import a statement imports like the Spring Boot
1737.69 -> application annotation. So annotations in Java are usually
1742.61 -> used to let the compiler know about what this class does.
1748.97 -> So other than this class, there is more or less nothing inside
1753.32 -> this package. So let's try to run our application and see if
1758.06 -> we can we can have anything on our browser. Okay.
1763.13 -> So you can actually click on this play button, besides the
1767.39 -> main method to run the program or this class play button, or
1773.57 -> this play button at the top. Let's use this one.
1779.99 -> Okay, so if your IDE says Lombok requires enabled annotation
1784.25 -> processing, just go ahead and click on Enable annotation
1787.61 -> processing and it should be fine.
1790.94 -> Now, if you look at the terminal, you will see that
1794.48 -> there is a nice arc that says the spring the springs version
1797.81 -> and there's bunch of logs and
1800.329 -> There is an exception. That exception states that the
1804.679 -> application is failing to connect to any MongoDB database
1807.889 -> at all. Which is true, since we have not let the application
1812.119 -> know about our, our cluster, our username, our passwords and
1817.669 -> things like that application cannot connect to our MongoDB
1820.669 -> database. Now, it's fine if you want to leave this error here.
1824.989 -> Or if you want to get rid of this error,
1828.65 -> you can just first stop that application.
1834.32 -> Open the POM dot XML file, which contains a list of all the
1839.75 -> different dependencies that we are using.
1842.9 -> And then look for
1846.02 -> MongoDB.
1852.08 -> It should be here somewhere yeah, there you go. Dependency
1855.41 -> artifact the Spring Boot starter data MongoDB. So just highlight
1859.55 -> the entire thing. And press ctrl and the forward slash which will
1865.64 -> comment this out.
1868.58 -> Then right click on form dot XML
1872.78 -> and then go to Maven
1875.63 -> and go to reload project
1883.58 -> now try to run the application once again.
1892.1 -> No your whatsoever.
1895.04 -> So if you look at the logs, it will say that Tomcat started on
1899.93 -> port 8080 Tomcat is actually an web server that will serve as
1906.32 -> the web server the development web server for our application.
1910.4 -> Now, you'd have to switch to a web browser to see the
1913.79 -> application in action. So let's do that.
1926.27 -> And then you can navigate to localhost
1934.25 -> 88080.
1938.78 -> There you go. Now it says whitelabel error page, that's
1941.81 -> fine. At least we know that the application is booting up and we
1946.64 -> are actually hitting the API itself. And not just some other
1950 -> page when what is zero states is that there is no endpoint at
1955.37 -> all. So although we have an API, there is no API to hit. I hope
1960.62 -> that makes sense. Now let's go back to our code and try to
1964.22 -> write our first endpoint.
1967.16 -> But after where it says the Spring Boot application,
1972.2 -> we will say
1975.23 -> Rest Controller.
1977.51 -> It's another annotation that lets
1981.08 -> the framework note that this class is actually a REST API
1984.71 -> controller and not just another class. Then inside this class,
1989.9 -> you will have to say
1993.38 -> get mapping.
1996.26 -> And next we'll have to create a new method called public. And
2000.43 -> the return type will be string. And the name of the method can
2003.97 -> be anything but let's just call it API index for now. Because
2008.62 -> this is the
2010.24 -> route endpoint or or list, let's call it API route.
2016.96 -> And we can say return.
2022.33 -> Have no or
2025.9 -> I know have our programs are boring, but it's essential, you
2029.8 -> know.
2031.06 -> So this gate mapping and notation to each, what it does,
2035.95 -> is that it lets the framework know that this method right
2040.21 -> here, API route, is a good endpoint. So if I put a bracket
2047.26 -> right here, and then inside, I'll say slash just a forward
2051.67 -> slash. Let's stop our application and run it again.
2058.6 -> Let's see if there are any errors.
2062.35 -> looks fine to me. Let's switch to our web browser
2066.28 -> and do a refresh. As you can see, it says hello world. Let me
2070.81 -> just increase the zoom level a bit. So you can
2075.22 -> tell alright.
2077.08 -> Now instead of putting a forward slash here, if I say for say
2082.15 -> slash route,
2084.79 -> rerun the application
2093.46 -> you will see that the whitelabel error page is back. But if you
2097.24 -> navigate to slash route, you will see
2100.51 -> Hello world. I hope this makes sense. Although DCS are valid
2105.61 -> eight point, we are not going to make our API like this, we will
2109.6 -> actually divide our application into separate layers, there will
2113.29 -> be a service layer, there will be a data access layer, and
2116.38 -> there will be an API layer. So let's go forward and get rid of
2120.82 -> this code and restart to put together our movies API.
2133.87 -> Now, in my opinion, the first logical step would be to
2138.79 -> configure the database for our application so that we can
2142.09 -> successfully connect to the MongoDB cluster that we have set
2145.21 -> up previously, and talk to it.
2149.44 -> To do so, open up the src folder right here, go inside main,
2155.71 -> go inside resources, and open the file that says application
2161.29 -> dot properties.
2163.84 -> Now, in this file, you will have to write the different
2168.28 -> application properties that is related to your project. For
2173.86 -> example, right now, we are trying to configure our MongoDB
2178.99 -> dependency.
2182.35 -> And to do that, you will have to write
2186.01 -> spring dot data dot Mongo DB dot database
2195.37 -> equals to the name of the database. I hope you remember
2198.97 -> that we named our database something like movies API dB. So
2206.05 -> we will write movies API dB,
2209.68 -> and next spring
2213.13 -> dot data dot Mongo DB dot URI. Now in here, you will have to
2221.62 -> actually write that URI to your MongoDB cluster like you did
2226.84 -> with Compass.
2230.53 -> I have my URL already copied to my clipboard. And I hope that
2236.38 -> you have saved it somewhere safe. Like I said in the
2239.17 -> beginning of the course that I will just go ahead and paste it
2241.9 -> right there.
2244.06 -> And you can get rid of this slash test thing. And the last
2249.52 -> slash, and it should be fine. Okay, so
2254.11 -> our application should be able to connect to our database. Now
2257.23 -> to test it out. Let's go back to POM dot XML. Let's remove the
2263.77 -> comments.
2269.98 -> And then let's start our application.
2274.51 -> Oh, see, we have forgot to reload our project. And the IDE
2279.67 -> is actually suggested me to load the map and changes. So I can
2284.53 -> just click this button or you can go ahead and right click and
2288.52 -> go to Melbourne and reload project. Let's use this button
2292.15 -> and see if it works fine or not.
2295.54 -> Of course it does. Let's run the application.
2305.59 -> And now the Euro is called. And actually it says some things
2310.75 -> about the MongoDB driver cluster. And this is a positive
2313.93 -> sign. If it failed to connect to the database itself, it would
2317.68 -> have screamed at us and whatnot. But thankfully, it's fine.
2328.42 -> Now, if you have worked with any applications, specifically web
2333.01 -> applications in the past, you've may already know that putting
2337.63 -> sensitive data like this in a file that's going to be in your
2341.95 -> GitHub repository is not safe at all.
2346.27 -> Instead, what you should be doing is putting all these
2349.57 -> things in a dot env file. So we can right click on Resource, go
2355.21 -> to new and create a dot env file for ourselves.
2362.32 -> And we can write down a few properties here.
2368.2 -> Mongo database, then Mongo user,
2375.73 -> then Mongo
2378.1 -> password,
2379.84 -> finally, Mongo
2382.78 -> cluster.
2384.97 -> Now you can go back to the properties file, and you can
2388.96 -> start moving these values one by one to your env file. So this is
2394.27 -> going to be the Mongo database.
2397.12 -> Next up the Mongo user name which is
2400 -> Solid Snake in my case, good among but then Mongo password.
2410.769 -> Finally, the cluster.
2417.039 -> And I sometimes like to put them inside quotes, this makes sure
2422.559 -> that if one of the passwords or username or clusters contain
2427.299 -> some special characters in them, it would not
2431.56 -> disturb the order of things. So I like to put this quotation
2438.85 -> marks around each fabs. Okay, now we have our env file ready
2443.77 -> to go, what I would suggest that you create another env file,
2449.59 -> simply called dot env, dot example,
2455.08 -> for later reference references
2466.48 -> then make sure you open up the dot Git ignore file. And as you
2470.62 -> can see, the Initialize project actually comes with a pretty
2474.16 -> good Git ignore file already. But we'll have to add a few
2478.09 -> things for ourselves, right. So you will say, you can actually
2483.01 -> copy this thing from here and paste it and say,
2487.87 -> in the white.
2491.59 -> Yeah. And then you say.in With this will make sure that you do
2496.78 -> not accidentally commit that dot env file into your repository
2501.34 -> and open up your database to the word.
2506.59 -> Now, the only problem with this spring is that spring doesn't
2510.28 -> support reading dot env files out of the box.
2516.49 -> So what we'll need is we actually need to install
2525.91 -> a new dependencies to our project. And I would like to
2529.51 -> take this opportunity to show you how you can add new
2534.37 -> dependencies to the project later on. So I'll switch back to
2539.47 -> my browser. I'll open up a new tab and I will search for
2548.98 -> Maven
2552.25 -> dependencies, something like that. Yeah. And here is Maven
2557.32 -> repository.
2560.29 -> Then let's search for something along the line spring. Dog
2566.26 -> Ian's.
2571.63 -> Yeah, I am referring to this one by Paul Suarez. I apologize if I
2577.21 -> have pronounced his name wrong.
2581.35 -> Let's select this one. And we can see that it says this spring
2587.44 -> plugins 1.0. And it says Central and whatnot. Okay, so the name
2591.97 -> of the thing is made up Paul Torres spring dot EMV. So as you
2596.53 -> can guess this is his group, group name and thesis, the name
2599.83 -> of the artifact or the or the project itself. So we can go
2604.03 -> back to our code. Let's open up POM dot XML. And inside the
2610.03 -> dependencies bar, make sure you are inside dependencies and not
2614.32 -> outside somewhere here. After the last dependency, we will
2619.6 -> create a new one.
2622.72 -> So it is a dependency.
2625.81 -> And the ID helps us by auto completing this. And we will say
2631.51 -> that the group ID is mi dot
2636.31 -> Paul
2637.87 -> is he h, w A are set just to make sure you can always copy
2644.98 -> from here.
2648.61 -> No one's going to judge you for that. And then name of the
2652.99 -> artifact which is spring dot E and
2657.04 -> now it's not strictly necessary to define a version as well. But
2662.14 -> you can do so by saying
2665.89 -> version and then put maybe the latest from two point 5.4
2671.92 -> by one. Yeah.
2674.71 -> So that's it, let's reload Maven.
2681.1 -> And yet now our project has the ability to use the spring dot
2685.12 -> env artifact and three dot env fights. Let's go back to our
2689.62 -> application properties and replace these hard coded values
2692.95 -> with our dot env references. To do so open up the resources and
2699.01 -> we need the
2700 -> env so Mongo database Mongo user Mongo password, okay?
2705.009 -> So you will first have to get rid of this value and then start
2709.269 -> with $1 sign
2711.82 -> and curly braces. And inside the set of curly braces, you will
2715.66 -> see say e NV dot
2719.35 -> Mongo.
2721.57 -> What do they call it? Database?
2726.01 -> Yeah, Mongo database, and you can kind of copy it from here
2730.48 -> then
2732.67 -> replace Solid Snake by Mongo user.
2740.56 -> And then they should be Mongo password.
2745.33 -> But sore tricked.
2748.54 -> Yes. And finally a cluster.
2759.28 -> Cluster Yes. Does this mean? Okay, we can ignore this typo.
2764.74 -> And if you want Singapore, you can actually come to this
2767.62 -> problem step and have a look at what are what's the ID is
2771.7 -> complaining about. So the annuals property, let's just
2774.94 -> ignore them from now.
2777.88 -> Which ones per year? Yeah. Okay, let's ignore these for now. And
2782.14 -> the typos. Okay, Mongo is not a typo.
2786.49 -> Except let's try running our application once again and see
2789.88 -> if our env file has taken any effect or not.
2800.65 -> So as it turns out, our MongoDB connection is fine, which means
2805.39 -> the end file has been read successfully. And we have
2809.26 -> successfully secured our confidential information from
2814.24 -> going out into the world. Now you, you don't have to write
2818.89 -> everything inside an env file, you can actually use this en v
2823.54 -> dot name of the variable notation to access any
2828.43 -> environment variable variable in your operating system. But I
2832.48 -> will not get into that anymore since we don't need it. Let's go
2837.43 -> ahead and get along with our project.
2841.42 -> Now in our application, there are two types of data that we
2844.75 -> are going to work with. First there are the movies and then
2848.8 -> there are the reviews. So we will need to first create two
2852.7 -> separate classes for representing these two entities
2856.21 -> in our application. So first, let
2861.31 -> left click on your project name new and Java class let's call it
2866.23 -> movie.
2869.62 -> And inside this movie, we will first have to annotate this
2874.12 -> class as a document.
2878.86 -> This will let the framework note that this class sheet presents
2883.93 -> each document in the movies collection.
2887.68 -> And we will also define the name of the collection here movies.
2893.62 -> Then inside here we will have a bunch of private data. So
2899.71 -> private
2901.93 -> object ID ID this will represent the ID of this movie and private
2909.31 -> IMDb ID sorry,
2914.35 -> string
2916.27 -> IMDb ID which will represent the IMDB ID of this movie. And
2922.87 -> preferred
2925.33 -> string, title,
2929.08 -> private string
2932.68 -> release date
2935.8 -> for private string
2939.76 -> Schadler link this will be a link to the YouTube page for the
2943.84 -> trailer
2945.76 -> private is string poster a link to the image on the internet
2952.39 -> private list string this will be the genres because there can be
2960.1 -> multiple genres of a single movie. And these lists class
2965.56 -> need to be imported
2967.84 -> at Java util
2970.27 -> by any private list string
2976.78 -> and
2979.12 -> this will be the backdrops now this backdrop images will
2983.29 -> actually be used in the front end application as you will see
2986.92 -> later. Let's just quickly jump to MongoDB compass and make sure
2992.41 -> that we have indeed written all the necessary properties for
2997.33 -> this class.
2999.49 -> So as you can
3000 -> Let's see we have written high D IMDb ID title yes released a
3004.11 -> trailer link genres poster, backdrops, air review ID. So you
3009.48 -> you, we will add review IDs, a few moments later.
3014.94 -> Now, we will have to also annotate this ID field
3026.58 -> as an actual ID, this will lead
3032.19 -> the framework know that
3035.85 -> this property should be treated as the unique identifier for
3040.47 -> each movie inside the database. Okay, apart from this we will
3045.75 -> also need getters setters that do is string methods and some
3051.27 -> constructors. So instead of writing out getters setters to a
3055.44 -> string for each of these private properties, we can just say
3062.01 -> at the read data, and this is one of the annotations that
3065.58 -> comes from the Lombok project. And it takes care of all those
3070.5 -> different gators setters and two string methods. Next, we'll also
3075.54 -> add all args constructor, this is basically an addition for
3082.62 -> creating a constructor that takes all this private field as
3087.66 -> argument finally, no args constructor, which means another
3092.4 -> constructor that takes no
3096.63 -> parameters whatsoever.
3099.06 -> Okay, next, let's create the reviews. So Java class
3104.49 -> reveal,
3106.47 -> it's the same deal.
3109.14 -> So this will be document
3112.2 -> and the collection name will be G fields. Now, we haven't
3116.52 -> created this collection yet. But the application itself has the
3122.07 -> ability to create new collections. So we don't have to
3124.53 -> worry about that. We'll add data just like before.
3129.84 -> All
3131.7 -> args constructor, Nords. constructor, and then
3137.34 -> there will be two private properties for a strong private
3142.95 -> object ID.
3146.25 -> ID, this will be the ID in this case.
3151.2 -> And then private
3156.33 -> review body
3159.39 -> just just body string body.
3164.19 -> Okay, so as you may have already seen in the database design,
3168.12 -> that each of these movies has an array of this review, and we
3172.92 -> haven't yet added this this area of reviews to the movie model
3177.66 -> yet. So to do that, we will go back to the movie class,
3182.73 -> go near the end and say
3186.51 -> private
3189.18 -> least
3191.7 -> review.
3194.1 -> Review IDs. Okay, so it matches this name review IDs, and the
3201.63 -> hall that our names are matching as well. Yes. Now if you write
3206.49 -> it like this, this will be an embedded relationship. So all
3211.26 -> the reviews that are related, this movie will be added to this
3217.23 -> list of reviews. Now this is completely fine. In fact, if you
3221.46 -> are modeling a one to many relationship, such as one movie
3225.69 -> can have many reviews, this is the way to go. But since I'm
3231.87 -> trying to demonstrate some of the features of Springboard
3236.16 -> MongoDB data, I will show you a nifty annotation right here. So
3240.93 -> I will say
3242.88 -> document reference.
3245.88 -> So this will cause the database to store only the IDs of the
3251.67 -> review. And the views will be in a separate collection. So this
3257.37 -> is called
3259.35 -> manual reference relationship. And there are some other ways to
3263.31 -> create relationships in MongoDB. I would suggest that you search
3267.48 -> them up on Google or MongoDB sufficient documentation and
3271.02 -> read about them on your leisure. It will give you a lot of
3274.08 -> context. So now that we have our movie and review models ready to
3280.59 -> go, we can go ahead and start writing on controllers. So I'd
3286.32 -> right click on
3288.6 -> my packet then a Java class. This will be called Movie
3295.41 -> controller.
3297.9 -> And this is our first official day
3300 -> API controller that we are writing in this API. Previously,
3303.87 -> we wrote a simple controller in our movies application class,
3309.06 -> but this time, it's going to be a bit different. So first, we
3312.87 -> will need to annotate this class as a Rest Controller.
3318.39 -> And instead of mapping it to localhost 8080, I want to make
3325.02 -> it sorry.
3327.75 -> Mapping request mapping, I want to make it map to slash API
3334.14 -> slash v1 slash movies. So any requests to slash API slash v1
3341.76 -> slash movies endpoint will be handled by this particular
3346.41 -> controller. Next, I will create a new gate method. So I will say
3352.65 -> get mapping. And then
3356.52 -> public.
3358.35 -> Let's return string for now.
3363.78 -> All movies,
3366.84 -> and then we can return
3369.87 -> all movies.
3374.31 -> OK, let's try to run our program and see if it works or not.
3378.36 -> Let's hit the play button.
3386.61 -> Okay, it's compiled fine. Let's go back to our browser. And here
3392.73 -> localhost 8080 slash route.
3396.93 -> We will get rid of fruit and say slash API, slash V one, slash
3403.65 -> movies.
3405.45 -> And it works. Now although it's okay to return these strings
3411.33 -> from this endpoint, it's better to return a response
3418.38 -> entity I'll show you why in a minute. So this is a generic
3422.7 -> pipe. So we'll say string.
3425.7 -> And then instead of returning or returning, and instead of
3430.35 -> returning all of this like this, we will say,
3434.4 -> new response entity of type is String. And this is the value.
3444.21 -> Then HTTP status dot O.
3450.06 -> HTTP status dot okay means 200.
3453.99 -> Let's read on this program.
3464.97 -> Refresh, and it works just as expected. Now, you may not see
3469.71 -> any difference there. But if you go back to your terminal
3474.3 -> and say, curl, I HTTP localhost 8080 slash API slash v1 slash
3481.83 -> movies, you will see we are indeed returning the 200
3485.88 -> response code.
3488.76 -> This comes in handy when working on a front end application and
3493.53 -> any REST API out there should return proper status codes.
3499.5 -> Since we have the movie model right here,
3503.19 -> let's try to use it and pull some data from the database.
3509.31 -> For that, we will need a service class as well as a repository
3515.76 -> class. So let's create the repository first, because that's
3519.39 -> the shorter one. So it's a Java class. And we'll select
3523.2 -> interface because repositories are of type interface. And then
3527.58 -> we'll say movie in repository.
3535.35 -> Yeah, now this interface will extend
3539.58 -> Mongo repository. This is the generic type. And we will have
3545.85 -> to let it know what type of data we are dealing with. So movie,
3550.41 -> and we'll also need to let it know what type of ID we're
3553.92 -> dealing with, which will be object
3558.75 -> ID, there you go. That's all for this interface, you will need to
3565.83 -> unnoted this interface as a repository. So that framework
3570.45 -> knows that this is a repository.
3574.35 -> And then let's create a service class which will be movie
3579.54 -> service.
3582.78 -> And this class will not extend anything, you will just need to
3586.74 -> annotate as service.
3591.69 -> Now, inside this class, we will write the database access
3596.01 -> methods. So the first one will be public
3603.149 -> Get on movies.
3608.61 -> Let's just name it all movies. And let's just change our
3613.74 -> controller method name to get on this because since it's a get
3619.14 -> mapping, we're saying get all modes.
3622.77 -> And the return type will be list
3629.46 -> of what will return a list of movie from this method.
3635.49 -> Now, inside the service class, you will need a reference of the
3639.99 -> repository to do that you will say
3644.19 -> movie repository
3647.46 -> it will be a private field.
3651.6 -> And its name will be movie repository.
3655.62 -> Now if you know Java, you may know that you will have to first
3659.76 -> initialize this bit of code, you will either have to initialize
3665.61 -> it using a constructor, or you can just use auto wire an
3673.14 -> audition what this will cause it will let the framework know that
3678.3 -> we want the framework to instantiate this class here for
3683.43 -> us, okay.
3686.58 -> Let's go inside the method now. And we will say return
3691.98 -> move the repository dot find all
3696.39 -> these find all method is described inside the Mongo
3701.67 -> repository class. As you can see, it says right here find all
3707.64 -> and it will return and least of the data type that we have
3711.63 -> passed right here certainly stock movie. So that's our
3715.38 -> service class right there. And then let's go back to our
3718.59 -> controller, we will need a reference to our service class.
3725.19 -> So we will say private
3728.61 -> movie service movie surface. And just like we did in the service
3734.43 -> class, we will auto wired the service class. Since it has the
3738.57 -> service and audition right here, we will set auto wire.
3743.52 -> Excellent. And it's also
3746.91 -> now inside the good old movies. Instead of returning a response
3752.43 -> entity of type string
3757.23 -> change it to list
3762.15 -> so we are returning a response entity of type list movie.
3768.36 -> Then inside the method, we will have to write return
3774.72 -> movie service.of movies
3783.39 -> new response entity
3787.23 -> of type list
3791.16 -> movie
3793.14 -> and inside movie service drug called movies comma HTTP status
3798.78 -> dot okay.
3802.17 -> Yeah, let's take a look at our repository. Once again, it's all
3805.92 -> set up.
3807.9 -> Services fine, the controller is fine. Let's cross our fingers
3813.39 -> and see if this works or not.
3821.55 -> Going to go back to our browser and hit refresh.
3828.18 -> And the reason behind this problem lies in my EMV file. So
3836.28 -> as you can see,
3839.64 -> we have called our database movie API dB.
3844.38 -> But in our configuration, we mistakenly put an S right here.
3849.81 -> So we'll get rid of the s.
3853.71 -> Res restart the application and hope for the best.
3867.78 -> And yeah, it works. As you can see, there are 10 movies in this
3872.52 -> list. Since it starts at zero and ends at nine. There are 10
3876.54 -> movies in this list and the code is perfectly fine. Now let's go
3881.76 -> back to the code and let me re iterate on what we have done so
3886.65 -> far. So in rest API's, usually there are multiple layers. So
3893.16 -> one of the layers is the API layer, which is this controller
3897.57 -> and it will only concern itself
3900 -> have about the task of getting a request from the user and
3905.94 -> returning a response and nothing else. And that's what it's
3909.6 -> doing. All it's doing is it's using a service class and
3914.25 -> delegating the task of fetching all the movies from the
3917.88 -> database. And give me giving it back to the API layer. So it
3924.84 -> calls the all movies method inside
3930.6 -> the service, gets the list of the movie and returns them with
3935.88 -> HTTP status. Okay, it doesn't know what's going on inside the
3941.22 -> service class. Now, when we come back to the service class, this
3945.12 -> is where most of our business logic will go.
3950.1 -> For now, there is nothing to be worried about in this classes.
3954.96 -> But soon, we will work with a little bit more complex business
3959.07 -> logic in this API. So the service class does is it uses
3964.83 -> the repository class, and talks to the database, get the list of
3968.76 -> the movies and returns to the API layer. Finally, the
3973.41 -> repository layer is kind of the data access layer for our API II
3979.74 -> does the job of actually talking to the database and getting the
3984.36 -> data back.
3986.82 -> I hope that makes sense. Now, since we have a list of all the
3991.47 -> movies in our databases, let's complicate it a bit more by
3997.02 -> trying to access a single movie. Now, we will begin by creating a
4002.75 -> new get mapping.
4005.63 -> And that is
4008.87 -> get mapping and this will actually take an parameter.
4014.27 -> And we will have this a slash that inside a pair of curly
4018.59 -> braces will say ID. So we are trying to search a movie by its
4024.5 -> ID.
4026.48 -> So we can set public
4029.33 -> response entity. This time, we will return a single movie.
4036.98 -> And we'll say get single
4040.82 -> movie. Sorry for the type book.
4046.07 -> We'll close
4048.98 -> the pair of parentheses
4056.51 -> and we'll start our method.
4060.02 -> Now inside the pair of parentheses, we'll have to say
4064.76 -> PATH variable, which lets the framework know that we will be
4070.25 -> passing the information we got in the mapping as a path
4074.3 -> variable. Or we will be using the information passed in the
4080.03 -> PATH variable
4082.22 -> as a string,
4086.21 -> or just object.
4089.6 -> Id ID.
4093.38 -> So what this does is it lets the framework know that whatever we
4097.01 -> are getting through this path variable, we want to convert
4101.96 -> that to an object ID called ID.
4105.71 -> And then we can say
4109.22 -> return first we'll have to go back to our service layer and
4114.14 -> write a new method here.
4116.78 -> Public
4118.82 -> movie single movie
4123.53 -> and we will say return
4127.07 -> movie repository dot
4130.43 -> find by ID
4134.93 -> and we will get that ID right here.
4140.33 -> And it goes here it
4144.56 -> David and the squiggly line it says that whichever option okay?
4150.83 -> So the thing here is that the find by ID method may not find
4156.47 -> any movie at all, maybe the ID you have passed doesn't exist.
4162.41 -> So in those cases, you it will have to return now, so we'll
4167.09 -> have to let Java know that it may return null by saying
4171.89 -> optional
4174.23 -> movie
4176.18 -> and we will just import the optional class
4182.27 -> we will also have to fix our response entity movie will say
4188.36 -> optional.
4191.87 -> Movie
4196.46 -> optional has been imported nice and then
4200 -> We can say return new response entity
4206.45 -> optional
4209.179 -> movie. And inside there we can say movie service
4215.509 -> dot single movie, we will pass the ID that we have received
4220.639 -> comma
4222.53 -> HTTP status dot. Okay.
4227.69 -> Let's restart the application
4238.22 -> let's go to our MongoDB compass inside the movie collection and
4243.23 -> copy one of the object IDs right here let's copy
4248.84 -> for Roald Dahl's Matilda the musical. Let's copy the object
4253.49 -> Id
4258.41 -> go back to our browser.
4263.99 -> And we can say movies, slash and then the object ID.
4269.66 -> As you can see, we have found Roald Dahl's Matilda the
4272.72 -> musical. Now, the problem is that I do not want to expose the
4277.82 -> object IDs of my collection entities to the public. Instead,
4283.79 -> what I want to do is use this IMDb ID to search for new
4289.76 -> movies.
4291.65 -> So let's see if we can find a way to do that.
4296.81 -> Now although the repository comes with built in methods for
4302.24 -> searching with ID, it doesn't come with methods for searching
4306.71 -> with IMDb ID so what we'll have to do is we'll have to implement
4312.53 -> that method ourselves. And it's really easy because there is
4318.2 -> something called automatic queries that lets you
4323.36 -> farm where it is dynamically from.
4330.77 -> property names so we will say optional.
4336.8 -> Movie because it may return null once again, we'll have the input
4342.08 -> optional
4344.69 -> movie and we will call it
4347.96 -> find movie
4351.62 -> by
4353.51 -> in dB ID and it takes a string
4360.26 -> I am DB ID.
4363.38 -> Now just by naming this method find movie by IMDb ID
4369.86 -> MongoDB data Spring Data MongoDB will understand what we are
4375.62 -> trying to do. It's that much intelligent. So now we can go
4381.08 -> back to our service class.
4384.98 -> We are no longer getting an object ID but we are getting a
4388.34 -> string
4390.59 -> IMDb ID
4393.98 -> and instead of find by ID we will say
4398.06 -> find a movie by IMDb ID, IMDb ID
4404.3 -> and that's it.
4406.88 -> Let's go back to controller.
4409.61 -> We'll change this from ID to IMDb ID by the way you do not
4414.38 -> have to name the ID IMDb ID exactly in this method. It's
4419.75 -> It's just that I know what I'm doing in a later date. So we
4424.97 -> will replace object ID by string
4430.43 -> IMDb ID
4433.73 -> and then response entity optional movie. This is fine.
4437.81 -> Yeah IMDB.
4440.78 -> So technically, this should do our job. Let's check it out
4453.68 -> let's see seems like there has been a mistake.
4458.81 -> Let's go up
4475.19 -> it looks like there is a problem. Let's go back to
4481.13 -> our movie repository.
4499.34 -> And the music
4500 -> It is it should be IMDb and not IMBD. So as you can see, the
4507.17 -> framework is clever enough to see that I have misspelled
4512.719 -> the property name right here.
4515.299 -> So let's run the program once again and see if you're trans or
4518.689 -> not
4520.34 -> fine tuned by cannot find
4525.59 -> up here, I have to correct terrorism,
4530.69 -> DIA. And yeah, it shouldn't be fine
4541.79 -> let's go back to our browser. And as you can see API slash var
4546.11 -> slash movies. And then I have used the IMDB ID for this movie.
4552.14 -> Hit enter, and it works just fine. We can use the IMDB ID to
4557.78 -> search for movies.
4559.94 -> Now, you can actually form dynamic queries like this using
4564.35 -> any property name in your model class.
4569.36 -> As long as they're unique, because if that's not unique,
4572.96 -> you will get multiple
4576.68 -> movies with the same ID or same name. Okay.
4583.91 -> Now that we have our movie controller sorted out, let's
4587.45 -> start working on our review controller, where we will let
4591.74 -> the user send us review. And we will add those under a movie
4597.62 -> name.
4599 -> So let's first create a new repository.
4605.48 -> View
4607.43 -> posit Ori
4610.58 -> and it spends Mongo D. B,
4617.24 -> Mongo repository and the die will be revealed.
4622.76 -> And object ID is our type. Yeah,
4628.25 -> yeah, that's their
4633.02 -> next let's create a new service class. Oh, I almost forget to
4639.02 -> enter this as repository.
4643.52 -> So, create a new class called
4647.87 -> the views service.
4651.47 -> And this will be a service class. So I'll go service
4657.68 -> here I will say public
4662.06 -> then
4664.16 -> this method will create a new reviews so it will return a new
4667.73 -> review then here she view
4672.62 -> by
4678.5 -> creative
4683.63 -> then this method will take two parameters. The first one will
4688.37 -> be a string
4690.47 -> which will be the reveal body and the since
4696.8 -> the second one will be string IMDb ID so what we are trying to
4701.87 -> do here we will first look for the movie with the given IMDb
4706.67 -> ID. And then we will create a new review and associate that
4712.49 -> review with the found movie. So let's first create a new review.
4721.97 -> Review
4725.18 -> few quotes from new review.
4728.39 -> Now you may
4732.44 -> now you may remember that in the review class, we have an pol
4737.06 -> arcs constructor and an aurochs constructor. But since IDs are
4741.56 -> auto generated, we cannot pass an ID to this class. So what we
4746.06 -> will do we will also generate a custom constructor that takes
4749.9 -> only the body. Now in IntelliJ IDEA you can right click inside
4754.64 -> a class go to generate and then constructor and we only need the
4760.07 -> body part of this class. So that's
4765.98 -> now let's go back to our service class and new review and we will
4770.51 -> pass the review body
4773.48 -> Excellent.
4776.45 -> Now that we have a new review, we will have to associate these
4782.51 -> to one of the movies
4794.15 -> now that we have a new review object, we will have to insert
4798.05 -> it to the database and for
4800 -> After that, we will need
4803.87 -> a reference to our
4806.569 -> review repository.
4810.019 -> So review repository view repository and needs to be auto.
4816.8 -> Fine. And we will say,
4820.16 -> review repository
4824.03 -> dot insert, and review.
4828.95 -> X. And that's the review taken care of now we can have to
4832.16 -> associate with this with one of the movies, right? To do that,
4837.59 -> we
4839.81 -> need a few things. Now the first thing that we need is called a
4845.45 -> template to create a template with set private Mongo template,
4852.68 -> Mongo template. Now, you have already learned about
4857.03 -> repositories as one of the ways to talk to the database. The
4860.69 -> other way is using a template. You see there are times when a
4865.91 -> repository just doesn't cut it, maybe you have an operations so
4871.49 -> complex that it cannot be implemented within a repository,
4876.29 -> or even if you can implement it within a repository, it will be
4882.11 -> not
4883.88 -> suitable. So what we need, we need a
4888.47 -> template, you can use this template to form up a new
4892.52 -> dynamic query and do the job inside the database without
4898.04 -> using the repository. So we will alter this.
4905.27 -> And then down here, we will say
4909.14 -> Mongo template
4912.26 -> dot update, since it's an update operation, and we need to say
4918.35 -> which class to you do we want to update. So we want to update all
4923.87 -> of the movies.
4927.56 -> And then come to the second line and put a dot here. And then as
4932.03 -> you can see, there are multiple operations that we can perform.
4936.41 -> So we want the match.
4939.95 -> Now inside the matching of version, we will need a new
4943.49 -> criteria. So we'll set criteria
4949.88 -> dot fire.
4952.7 -> And inside where we will say IMDb ID, make sure it's matching
4958.28 -> up with the column name or the property name inside the
4961.94 -> database
4964.91 -> then.is the IMDB ID that we have got.
4972.44 -> Then come to the next line and put a dot once again and then
4975.89 -> we'll say Apply.
4979.67 -> We'll say new update. This is called an update definition
4986.3 -> dot push
4996.83 -> review IDs
5001.81 -> and then dot
5004.27 -> value
5006.55 -> sheet view.
5008.89 -> See, that's pretty much it. Okay, so what we are doing is we
5014.26 -> are using the template to perform an update call on the
5017.89 -> movie class. Because I hope that you'll remember that each movie
5022.75 -> in our collection contains an empty array of review IDs. So
5028.81 -> what we need to do,
5030.97 -> what we need to do is we need to update this array and push a new
5036.1 -> review ID into this.
5040.15 -> So we are saying movie dot class then we have to perform the
5043.93 -> matching. So which movie are you updating? We are updating a
5048.52 -> movie where the IMDB ID of the movie in the database matches
5054.55 -> the IMDB ID that we have received from the user. Okay,
5059.74 -> then we want to apply this update. To do so we call apply.
5065.56 -> And then we create a new update definition which does the job of
5070.63 -> making the change inside the database. So we say Update, push
5077.41 -> and review IDs. So we want to update the review IDs in this
5082 -> found movie and the value of this movie will be revealed. So
5086.59 -> that review that we have just created it will be pushed inside
5090.28 -> the review IDs array okay.
5095.92 -> Now, finally, we will have see the
5100 -> First, to make sure that we are getting a single movie and we
5104.32 -> are updating that. Now one thing that I have done, which I
5108.97 -> shouldn't have is we cannot new up a review like this.
5114.82 -> Rather, what we need to do is we will just save the review on
5122.41 -> insert, because when you call insert, it actually returns the
5127 -> data you just pushed inside your database. Okay?
5131.86 -> First, finally, we can return
5136.78 -> that view we just created.
5140.32 -> So let's review the Create review method. We are taking a
5145.21 -> new Mongo template, we are using it to update the movie with the
5148.99 -> new review, we just pushed using the repository.
5153.52 -> So likely say sometimes you will have to code up complex business
5158.47 -> logics by yourself. And as you grow as a software engineer and
5162.97 -> an web developer, you will start to understand all these things
5166.63 -> all by yourself.
5168.82 -> So let's go back to our review service. Yeah. So I mean, our
5174.91 -> review
5177.43 -> is is fine. If you're in positions where you feel
5179.62 -> service, yeah. Now let's create a new review controller.
5187.24 -> And inside this controller, we will have only one post method.
5195.22 -> But you may think, why only a single post method? How are we
5199.9 -> going to get all these reviews that are associated with a
5203.35 -> movie, I'll show you how.
5206.98 -> Now let's begin by annotating it as a Rest Controller.
5213.28 -> And then of course, we will have input request mapping
5219.04 -> which is
5222.19 -> slash API slash v1 slash
5227.62 -> mobile movies
5233.8 -> Okay, since
5236.59 -> the review form will be inside a movies Details page, or in the
5241.81 -> page where you are viewing a single movie so we can make the
5245.53 -> requests to the movies and point instead of creating a new if we
5249.82 -> use NS N bar. Now when it comes to creating endpoints like this,
5254.38 -> it really depends on the on the developers preferences, you may
5259.99 -> you may choose to organize your API differently from what I am
5265.3 -> doing here. And in a real life project I maybe I will do
5270.67 -> something different but since it's just for learning, and we
5274.99 -> are just getting started, I think it's fine.
5280.06 -> Inside the controller, we'll first need our service. So we'll
5283.75 -> say private
5286.84 -> reveal Service Review service and we will auto add this
5294.91 -> nice
5297.94 -> then we'll create a new post mapping
5308.14 -> and then a new method of Lake will again return a response
5313.39 -> entity and this will be of type review. And we will call it
5319.84 -> create review method.
5322.87 -> Inside this pair of parentheses we will say
5328.39 -> request body
5331.42 -> then map
5336.73 -> string, comma string
5341.08 -> and we will call it payload
5344.92 -> so we'll import map.
5347.35 -> So, what we are saying to the framework here that whatever we
5351.25 -> get as the request body we would like to convert it to a map of
5357.7 -> the key string and value string and we want to name this map as
5362.5 -> payload you will see why this is
5367.15 -> then we will say
5370.09 -> return new response entity.
5373.84 -> And yeah we can say review this review
5378.55 -> and then it says Service Review service dot create review and we
5384.94 -> will pass two tests. First one payload dot get
5393.13 -> is the review body
5397.09 -> and the second one will be payload
5400 -> Don't get
5405.13 -> IMDb ID Okay.
5409.51 -> Finally we say
5413.559 -> comma
5415.54 -> HTT be
5418.84 -> status dot created, it will be 201. Since we are creating a new
5424.33 -> review, we want to send 201 instead of the plane 200 Because
5429.34 -> this means created and that means okay. So now that we have
5433.84 -> the post mapping done, we need our REST client a separate risk
5439.09 -> flying to test our test out our code. But before that, I can see
5445.03 -> that there is this squiggly line underneath the view controller.
5447.88 -> So I will just go to problems and see what's wrong. cannot
5451.78 -> resolve symbol IMDb ID Okay, let's see where I missed a typo
5456.28 -> here. So it should be inside a pair of quotation mark. And
5460.63 -> that's gone. See, this is the beauty of IntelliJ IDEA. It
5464.05 -> helps you a lot. Now let's restart our program. And I will
5469.63 -> use postman to test out our API.
5480.79 -> In fact, I just thought instead of mapping the reviews request
5485.92 -> to API slash API slash movies, let's just go with reviews.
5491.05 -> Because that sounds more appropriate. Now let's start our
5495.58 -> application
5502.24 -> and let's jump to postman.
5507.49 -> So inside postman first, I'll create a new collection. And
5511.87 -> I'll call the movies API.
5516.64 -> Then let's create a new GET request get all movies
5524.08 -> so it would be localhost 8080 slash API slash VLANs slash x.
5535.66 -> So it works out just fine. Let's copy the IMDB ID from one of
5544.48 -> these movies so that we can test out our next request
5551.08 -> which will be
5553.81 -> get a single movie
5559.66 -> and we should be able to carry everything from the previous
5563.41 -> request
5565.87 -> will host slash view and slash movies slash then the IMDB ID.
5572.56 -> Let's execute and the works just fine.
5576.82 -> Finally, let's try to create a new review here to review.
5588.52 -> And let's say v1 slash reviews.
5594.1 -> Okay, that's I set that because by mistake so it has to be post
5599.89 -> inside body I would say raw data in JSON format.
5607.51 -> So I will say review
5613.33 -> body will be I really enjoyed the movie with
5621.85 -> I.
5623.98 -> Yeah. And then I will say IMDb ID,
5630.49 -> column and timed ID. Now you have to make sure that the name
5635.65 -> or the key in this JSON data review body and IMDb ID
5646.36 -> exactly matches the two keys inside the payload which is
5651.46 -> review body and IMDb ID. So what will happen is this endpoint
5656.05 -> will receive a JSON data from the user and then convert it to
5660.61 -> a map where the keys are extreme and the values are history. Then
5665.35 -> from this map, we'll be able to access the review body which is
5669.73 -> a string and the IMDB ID, which is another string. And then
5674.62 -> through the service layer, we can create a new review on the
5678.13 -> database, update the movie to be associated with that review, and
5684.04 -> then return the review. And of course, there's a repository
5687.88 -> that works as the intermediary layer
5692.92 -> between the service class and the database to let's let's go
5698.95 -> let's come back
5700 -> postman, and let's see if it actually works on
5706.33 -> here. So we have got 201 created. So theoretically, we
5711.19 -> should have created a new review for the movie boosting boards.
5716.8 -> And let's go back to get a single movie it sent,
5721.96 -> come down to review ideas. And of course, we have the new
5725.41 -> review associated with this movie.
5729.07 -> That's how we can get the list of review ideas, they will be
5734.89 -> embedded with the data of the movie they're referred to.
5742.48 -> So in terms of the API, that's it, I know, it's a pretty simple
5746.11 -> API. But the goal of this course, or the first half of
5750.55 -> this course, was to give you some idea about how you can
5754.15 -> create a new back end API. Powered by Spring Boot and
5758.5 -> MongoDB. I hope that you have understood the basic concepts.
5763.51 -> using MongoDB. And Spring Boot together, you can go ahead and
5768.94 -> further your study by learning about how to implement
5772 -> authorization and authentication. You can also
5775.66 -> learn about more complex relationships, and maybe try to
5779.32 -> build a bigger API with Gillette and ports and other kinds of
5784.54 -> requests. I will be leaving this stretch right now. And from now
5789.7 -> on Gavin long will teach you how you can create a React
5794.47 -> application that can go with this API. So take care, I will
5799.87 -> maybe see you in another course in the future. Now that you've
5803.47 -> learned how to develop the back end, Gavin will teach you how to
5806.47 -> develop the front end using React. Just a quick note before
5810.34 -> we get started, this will not be a deep dive into React. My only
5814.9 -> goal here is to demonstrate how we can interface with a remote
5818.41 -> API from a front end application created using React through
5822.82 -> which we are able to retrieve data from a MongoDB database
5826.45 -> hosted on a remote server, as well as posting data to our
5830.98 -> MongoDB database. Now, any data that we retrieve from the server
5836.92 -> will be in JSON format. JSON formatted data may be pleasing
5841.9 -> to some people. But most users of application I think would
5846.01 -> much prefer something like this. So we're going to transform the
5850.21 -> data passed to us in a JSON format into an aesthetically
5854.5 -> pleasing front end display. React and associated
5857.74 -> technologies provide an efficient way to create both
5860.92 -> aesthetically pleasing front ends, as well as help us
5864.1 -> developers to facilitate a great UX user experience. I'd like to
5869.59 -> give a shout out to the movie db.org All the movie poster
5873.64 -> images and backdrop images that we are going to use in the React
5877.21 -> application that we are going to build in this course, come from
5880.84 -> the movie db.org Right, let's get into it. Let's start by
5884.92 -> launching VS code.
5891.4 -> And let's create a working folder on our local machines.
5901.51 -> I'm going to name my folder
5904.39 -> movie client.
5910.51 -> Let's open our working folder like this from within VS code.
5919.15 -> So we are going to use the Create dash react dash app
5923.02 -> command to generate our React projects infrastructure. You of
5927.82 -> course, must have Node js, preferably the latest version
5931.75 -> installed on your local machine as a prerequisite before
5935.62 -> creating a React application.
5939.55 -> If you don't have no JS installed, you can navigate to
5943.03 -> this URL to install the latest release of node j s. So from
5948.16 -> within VS code, let's launch the terminal window so that we can
5952.18 -> create our React project infrastructure using the Create
5955.75 -> dash react dash app command.
5959.71 -> You can launch the terminal window from within VS code by
5962.59 -> pressing Ctrl and the tilde character.
5967.87 -> Great.
5969.88 -> So the current directory reflected at the terminal prompt
5974.2 -> should be the working directory that we have just created. my
5978.16 -> working directory is named movie client.
5981.76 -> Then at the terminal prompt, let's type in MPX space create
5987.19 -> dash react dash app followed by the name we'd like to call our
5992.29 -> React project. So I'm going to name my react project movie dash
5997.45 -> gold dash v one
6002.07 -> Then let's press the enter key. And the Create dash react dash
6006.12 -> app command generates the React project infrastructure, which
6010.59 -> includes all the relevant node modules that contain components
6014.79 -> that we are able to import into our React application. This
6019.62 -> process can take a while to complete.
6034.02 -> And we can see the process on my local machine has now completed.
6038.31 -> So at this stage, we don't really need the movie client
6041.97 -> folder. Opened within VS code, we only want the folder
6045.99 -> containing the files for our React project. So at the
6049.38 -> terminal, let's use the cd command and then enter the name
6054.12 -> of the React application that we created using create dash react
6059.16 -> dash app. So I'm going to type cd space movie dash gold dash v
6065.34 -> one, and press the Enter key. So once we have made the folder
6069.57 -> containing the files for our React projects infrastructure,
6074.19 -> we can launch another instance of VS code by typing and code
6078.18 -> space dot and then pressing the Enter key. This command opens
6082.65 -> another instance of VS code, where we are now directly within
6086.49 -> the folder that contains the files for our React projects
6089.58 -> infrastructure.
6091.5 -> We can now close down the first instance of VS code, because we
6095.49 -> only need the instance that we have just launched.
6099.72 -> So we are almost ready to create our React application.
6103.89 -> We won't be using some of the files that the Create dash react
6107.64 -> dash app commands generated for us. So let's delete the
6111.03 -> following files from within the SRC directory. Let's delete the
6115.65 -> setup tests dot j s file, the report vitals dot j s file and
6121.41 -> the app dot test dot j s file.
6132.36 -> We must also delete a setting from within the package dot json
6136.11 -> file, which has to do with linting. We don't need this
6140.55 -> linting setting in our project.
6145.23 -> Let's save our changes.
6147.93 -> Lastly, let's open the index.js file and remove the code related
6152.58 -> to the report web vitals functionality like this.
6159.39 -> Let's save our changes
6168.84 -> and let's move on to installing a few NPM packages that contain
6173.19 -> components that we are going to integrate into our application.
6176.97 -> If your project terminal is not available within VS code at the
6180.72 -> moment, you're able to launch the terminal by pressing Ctrl
6185.01 -> and the tilde character.
6187.62 -> The next package we are going to install is Axios Axios will make
6192.75 -> it easy for us to make HTTP requests from our React client
6197.91 -> to the relevant API hosted on a distant remote machine. So that
6203.04 -> we can retrieve relevant movie data from the MongoDB database
6206.7 -> also hosted on the relevant distant remote machine through
6210.69 -> HTTP GET requests.
6213.87 -> We will also be able to add movie reviews to the relevant
6217.89 -> Mongo DB database through the use of HTTP POST request, which
6224.01 -> will be facilitated on our React client through the use of Axios.
6229.56 -> We'll implement this functionality later in this
6232.14 -> video.
6234.57 -> So to install Axios, we can type this command at the command
6238.92 -> prompt NPM space install space Axios.
6245.43 -> And let's press the enter key.
6254.31 -> Great, so let's install our next NPM package
6259.29 -> which will enable us to use Bootstrap for layout and styling
6262.74 -> purposes from within our React project. So let's type the
6266.16 -> following at our command prompt
6269.4 -> NPM space install space Bootstrap.
6279.72 -> Note that in order to integrate bootstrap into our project, we
6283.8 -> must include this import statement within the index.js
6288.78 -> file.
6293.97 -> Let's save our changes.
6296.67 -> The next NPM package that we must install
6300 -> allows us to use Bootstrap related components for layout
6303.9 -> and styling purposes. So let's install react dash Bootstrap.
6309 -> For this purpose, we can install react dash bootstrap by typing
6314.01 -> NPM space I space react dash Bootstrap.
6325.26 -> And of course, follow this by pressing the Enter key.
6331.74 -> Great. The next NPM package that we are going to install enables
6337.38 -> us to easily install font awesome icons within our React
6342.54 -> application. The first font awesome related package can be
6346.35 -> installed by typing in npm space I space at Fort dash awesome,
6352.71 -> forward slash react dash Font Awesome.
6357.54 -> So make sure you type at Fort dash awesome here and not at
6362.22 -> font stash awesome, which I know is a little bit confusing. So
6367.14 -> it's add 14 Awesome dash, react dash and then Font Awesome.
6375.3 -> Great.
6377.1 -> Let's install the second font or some related package by typing
6380.94 -> in npm space I space at Fort Awesome forward slash free dash
6388.59 -> solid dash SVG dash icons.
6395.82 -> And let's Of course, press the enter key.
6400.98 -> Excellent.
6402.9 -> To play movie trailers from within our application, we're
6406.5 -> going to use the React player component. So let's install the
6410.73 -> appropriate NPM package. So that we can integrate react player
6415.83 -> into our React application. So let's type npm space I space
6421.71 -> react dash player
6428.25 -> and press the Enter key.
6437.73 -> Great in order to declare the paths where our components will
6443.19 -> reside, in order to map the routes to our components as it
6446.19 -> were, we are going to use relevant components from the
6450.48 -> React dash router dash DOM NPM package. So in order to install
6456.36 -> the React dash router, dash DOM NPM package, let's type in this
6461.25 -> command npm space I space react dash router dash DOM.
6470.85 -> And of course, press the enter key.
6479.52 -> Great.
6482.28 -> On our homepage, we want to display relevant movies in a
6485.7 -> carousel.
6488.31 -> We can easily implement a carousel using material UI. So
6493.11 -> in order to do this, we must install three material UI NPM
6496.98 -> packages. So we can install the relevant three NPM packages by
6501.51 -> typing the following NPM space install space at Nui forward
6507.48 -> slash material space at emotion forward slash react space at
6513.33 -> emotion forward slash styles.
6520.11 -> And let's press the enter key.
6528.15 -> Excellent.
6530.22 -> In order to use the material UI carousel component, let's
6533.97 -> install the material UI carousel NPM package. We can do this by
6539.07 -> typing in npm space install space react dash material, dash
6545.61 -> UI dash carousel
6551.61 -> and press the Enter key.
6567.81 -> Great,
6569.55 -> and we have now installed all the NPM packages we need in
6572.79 -> order to integrate the functionality we want to include
6576.24 -> within our React application.
6579.09 -> Excellent. Let's get started with writing the code for our
6582.9 -> React application. So the first thing I'd like to do is set up
6586.77 -> Axios. So to do this, let's create a folder within the src
6591.96 -> folder
6599.73 -> and Let's name our folder API.
6603.899 -> Let's create a file within the API folder named Axios config
6609.149 -> dot j s.
6617.16 -> We can import Axios into our project with this line of code.
6627.72 -> So we can configure and export the Axios object that we will
6631.29 -> use to make HTTP requests to the relevant remote API through this
6635.91 -> code.
6654.12 -> Notes the settings that have been included here,
6657.9 -> we have the base URL setting, which provides the base address
6662.1 -> of the API endpoints that our client react application will be
6666.21 -> calling. So you'll see later on when we use Axios. To call an
6670.8 -> endpoint, we won't need to repeat the base URL with each
6676.14 -> HTTP request within our code, we will only need to include the
6681 -> additional path information required to target a specific
6684.78 -> endpoint. If this isn't clear, at the moment, it will become
6689.16 -> clear. When we write code to make a HTTP request to the
6694.32 -> relevant remote endpoint. This setting here is necessary.
6699.09 -> Because during the development phase, the technology that the
6702.87 -> remote machine is using to expose the relevant API
6706.41 -> endpoints is called ngrok.
6710.64 -> I won't go into the specifics of N grok. But we need to include
6714.78 -> this setting in order for our client HTTP requests to not be
6719.79 -> blocked by cause I won't go into the details, of course, but it
6724.65 -> stands for cross origin resource sharing. So all we need to know
6729.69 -> is that because the relevant web API is running in a different
6732.96 -> domain, or origin, that cause may block our access to the end
6738.9 -> point. The server code has included settings in order to
6744.06 -> overcome the restrictions imposed by cores. And we are
6748.65 -> including this setting in the HTTP headers of our requests
6753.81 -> from the client, so that we can overcome the restrictions
6757.32 -> imposed by cause IE, so that we are able to access the resources
6762.75 -> made available through the relevant API endpoints. Great,
6767.58 -> so we have now set up Axios. Let's open the app.js file and
6772.98 -> write code to call an endpoint that will return an array of
6777.54 -> movie data.
6785.64 -> Let's write code to import our Axios object from within our
6789.09 -> Axios config.js file.
6798.54 -> Let's import the use state hook and the use effect hook from
6803.04 -> react.
6811.98 -> Let's return a D structured array from the use state hook.
6819.81 -> The first item in the de structured array is named movies
6823.71 -> and will store an array of movie data returned from a call to the
6828.12 -> relevant API endpoint.
6832.74 -> The second item in the array is a function that can be used to
6836.37 -> change the state of the movies variable.
6840.54 -> When the state of the variable tracked by react through the use
6844.77 -> state hook is changed the component is re rendered by
6847.98 -> react. So in this case, the app component will be re rendered
6852.18 -> when the state of the movies variable changes. Let's create a
6856.17 -> function that will handle a HTTP get request to an endpoint that
6861.39 -> returns an array of movie data. Once the movie data is
6865.17 -> successfully returned, this code that changes the state of the
6868.62 -> movies array is executed.
6880.56 -> You can see here we are passing the additional path information
6884.82 -> to the get method. This path information is appended to the
6889.17 -> base URL setting that we created when setting up the
6892.56 -> configuration for Axios.
6896.04 -> We are using async await for asynchronous thread management
6899.46 -> functionality
6900 -> to the client, I won't go into detail explaining async await
6904.59 -> and promises. But this functionality can be effective
6908.1 -> in ensuring that the UI is not blocked. When potentially long
6913.05 -> running operations, like for example, a remote API call are
6917.22 -> processed, the UI thread will not be blocked, and therefore
6923.25 -> the use of screen will not, for example, freeze, the use the
6927.09 -> screen will still be responsive, while a potentially long running
6930.93 -> IO bound operation is processing. Once the relevant
6934.95 -> task has completed, the code directly below the code that
6938.67 -> kicks off the awaited process will be executed. So it's like a
6944.04 -> promises made to return to the appropriate line of code. Once
6947.97 -> the task potentially long running IO bound task, for
6951.45 -> example, has completed.
6955.17 -> As explained, this async await functionality is useful in order
6959.73 -> to ensure a better UX user experience. In case something
6965.16 -> goes wrong during the execution of our HTTP request, let's wrap
6969.6 -> the relevant code in a try catch block. And let's include code in
6974.04 -> the catch block to log the relevant exception to the
6976.92 -> browser console window. So you could be more thorough here in
6981.42 -> your code and check the HTTP status code. For example, if the
6985.74 -> HTTP status code returned from the server is 200. This
6989.37 -> indicates that the operation performed on the server was
6992.97 -> successful.
6995.04 -> I'm not going to include this functionality in this course, in
6997.92 -> order to keep the code fairly basic for our HTTP requests that
7002.48 -> we are executing from the client.
7010.7 -> Let's implement the use effect hook so that the get movies
7014.39 -> function is executed when the app component first loads.
7024.44 -> Let's also write code to log the results returned from the call
7028.19 -> to the relevant endpoint to the browser console window.
7037.79 -> Let's use the npm start command to run our React application.
7046.43 -> Let's look at the browser console window to see if our
7049.34 -> results have been returned from the server.
7054.56 -> Excellent our HTTP get request made through the use of Axios
7059.51 -> executed successfully.
7067.16 -> So the next step is to start implementing our routing
7071.96 -> functionality or routing functionality.
7084.14 -> Let's create a React component named layout dots Jas.
7094.25 -> Let's open the layout.js file and import the outlet component
7099.71 -> from the React Router DOM NPM package to generate boilerplate
7105.29 -> code for our layout component, we can type ra F C E and press
7110.24 -> the Tab key like this.
7113.09 -> Let's rather use semantic HTML here and include main tags
7117.23 -> instead of div tags. Within our main tags, let's include a
7122.09 -> reference to the outlet component.
7130.7 -> Let's go back to the app.js file and write code to import the
7134.75 -> layout component that we have just created.
7141.44 -> Right, so I'm going to create a components folder within the src
7146.33 -> folder, and move the layout.js file into the components folder.
7163.52 -> Let's write the code to import the layout component into the
7166.37 -> app component.
7170.36 -> Let's write code to import the routes component and the route
7174.44 -> component from the React Router DOM NPM package
7186.44 -> in the return part of the app component, ie where JSX code is
7190.25 -> returned from our component, let's write code to establish
7193.76 -> the route mappings as it were for our applications React
7196.79 -> components. So let's first add the routes.
7200 -> elements here
7209.15 -> within the root element, let's include a parent root element.
7213.35 -> It's a parent root element because child root elements will
7216.56 -> be included within this parent root element. Like, for example,
7220.43 -> a child route component that points to the home component we
7224.21 -> will write the home component in a bit, will be a child of the
7228.2 -> parent route component that points to the layout component.
7232.61 -> So the layout component referenced through the outlet
7235.91 -> element in the layout.js file denotes the components pointed
7240.8 -> to by the child root component references that will include
7245.09 -> within the parent root element here, we'll include the relevant
7250.07 -> child root elements as we progress with the development of
7254 -> our React application. The next step is to open the index.js
7259.61 -> file and write code to import the browser router component,
7264.71 -> the routes component and the route component into the index
7269.09 -> component.
7292.55 -> Let's include code to establish the relevant route mapping for
7296.78 -> the app component.
7306.14 -> Great, let's create our home component. Let's first create a
7310.91 -> folder within the components folder named home. Let's ensure
7314.6 -> that the first letter in our home folder name is lowercase.
7324.17 -> Let's add a file named home with an uppercase H to our home
7329.27 -> folder. Let's type in ra f c e followed by pressing the tab key
7334.88 -> to generate boilerplate code for the home component.
7341.69 -> Let's simply type in the text welcome so that we can test our
7345.26 -> route functionality.
7347.96 -> We'll create the code for our home component in just a bit
7358.31 -> let's create the code for the route element that points to our
7361.28 -> home component within the app.js file.
7383.72 -> Oops, I can see a little bug in our code. This reference to
7388.22 -> layout
7390.2 -> is not correctly formed. Let's include the layout element
7393.47 -> properly within our code here.
7397.22 -> Let's type in npm. Start at our command prompt and press Enter
7401.51 -> to launch the application
7408.8 -> Great.
7421.25 -> So let's create a component that will be a child component of the
7425.48 -> home component. We will name this component hero. This
7430.22 -> components denotes the hero section of our home page that
7434.78 -> will display items in a carousel that are representative of
7438.56 -> movies to the users of this application. So let's create a
7442.28 -> folder within the components folder named hero.
7453.98 -> Within the hero folder, let's add a file named hero dot j s.
7468.62 -> Let's also add a file to the hero folder named hero dot css
7473.36 -> where we will of course include CSS code for our hero component.
7489.56 -> Let's write code to import the hero dot css file into our hero
7493.34 -> component.
7496.91 -> Let's import the carousel component from the relevant man
7500 -> Terrio UI NPM package
7522.65 -> let's import the paper component from the relevant material UI
7526.4 -> NPM package
7539.99 -> let's write code to destructure. The props passed into this
7543.5 -> component, only one destructured value containing an array of
7548.09 -> movie data needs to be included here
7560.99 -> let's implement the carousel functionality. Let's include the
7564.56 -> carousel element like this.
7575.69 -> Within the carousel element, let's write code to map each
7579.23 -> item in the movies array to an item displayed in the carousel.
7593.96 -> The pay per element encapsulates each movie item displayed in the
7598.43 -> carousel.
7616.97 -> Let's include div tags, so that the movie poster is displayed,
7621.29 -> as well as the movie title is displayed for each carousel
7624.8 -> item.
7643.55 -> As you can see, I've included CSS class references in the
7647.69 -> relevant div tags, we'll style our components in the hero dot
7651.74 -> css file in a bit,
7654.74 -> where we will implement the appropriate CSS properties for
7657.8 -> these CSS classes.
7661.52 -> Oops, let's make sure that we are importing the hero dot css
7665.81 -> class correctly here.
7669.68 -> Let's open the home.js file and include the hero element in the
7674 -> part of the code that is returned as JSX code from the
7677.81 -> home component.
7689.51 -> Let's make sure that we are importing the hero component
7693.05 -> into our home component.
7704.6 -> Let's write code to ensure that the movies array is being passed
7708.62 -> down from the app component to the home component and
7712.22 -> subsequently the hero component.
7728.87 -> And that's great. We are displaying the relevant data
7731.9 -> from the JSON data returned from the relevant API's endpoint. But
7736.22 -> let's customize the styling of our carousel through CSS code.
7745.04 -> We can position our Vyas code editors to a pane on the left
7749.69 -> side of our screens. And we can position our browsers to a pane
7753.95 -> on the right side of our screens like this. In this way, we can
7758.69 -> watch the effects of our CSS code changes in real time. I'm
7763.1 -> not going to go into a lot of detail regarding the CSS code.
7766.4 -> The code will be available on GitHub, where you can examine it
7769.94 -> in more detail if you'd like.
7774.08 -> Let's first update the CSS code in the app dot css file. This
7778.67 -> CSS code effects all components that are child components of the
7783.14 -> app component.
7785.81 -> And you're able to observe the effects of the CSS code on the
7789.44 -> browser in real time as the CSS code evolves.
7799.13 -> So let's import
7800 -> quicksand font from Google with this line of code
7820.64 -> let's set up the box sizing and font family properties for all
7824.33 -> elements
7834.02 -> let's set the body elements padding and margin properties to
7837.02 -> zero.
7850.04 -> Let's style the App class. Note that all of our components are
7854.63 -> children of the app component.
7879.98 -> Let's remove this code from the index dot css file because it is
7884.57 -> not needed
7889.79 -> let's style the carousel component that has been
7892.91 -> implemented within our hero component. So let's include our
7896.81 -> CSS code in the hero dot css file.
7920.6 -> And we are able to watch the effects on the carousel
7923.48 -> displayed in our browsers in real time as the relevant CSS
7926.87 -> code evolves.
7935.6 -> And we don't actually want the post image to take up the
7938.33 -> carousel display. As it is at the moment, we want an
7942.23 -> appropriate backdrop image a larger image to fill the
7945.98 -> background for each item in the carousel.
7965.45 -> I want to include a gradient that fades from dark to light
7968.9 -> from the bottom of each carousel item to where the title is
7972.23 -> displayed. In order to dynamically reference the
7975.86 -> background image URL for each carousel card,
7980.99 -> I'm going to use a CSS custom variable.
7985.82 -> So we can do this by including an inline style within the div
7989.69 -> element that references the movie dash card CSS class. And
7994.04 -> within that inline style, assign a variable to the property that
7999.2 -> we wish to reference within the relevant CSS file. So here, we
8004.78 -> are naming our custom CSS variable image.
8012.58 -> We are setting the CSS URL value to the CSS background dash image
8016.93 -> CSS property from the backdrops property of each movie in the
8020.86 -> movies array returned from the server. Note that the backdrops
8024.46 -> property returned from the server is an array containing
8027.22 -> pause to movie backdrop images. In this code, I'm choosing to
8032.29 -> reference the first backdrop image path in the backdrops
8035.95 -> array returned from the server. Each backdrop points to an image
8039.94 -> that we want displayed as a background image appropriately
8043.24 -> for each movie item in the carousel. We can now reference
8047.32 -> each background image from within our CSS class and style
8050.98 -> the background appropriately.
8086.68 -> So we are assigning the background dash image CSS
8090.1 -> property or gradient that fades from light to dark?
8098.38 -> This is just a stylistic choice.
8100.359 -> For our front end display, you can see here in our CSS code how
8105.639 -> we are using the dash dash image custom CSS variable to link the
8111.099 -> URL property value referenced in the JSX code in the hero
8116.049 -> component to the background dash image CSS property in the hero
8119.679 -> dot css file. You can see that the poster image is looking
8124.509 -> distorted so let's style the poster and the title
8128.439 -> appropriately.
8149.68 -> Great and we have used absolute positioning and the CSS Flexbox
8154.72 -> to style our poster and handle where it appears in the layout
8171.55 -> let's style the title appropriately.
8209.38 -> Great, and our carousel is looking pretty good. Let's
8213.79 -> create the components to house our navigation display. Let's
8217.27 -> create the header component. So let's create a folder within the
8221.62 -> components folder named header. Let's create a file within the
8225.82 -> header folder named header.js.
8233.08 -> Let's import the appropriate font awesome components
8247.96 -> let's import the appropriate bootstrap components.
8268.96 -> And let's use React bootstrap components to create a
8271.93 -> responsive layout for our navigation menu which will be
8275.26 -> displayed at the top of the screen. This is one of the huge
8279.1 -> advantages of using Bootstrap it can save us a lot of time in
8282.61 -> creating responsive layouts.
8302.83 -> We are using the FA video flash font awesome icon for our logo
8307.21 -> that will be displayed in the top left corner of our screen
8310.48 -> within the navigation bar that we are creating within the
8314.02 -> header component.
8337.6 -> The login and registration buttons are being included here.
8340.96 -> Superficially, they are purely cosmetic indicating that we
8345.49 -> could extend the functionality of this application to include
8349.06 -> login and registration functionality at a later stage.
8351.88 -> For example, if we wanted to enable users to create their own
8355.3 -> list of favorite movies or a watch list, the watch list link
8359.44 -> here is also there purely for cosmetic reasons. We won't
8364.36 -> implement a watch list component in this course.
8368.98 -> So above the routes functionality within the app.js
8373.57 -> file, let's reference the header component
8384.07 -> let's go back to the header.js file and make sure that our
8387.76 -> imports are correct.
8394.75 -> Let's run the code
8402.129 -> Excellent, our navigation bar, and our logo looks pretty good
8415.33 -> the next step is we want to be able for a user to click a play
8420.64 -> button icon on each carousel item. And for an appropriate
8424.72 -> movie trailer to play will enlist the help of the React
8428.92 -> player component for this purpose. Let's first create a
8432.82 -> folder named trailer within the components folder.
8442.96 -> Let's create a file named trailer dot j s within the
8446.23 -> trailer folder. Let's also create a file named trailer dot
8450.34 -> css within the trailer folder.
8461.77 -> Let's create the relevant input code in the trailer.js file.
8467.26 -> Let's import the use params hook into our code from the React
8471.37 -> Router DOM NPM package, a YouTube video ID will be passed
8476.47 -> into this component as a parameter. So we are going to
8479.5 -> use the use params hook to extract the relevant parameter
8482.47 -> value from the relevant URL. The relevant parameter will contain
8488.41 -> a YouTube video ID which will allow us to play a YouTube
8493.09 -> video, which is a trailer of the relevant movie to the user.
8503.32 -> Let's import the React player component.
8510.31 -> Let's import the trailer dot css file.
8515.65 -> Let's create the boilerplate code for our trailer component
8518.68 -> by typing in our AFC E and pressing the tab key. Let's
8523.42 -> create a div container in which our React player components will
8526.48 -> reside
8533.23 -> let's assign the Paston parameter value to a const named
8537.13 -> key
8543.52 -> then we can include the React player component appropriately
8546.67 -> like this
8553.99 -> we want the player to include controls. So here we can set the
8558.31 -> controls property to true we can set the playing property to true
8562.3 -> so that the relevant video plays as soon as the trailer component
8565.6 -> loads
8567.52 -> and lastly, and most importantly, we can set the URL
8571.81 -> property to the relevant video on YouTube so we can append the
8576.58 -> relevant YouTube video ID stored in the key const to the base
8581.05 -> YouTube address to point react player to the YouTube video that
8586.06 -> will be played within react player great
8597.94 -> let's go to the app.js file and include the relevant route
8601.57 -> information for the trailer component
8608.98 -> notice how we are able to let React Router DOM know as it were
8612.79 -> about the YouTube video ID parameter then our code within
8616.24 -> the trailer component must access
8633.01 -> let's include a play button icon provided by font awesome within
8637.06 -> our carousel.
8695.17 -> Okay so the play button icon is present, but it needs to be
8698.8 -> appropriately style
8700 -> Okay, as it is tiny at the moment, let's go to the hero dot
8703.75 -> css file and style the play button icon appropriately.
8776.29 -> Great, let's include a media query so that our carousel
8780.88 -> adapts to smaller screens
8793.69 -> Great, let's go to the trailer dot css file and create CSS code
8799.09 -> so that the React player takes up 90% of the viewport height.
8816.52 -> Lastly, we need to create the link so when the play button
8819.01 -> icon is clicked, that the trailer component is invoked,
8822.79 -> and the appropriate parameters passed through to the trailer
8825.91 -> component.
8839.62 -> So the trailer link property retrieved from the server
8843.55 -> contains the entire URL to the YouTube video, we only want to
8848.38 -> pass the ID of the YouTube video to the trailer component from
8852.85 -> the hero component. We can extract the YouTube video ID by
8857.77 -> using the JavaScript substring method to extract the last 11
8862.87 -> characters from the trailer link property like this
8873.88 -> let's run the code.
8896.17 -> Excellent. The last component we need to create is the reviews
8900.1 -> component. The reviews component will enable users to view
8904.09 -> reviews from other users as well as add reviews for movies into
8908.08 -> the system, ie, which entails a HTTP POST request being made.
8913.54 -> From our React component to the relevant remote API endpoints
8917.41 -> carrying the review data entered by the user and the server side
8921.07 -> Java code will then save the review data appropriately to the
8924.97 -> MongoDB database. Firstly, let's create a component named review
8929.62 -> form. This component will contain a form component that
8933.61 -> contains a text area control where the user can enter text
8937.39 -> that denotes a movie review. a submit button will also be
8941.56 -> included so that the user can click this button in order to
8945.37 -> submit the user's movie review. So let's create a folder named
8949.63 -> review form.
8953.29 -> Let's create a file named review form dot j s within the review
8957.04 -> form folder.
8962.26 -> Let's include the code for the functionality we have just
8965.83 -> discussed.
9001.8 -> Let's create the reviews component that will be a parent
9005.55 -> component of the review form child component. Let's create a
9009.69 -> folder named reviews.
9014.519 -> Let's include a file within the reviews folder named reviews dot
9017.849 -> j s
9023.43 -> let's include the appropriate import code at the top of the
9027.03 -> reviews.js file.
9055.35 -> Let's generate the appropriate boilerplate code for the reviews
9058.44 -> React component by typing in RFC E and then pressing the tab key.
9072.6 -> Let's use the use ref hook to reference the text area control
9076.53 -> within the review form. Let's use the use params hook so that
9081.18 -> we can extract the movie ID parameter value from the
9084.24 -> relevant URL.
9095.97 -> This movie ID is actually the IMDB ID of the movie that we
9101.16 -> have retrieved through the API call that is made to retrieve
9104.91 -> the array of movie data from the server. The IMDb ID value, of
9109.35 -> course, is used to uniquely identify a specific movie.
9122.82 -> So when our component first loads,
9126.36 -> we want to call a method that is passed in as a prop to our
9130.83 -> component in order to retrieve the appropriate data for the
9134.82 -> relevant movie that the user wishes to review. So we can use
9139.2 -> the use effect hook like this for this purpose.
9149.19 -> Let's use React bootstrap components for example, the row
9152.91 -> and col components to create an appropriate layout for the
9156.69 -> reviews component, we want to display the poster for the
9160.41 -> relevant movie in the left part of the screen and the reviews in
9165.27 -> the right part of the screen we can use the row and col
9168.6 -> components appropriately to achieve this.
9195.51 -> Let's include the review form element here like this.
9241.53 -> Let's create a method named add review and create the relevant
9245.19 -> HTTP POST request functionality for adding a review to the
9249.15 -> MongoDB database which resides on a remote server.
9283.71 -> And let's write code to update the state of the reviews array
9287.61 -> on the client side. optimistically meaning that we
9291.54 -> are not using data returned from the server ie data that is saved
9294.72 -> to the database for updating the state of the reviews array. We
9298.77 -> are updating the array
9300.359 -> directly from the data entered on the client.
9304.17 -> We also want to include code that clears the relevant text
9307.38 -> area control. Once the user has successfully submitted a review,
9312.15 -> we are updating the state of the reviews array on the client
9315.54 -> through the use of the set reviews method that will be
9318.48 -> passed as a prop from the app component.
9333.69 -> Let's go to the app.js file and create a method that uses Axios
9339 -> to make a get request for data pertaining to a single movie
9349.26 -> so an IMDB ID value will be passed into this method to the
9354.12 -> movie ID parameter and HTTP get request. Using the movie ID
9358.92 -> value appropriately in the URL will be made to retrieve data
9363.75 -> for a single movie from the remote server.
9385.86 -> So let's set the state for the movie variable.
9391.47 -> And to make our code clearer, let's extract the reviews array
9394.83 -> from the movie data and track the state of the reviews array.
9418.26 -> Let's make sure that the appropriate props are being
9420.45 -> passed down to the reviews component.
9502.2 -> We are now able to create reviews for the movies retrieved
9505.62 -> from the remote server ultimately from a MongoDB
9509.49 -> database that stores our movie data. So we are adding reviews
9513.75 -> to our MongoDB database through an appropriate HTTP POST request
9518.16 -> to inappropriate endpoint Excellent.
9595.53 -> One thing we must do whenever we implement a list of uniquely
9598.95 -> identifiable AI
9600 -> items in our JSX code like this
9604.23 -> is appropriately includes the key property for each list item.
9608.16 -> to uniquely identify each item in the carousel, we can set the
9612.6 -> key property for each movie item displayed within the carousel to
9618.72 -> the appropriate IMDb ID value for each movie. This value has
9623.94 -> been passed down to us with the movie data array that we
9627.99 -> retrieved from the remote server using the appropriate HTTP get
9632.25 -> request. I hope you've enjoyed building this front end using
9636.48 -> React. And I hope you feel that you have benefited from this
9640.08 -> course.
9642.3 -> If you've got to the end of this course you've done exceptionally
9644.85 -> well. Thank you and take care

Source: https://www.youtube.com/watch?v=5PdEmeopJVQ