"Welcome To Ashok IT" "Spring Boot & Microservices" Topic : Rest API Development Date : 23/12/2024 (Session - 91) _____________________________________________________________________________________________________________________________ Yesterday Session ================== * We have completed the Serialiation & Deserialization process using Jackson API. * We have Completed introduction about Spring Rest API Development. Spring Rest (or) Spring Boot Rest is an extension of Spring MVC (or) Spring Boot MVC Development Spring Rest = Spring MVC ++ & Spring Boot Rest = Spring Boot MVC++ In order to work with Spring boot Rest Development with help of Spring Boot web Starter dependency. * We discussed about @RestController is specialized version of @Controller Annotaion @RestController = @Controller + @ResponseBody * @ResponseBody Annotation helps us to transfer response in Response Body. * Basically Rest API Development comes two Parts 1) Producer Application Development. 2) Consumer Application Development. Today Session : Developing First Rest API Application ===================================================== Step-1 : Open STS IDE and create spring Boot Starter Aplication with below Dependencies i.e.,Web Starter and Packing Mode as "WAR". Step-2 : Create Some packages under "src/main/java" for Holding Layered Components com.ashokit.controller >>>>>>>> For Storing Rest Controller Classes com.ashokit.services >>>>>>>> For Storing services Classes com.ashokit.dao >>>>>>>> For Storing DAO Classes com.ashokit.dto >>>>>>>> For Storing DTO(Data Transfer Object) Classes Entity Classes (10 Fields) are used for communicating with Database Binding classes(5 Fields) are used for mapping consumer request into Java object at Producer Application DTO Classes are used for transferring data from one layer to another layer in application. Step-3 : Develop the Rest Controller class using below code WishResource.java ================= package com.ashokit.producer.resources; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/api/wishes") public class WishResources { @GetMapping(value="/") public ResponseEntity generateWishes(){ String wishMessage ="Welcome To AshokIT For Rest API Development"+ new java.util.Date(); return new ResponseEntity(wishMessage,HttpStatus.OK); } } LoginResource.java ================== package com.ashokit.producer.resources; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/v1/login") public class LoginResource { @GetMapping("/") public ResponseEntity getLoginStatus(@RequestParam("username") String username, @RequestParam("password") String password){ //validating the login Credentials if(username != null && password != null) { if("Mahesh".equalsIgnoreCase(username) && "Mahesh".equalsIgnoreCase(password)) { return new ResponseEntity("Login Success....." ,HttpStatus.OK); }else { return new ResponseEntity("Login Failure Due to either Username or Password are Incorrect....." ,HttpStatus.OK); } }else { return new ResponseEntity("Username & Password Can't be Empty....." ,HttpStatus.OK); } } } CustomerResource.java ===================== package com.ashokit.producer.resources; import java.util.List; import java.util.Optional; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ashokit.producer.binding.Customer; import com.ashokit.producer.utils.CustomerUtils; @RestController @RequestMapping("/api/customers") public class CustomerResource { @GetMapping(value="/") public ResponseEntity> getAllCustomers(){ List allCustomers = CustomerUtils.getAllCustomers(); return new ResponseEntity>(allCustomers,HttpStatus.OK); } @GetMapping(value="/{customerId}") public ResponseEntity getCustomersDetails(@PathVariable("customerId") String customerId){ //Get All Customers List allcustomers = CustomerUtils.getAllCustomers(); //filtering the customer based on customerId path variable Optional customerOpt = allcustomers.stream().filter(eachCustomer -> eachCustomer.getCustomerId().equals(customerId)).findFirst(); if(customerOpt.isPresent()) { return new ResponseEntity(customerOpt.get(),HttpStatus.OK); }else { return new ResponseEntity("Customer Data Not Found With Supplied CustomerId...",HttpStatus.OK); } } } Step-4 : Changing the port no of spring boot application(application.properties) server.port=1234 Step-5 : Start the Server and test the "Get" Request by using Browser Software Wish Resources ::::::::::: http://localhost:1234/api/wishes/ Login Resource ::::::::::: http://localhost:1234/api/login/validate?username=Mahesh&Password=Mahesh Customer Resource ::::::::: http://localhost:1234/api/customers/ >>>> Get All Customers http://localhost:1234/api/customers/AIT123 >>>>> Getting Specific Customer.. Inorder to test the GETRequest we need to download & Install "PostMan" Tool. POSTMAN is an Unit Testing of Rest API Tool Query Parameters ================ * Query parameters will represent the data in the form of key-value pairs * Query Parameters will send to Server in the URL. * Query Parameters should present only at the end of the URL. * Query Parameters will always starts from ? symbol in the URL. * Query Parameters will be seperated by & Symbol. http://localhost:8787/user?uname=mahesh&pwd=ashokit * In order to read the Request parameter we will use @RequestParam annotation. Path Parameters =============== * Path Parameters are used to send data from client to Server in URL. * Path Parameters will represent data directly in URL and Keys will not be available in Path Parameters. * To uses path Parameters we have to respresent them in url pattern like below http://localhost:8787/{userId}/{roleName} * Multiple Path variables will be seperated by "/" and every path variable is enclosed with curly braces "{}". * To read the Path Variables in Request Handler method we will use @PathVariable Annotation. Query Parameters VS Path Parameters =================================== * Query Parameters & Path Parameters both are used to send data to server in URL. * Query Parameters represents the data in the form of Key-value pairs Path Parameters represents the data directly with out keys. * Query Parameters will start with ? and will be seperated by &. Path Parameters will start with / and will be seperated by / only. * To Read the Query Parameters we will use @RequestParam Annotation To Read the Path Parameters we will use @PathVariable annotation. * Query Parameters will not represented in URL Pattern Path Paramaters will be represented in URL Pattern as segments. NOTE ==== * whenever we wanted to send limited data to server either GET (or) POST always recommended for Query parameters (or) path Parameters. * We shouldn't use Query Parameters & Path Parameters for Sensitive Data like usernames,password,creditcardnumbers,atmpins etc., Post Request in Rest API Development ==================================== * Post Request is used for posting/sending data to server and for every Post Request always we do have "Request Body". * In Spring MVC/Spring Boot MVC Concepts we are able to send the data to Server through Html Form page/JSP page/Thymeleaf Page. * In REST API Development of an Post Request always using RequestBody Section for sending Data from Consumer Application to Producer Application. * In order to map the Request Handler Method of an Post Request we need to use the @PostMapping Annotation. * In Post Request Handler Method to Accept the Data either XML (or) JSON and convert into Java Object we need to use another annotation i.e.,@RequestBody Request Body (raw >>> JSON) Producer Application =========================== ===================== { @PostMapping(value="/create") "customerId" : 123456, public ResponseEntity createRecord(@RequestBody Customer customer){ "customerName" :"Mahesh", >>>> ------------------------------- "customerLocation":"Hyderabad" } } NOTE ==== * Post Request Can't be tested through Browser Window always it should be tested through PostMan Tool. Application =========== package com.ashokit.controller; import java.util.List; import java.util.Optional; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ashokit.dto.Customer; import com.ashokit.util.CustomerUtils; @RestController @RequestMapping(value = "/customers") public class CustomerController { @GetMapping(value="/") public ResponseEntity> getAllCustomers(){ List customers = CustomerUtils.getAllCustomers(); return new ResponseEntity>(customers,HttpStatus.OK); } @GetMapping(value="/{customerId}") public ResponseEntity getCustomerDetailsById(@PathVariable("customerId") Integer customerId){ Customer customerDetails = CustomerUtils.getCustomerDetailsById(customerId); return new ResponseEntity(customerDetails,HttpStatus.OK); } @PostMapping(value="/",consumes = {"application/json","application/xml"}) //@PostMapping(value="/",consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}) public ResponseEntity createNewCustomer(@RequestBody Customer customer){ System.out.println("Customer Object:::::" + customer); Optional custOpt = Optional.of(customer); int customerId=0; if(custOpt.isPresent()) { customerId = customer.getCustomerId(); } return new ResponseEntity(customerId+" Record Created Successfully",HttpStatus.CREATED); } } Execution For Testing POST Request API ====================================== 1) We need to open the POST Man in our Machine. 2) Select our API Collection in left side navigation and clicke on "three dots" button and select "Add Request" Option. 3) Select Request types from Dropdown "POST" and specify the API URL in int address bar as below http ://localhost:8787/customers/ 4) Select "Request Body" option and Again we need to select "raw" option and again select "JSON" option from dropdown and find below sample Request body for testing POST Request API { "customerName":"Mahesh", "customerLocation":"Hyderabad" } 5) Finally click on "Send" but to Hit our request of Our API. 6) If we want to test our POST Request API with XML Request body we need select Request Body >>>> raw option >>>> XML Option Mahesh Hyderabad NOTE ==== * By default every handler method in Rest Controller class will accept only JSON data and will return as JSON only. * When we wanted to accept xml data or returning xml data from Rest API then definetly need to add the below dependency in pom.xml file com.fasterxml.jackson.dataformat jackson-dataformat-xml NOTE ==== * Here Serialization will be taken care by @RequestBody Annotation and we no need to perform explictly(JSON To Java Object). 400 >>>>>>>>>>>> Bad Request (When you forgot to send Request body for Post Request) 404 >>>>>>>>>>>> Resource Not Found(When you made mistake in Request URL) 415 >>>>>>>>>>>> Unsupported MediaType Error (Request Handler method only accepting JSON data but client sending xml data) Consumes Attribute ================== * It Representing the Input Format allowing by Request Handler Method/Resource Handler Method. * If your Request Handler Method are allowing only JSON Data Format @PostMapping(value ="\", consumes ={"application/json"}) >>>> application/json (MEDIATYPE For JSON DATA) @PostMapping(value="\",consumes= MediaType.APPLICATION_JSON_VALUE) * Suppose If the client is sending Data through Request body in xml format and our request handler method is allowing JSON data format only in this case data format will be mismatched and get error as "415(UnsupportedMediaType)". * If your Request Hanlder Method are alllowing only XML Data Format @PostMapping(value="\", consumes={"application/xml"}) @PostMapping(value="\",consumes=MediaType.APPLICATION_XML_VALUE) ContentType =========== * ContentType is one of Implict Request Header in Request. * ContentType header represents Client Sending Data Format. * For this Header automatically POSTMAN Tool will pick value of MEDIATYPE based data available in Request Body. Request Body(JSON) >>>>>>>>>>>>>> content-type(application/json) >>>>> automatically Request Body(XML) >>>>>>>>>>>>>> content-type(application/xml) >>>>> automatically Produces ======== * It Represents the Output Format suppported by the Resource Method/Request Handler Method. * If your Resource Handler Method sending back the JSON as Output then we need to use below annotation @PostMapping(value="\",produces ={"application/json"} consumes={"application/json"}) >>>> Input (JSON),Output(JSON) * If your Resource Hanlder method sending back the XML as outuput then we need to use below annotation @PostMapping(value="\",produces={"application/xml"},consumes={"application/xml"}) >>>>> Input (XML),Output(XML) * If your Resource Handler method sending as JSON as ouput but input receiving as XML we need to use below annotation @PostMapping(value="\",produces={"application/json"},consumes={"application/xml"}) >>>>> Input (XML),Output(JSON) * If your Resource Handler method sending as XML as ouput but input receiving as JSON we need to use below annotation @PostMapping(value="\",produces={"application/xml"},consumes={"application/json"}) >>>>> Input (JSON),Output(XML) Accept ====== * It representing the Client Expected Response format from Resource Handler method. * By default this header in POSTMAN tool as "Accept:*/*" (Post Man Can process any type of data). * If you want this customize simple disable the POSTMAN Given header by clicking on checkbox and add new entry for same header key(Accept) : (application/json (or) application/xml) NOTE ==== * If input formats are got mismatched(Client-> xml , Producer -> JSON) >>>>>>>>>>>>> 415 UnSupported Media Type * If output formats are got mismatched(Client -> JSON, Producer -> XML) >>>>>>>>>>>>> 406 Not Acceptable +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++