Creating RESTful Services and Understanding its components
RESTful APIs are present in most modern applications we use every day, from reading Twitter messages or visiting Facebook pages to reading our emails or doing a Google search. With a lightweight communication protocol and an emphasis on resources, states, and verbs, they have become a natural language for the interchange of information through the HTTP protocol. In this blog, we will understand how we can create our own RESTful APIs using Kotlin and the Spring framework. We will learn how we can receive parameters, and how HTTP verbs and status will make our APIs define their ubiquitous language. We spoke about a ubiquitous language in our Domain-Driven Design blog, Understanding Microservices. Furthermore, we will learn how to handle JSON requests and responses in our APIs. And finally, we will review how Spring allows us to handle errors in our microservices.
In this blog, We will learn about:
RestController
Request Mapping
Path Variable
RequestParam
Response Entity and Response Body
Controller Advice
Understanding RestController
Any RESTful API needs to answer requests coming from their client; these requests are handled in Spring by a controller object. In this section, we will understand what a controller actually is and how the RestController will help us to create our first component in a RESTful API.
What is a controller
Each request coming to a RESTful API is a stateless message that mainly will: Ask for a resource Update a resource Create a resource Delete a resource Those requests will use JSON as the mechanism to interchange information. JavaScript Object Notation (JSON) is a human-readable data format to transmit objects. It is a language-independent data format, but it was derived from JavaScript. Most programming languages include code to generate and parse JSON-format data. Requests in a Spring web application are handled by a controller, a specialized component whose mission is to handle requests from a client and send responses back. Controllers can be used for a variety of communication protocols, but since we are going to do a RESTful API, we will use a RestController. RestController will specify that our controller will handle the request and output a body; this will help us create our responses.
Creating a RestController
For creating our controller, we will start generating a new Spring Boot Application using Spring Initializr, visiting the website: https://start.spring.io/.To create a new project, we will choose Maven project with Kotlin and Spring Boot 3.1.0 . in Spring Initializr. For the project metadata, we will set a Group com.microservices, and Artifact, and as Dependencies, we will include Web. Now, we will unzip the generated project and open it with IntelliJ IDEA. In the Project window, we will right-click in our package, com.microservices, and we will choose in the drop-down menu, Kotlin File/Class. In the new dialog, we will choose to create a class named CustomerController, and we will write the following code:
package com.microservices
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.ResponseBody
import org.springframework.web.bind.annotation.RestController
@RestController
class CustomerController {
@RequestMapping(value = "/customer", method = arrayOf(RequestMethod.GET))
fun getCustomer() = "hello from a controller"
}
If we insert in our browser the URL http://localhost:8080/customer, we will get a message saying"hello from a controller". Since RESTful services are about returning resources, let's create a class that represents a resource, for example, a customer creating a class named Customer:
package com.microservices
data class Customer(var id: Int = 0, var name: String = "")
Understanding our controller
In our example, we have created a controller using the Spring annotation @RestController. This controller will be picked up by the component scan, at the application startup and will be added to our Spring context as a bean, Getting Started with Spring Boot 3.1.0. In this controller, we have set a mapping using @RequestMapping, for the URL /customer, to accept GET requests. Since it is a RestController , the response will output as a JSON Object. This mapping will be autoconfigured by Spring Boot and wired into our web application. If we check our application log when we start the microservice, we can see, among other messages.When everything is up and running for each request to the mapped URL, our method will be executed and a new instance of the Customer object will be created and converted to JSON to be sent back as a response to the request.
Path and request parameters
Now that we have an understanding of how we can return data in a controller, we should learn how we can ask for a particular resource so we can filter the information and return it as a response. In RESTful APIs, when an application invokes our services for a particular resource, it will query through the URL path, the desired information to be returned. For example, if an application invokes our API with the URL /customer/1, it is indicating that the resource that has been queried is a particular customer 1 in this example. But RESTful APIs also allow us to extend a request further providing additional information through parameters. An application could invoke our API using the URL /customers, indicating the need to receive the customer list. But that URL could provide an additional parameter to specify a filter, for example, to search customers by name giving the URL /customers?nameFilter="lin". We should never filter the resource that's been requested through request parameters. In RESTful APIs, this is always done through path variables.
Understanding path variables
Spring has mapped our new URL to receive a parameter. We have specified that its name will be an id using curly braces on the URL, /customer/{id} in our example.
Then, we will create an argument for our method getCustomer that is named exactly id, and we have annotated this method with the annotation @PathVariable and will specify its type to be an Int. When Spring is autoconfiguring our controller, we will understand this annotation and will map the value pass in the URL to the value required to our method, and it will convert it to the right data type specified. This is a very powerful feature that allows us to easily do mapping on path variables in our methods without requiring any kind of configuration.
Understanding request parameters
In RequestMapping, we do not define parameters using the URL as we did in path variables. We declared them as parameters in our functions and annotated with the @RequestParam annotation. In the annotation, we can specify if the parameter is a required parameter, and if it has a default value, so if it is not present, that value will get injected in our mapping method. The default value must always be a string, and Spring will convert it back to any other type automatically. We can define as many parameters as we like, and they will be separated with and in the URL. With this last addition, we can start to create more flexible APIs that will handle those parameters to tweak our functionality. Be cautious about how many parameters we use, and what they are for. If you are starting to make an API behave really differently because of something in the parameters, it could be an indication that a different API may be required.
HTTP verbs and statuses
In RESTful APIs, we use standard HTTP verbs to indicate what we need to do with a particular resource. These verbs define what the client needs to do, but we need to answer in our microservice what response we give back. For example, when a client asks for a specific customer using the URL http://localhost:8080/customer/1 with the HTTP verb GET, we can answer back with a status 200 OK, or with a 404 NOT FOUND, if we don't find the customer. This two-way communication becomes part of a conversation between the client and the API and will form our ubiquitous language.
Standard HTTP verbs and statuses
In RESTful APIs, HTTP verbs and statuses are very flexible, and our application can decide how to use them, but there are a set of standard and well-known patterns to combine them.
Single resources
Considering that we are using an API that provides a resource through a URL, for example /customer, we can use:
URL =/customer/1, Verb=GET , Status=200 OK , Meaning=We asked for a specific customer, and got back the result
URL =/customer/1 , Verb=GET ,Status=404 NOT FOUND ,Meaning=We asked for a specific customer, but they could not be found
URL=/customer ,Verb=POST ,Status=201 CREATED ,Meaning=We asked to create a new customer, and it was created
URL=/customer ,Verb=POST ,Status=400 BAD REQUEST ,Meaning=We asked to create a new customer, but the data was not correct
URL=/customer/1 ,Verb=PUT ,Status=202 ACCEPTED ,Meaning=We asked to update a customer, and it was updated correctly
URL=/customer/1 ,Verb=PUT ,Status=404 NOT FOUND ,Meaning=We asked to update a customer, but the customer was not found
URL=/customer/1 ,Verb=DELETE ,Status=200 OK ,Meaning=We asked to delete a customer, and we did it correctly
URL=/customer/1 ,Verb=DELETE ,Status=404 NOT FOUND ,Meaning=We asked to delete a customer, but it could not be found
Collections
If we are using an API to provide a collection of resources, for example, a list of customers giving the URL/customers, we can use:
/customers/ GET 200 OK We asked for a list of customers and got back the result
/customers/ GET 204 NO CONTENT We asked for a list of customers, and there was none
/customers/?name=son GET 200 OK We asked for a list of customers filtering the results
/customers/?name=son GET 204 NO CONTENT The filtering of customers returned no results
/customers/?name=# GET 400 BAD REQUEST The filtering for customers was incorrect
Note : Follow this blog for code https://androidcodingworld.blogspot.com/2023/05/spring-boot-application-structure.html
No comments:
Post a Comment