Summary
Highlights
This section introduces a new series on building an end-to-end movie booking application backend with NodeJS, ExpressJS, and MongoDB. The core competency is to help beginners and intermediate developers understand project structuring. The video will focus on API development and the booking flow. The discussion then moves to the MVC (Model-View-Controller) architectural pattern. MVC, a design pattern from the 1970s, is popular in frameworks like Python Django and Ruby on Rails. It segregates code into three sections: Views, Controllers, and Models. Views are what the user interacts with (UI). Controllers receive requests from views, validate them, and pass them to models. Models apply business logic and interact with databases. The concept is explained with a restaurant analogy, where cooks are models, waiters are controllers, and customers are views.
The video moves to implementing the movie creation API. The API route will be '/MBA/API/v1/movies' with a POST request type. The movie details (name, description, casts, trailer URL, language, release date, director, release status) will be sent in the request body as a JSON object. The response will include 'success', 'error', 'message', 'data' (the created movie object), and a 'status code' (201 for successful creation). The implementation involves creating 'movie.routes.js' and 'movie.controller.js' files. The controller will handle the request and use the 'movie.create' function from the Movie Model to store data. After successful creation, a JSON response with status 201 is returned; otherwise, a 500 internal server error is returned.
The newly implemented movie creation API is tested using Postman. A sample movie, 'Jun', is created successfully, demonstrating the API's functionality. The video then addresses a minor issue with array handling for 'casts' in MongoDB, showing how to correctly pass array data in JSON. Two movies, 'Jun' and 'Kashmir Files', are created and verified in MongoDB Compass. The section concludes by committing the changes to Git and outlining future improvements.
To improve the development workflow, Nodemon is introduced. Nodemon automatically restarts the Node.js application upon file changes, eliminating the need for manual restarts. Installation and usage with 'npx nodemon index.js' and as an npm script ('npm start') are demonstrated. Next, the 'body-parser' package is installed to enable ExpressJS to read body parameters from incoming requests. 'body-parser.urlencoded' and 'body-parser.json' middlewares are configured in 'index.js' to parse different request body types. The video briefly explains 'request.query' and 'request.params' for accessing URL parameters and query strings.
The video emphasizes the importance of a well-structured folder based on the MVC architecture. 'controllers', 'models', and 'routes' folders are created. The '.env' package is then introduced to manage environment variables. This allows for flexible configuration, such as defining different port numbers for development and production environments. The installation of '.env' and creation of a '.env' file to store variables like 'PORT=3000' are explained. The hardcoded port in 'index.js' is replaced with 'process.env.PORT', enabling dynamic configuration.
The implementation of a GET API to retrieve movie details by ID is discussed. The route will be '/MBA/API/v1/movies/:id' with 'id' being a URL parameter. The request type will be GET, and no request body is expected. The response format will include 'success', 'error', 'message', 'data' (the movie object), and a status code (200 for success, 404 for not found). The 'getMovie' controller function is created, utilizing 'Movie.findById' from the model. The controller handles success and error responses, returning appropriate JSON and HTTP status codes.
Testing the 'getMovie' API reveals an issue: if a movie is not found, a 200 OK status is returned instead of a 404 Not Found. This highlights the need for better error handling and separation of concerns. To address this, a 'services' folder and 'movie.service.js' file are introduced. The business logic for finding a movie and generating specific error messages (e.g., 'no movie found') with appropriate status codes (like 404) is moved to the service layer. The controller now calls the service, which acts as an intermediary, returning a structured response that the controller uses to build the final API response. This approach maintains thin controllers and centralizes business logic.
The video then focuses on implementing an API to delete a movie resource. The API route is '/MBA/API/v1/movies/:movieId', where ':movieId' is a URL parameter representing the ID of the movie to be deleted. The request type is DELETE, adhering to REST conventions. The request body is expected to be empty. The response will indicate success or failure, provide a message, and return the deleted count in the 'data' field. A 'deleteMovie' controller function is created, which uses 'Movie.deleteOne' from the Mongoose model. The controller extracts the 'movieId' from 'request.params' and uses it to delete the movie. A 200 status code is returned for successful deletion, and a 500 status code for internal server errors. The 'deleteMovie' function is exported and configured in 'movie.routes.js'.
The 'deleteMovie' API is tested using Postman. A movie is successfully deleted, with the response indicating 'acknowledged: true' and 'deletedCount: 1'. The MongoDB Compass is refreshed to confirm the movie's removal. The video then addresses a previous error in the 'getMovie' API where an 'await' keyword was missing, causing incorrect promise handling. This fix ensures accurate movie fetching and error reporting (e.g., 404 for not found). The code is further refactored to use 'successResponseBody' and 'errorResponseBody' utility objects for consistent API responses across all controllers, leading to cleaner code and promoting reusability. The 'create' and 'delete' logic is also moved into the service layer to keep controllers lean.
The video demonstrates how to implement validation in the Mongoose schema (e.g., a minimum length of 5 for movie descriptions). When an invalid request is sent (e.g., a description shorter than 5 characters), the backend now returns a 500 Internal Server Error. The instructor explains that this should ideally be a client-side error (4xx series). To achieve this, the service layer is enhanced to catch validation errors (`ValidationError`) and construct a custom error response object. This object includes specific error messages for each invalid field, allowing the frontend to display targeted feedback. The HTTP status code is changed to 422 (Unprocessable Entity) for semantic errors. The 'create' function in the service layer now handles these validation errors, returning a structured error response that the controller then processes, providing clear and informative error messages to the client.
The video demonstrates how the system distinguishes between validation errors (422) and true internal server errors (500). By artificially introducing a server-side error, it shows that a 500 status code is returned. Conversely, when a validation rule is violated, a 422 status with detailed error messages is provided. This robust error handling, facilitated by segregating logic into the service layer, prevents controllers from becoming bulky and ensures precise feedback to the user.