In this chapter, we will first create a RESTful web service using the controller class. After that, we will demonstrate how to use Spring Data REST to create a RESTful web service that also provides all CRUD functionalities automatically. After you have created a RESTful API for your application, you can implement the frontend using a JavaScript library such as React. We will be using the database application that we created in the previous chapter as a starting point.
Web services are applications that communicate over the internet using the HTTP protocol. There are many different types of web service architectures, but the principal idea across all designs is the same. In this book, we are creating a RESTful web service from what is nowadays a really popular design.
In this chapter, we will cover the following topics:
The Spring Boot application created in the previous chapters is required. Postman, cURL, or another suitable tool for transferring data using various HTTP methods is also necessary.
The following GitHub link will also be required: https://github.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/tree/main/Chapter04.
Check out the following video to see the Code in Action: https://bit.ly/3PP2SOn
Representational State Transfer (REST) is an architectural style for creating web services. REST is not a standard, but it defines a set of constraints defined by Roy Fielding. The six constraints are as follows:
The uniform interface is an important constraint, and it means that every REST architecture should have the following elements:
The RESTful web service that we are going to develop in the following topics follows the REST architectural principles above.
In Spring Boot, all HTTP requests are handled by controller classes. To be able to create a RESTful web service, first, we have to create a controller class. We will create our own Java package for our controller:
Important Note
If you create classes in the wrong package accidentally, you can drag and drop the files between packages in the Eclipse Project Explorer. Sometimes, the Eclipse Project Explorer view might not be rendered correctly when you make some changes. Refreshing Project Explorer helps (activate Project Explorer and press F5).
package com.packt.cardatabase.web;
import org.springframework.web.bind.annotation.
RestController;
@RestController
public class CarController {
}
package com.packt.cardatabase.web;
import org.springframework.web.bind.annotation.
RequestMapping;
import org.springframework.web.bind.annotation.
RestController;
@RestController
public class CarController {
@RequestMapping("/cars")
public Iterable<Car> getCars() {
// Fetch and return cars
}
}
The getCars() method returns all the car objects, which are then marshaled to JSON objects by the Jackson library (https://github.com/FasterXML/jackson).
By default, @RequestMapping handles all the HTTP method (GET, PUT, POST, and so on) requests. You can define which method is accepted using the following @RequestMapping(value="/cars", method=GET) parameter. Now, this method handles only GET requests from the /cars endpoint. You can also use the @GetMapping annotation instead and then only the GET requests are mapped to the getCars() method. There are other annotations for the different HTTP methods, such as @GetMapping, @PostMapping, @DeleteMapping, and so on.
package com.packt.cardatabase.web;
import org.springframework.beans.factory.annotation.
Autowired;
import org.springframework.web.bind.annotation.
RequestMapping;
import org.springframework.web.bind.annotation.
RestController;
import com.packt.cardatabase.domain.Car;
import com.packt.cardatabase.domain.CarRepository;
@RestController
public class CarController {
@Autowired
private CarRepository repository;
@RequestMapping("/cars")
public Iterable<Car> getCars() {
return repository.findAll();
}
}
// Owner.java
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer",
"handler"})
public class Owner {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long ownerid;
private String firstname, lastname;
public Owner() {}
public Owner(String firstname, String lastname) {
super();
this.firstname = firstname;
this.lastname = lastname;
}
@JsonIgnore
@OneToMany(cascade=CascadeType.ALL, mappedBy=
"owner")
private List<Car> cars;
Important Note
Your output might differ from the screenshot due to using a different browser. In this book, we are using the Chrome browser and the JSON Viewer extension, which makes JSON output more readable. JSON Viewer can be downloaded from the Chrome Web Store for free.
We have written our first RESTful web service, which returns all the cars. Spring Boot provides a much more powerful way of creating RESTful web services and we go through this in the next topic.
Spring Data REST (https://spring.io/projects/spring-data-rest) is part of the Spring Data project. It offers an easy and fast way to implement RESTful web services with Spring. To start using Spring Data REST, you have to add the following dependency to the pom.xml file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
By default, Spring Data REST finds all public repositories from the application and creates RESTful web services for your entities automatically. In our case, we have two repositories: CarRepository and OwnerRepository, therefore Spring Data REST creates RESTful web services automatically for those repositories.
You can define the endpoint of service in your application.properties file as follows:
spring.data.rest.basePath=/api
Now, you can access the RESTful web service from the localhost:8080/api endpoint. By calling the root endpoint of the service, it returns the resources that are available. Spring Data REST returns JSON data in the Hypertext Application Language (HAL) format. The HAL format provides a set of conventions for expressing hyperlinks in JSON and it makes your RESTful web service easier to use for frontend developers:
We can see that there are links to the car and owner entity services. The Spring Data REST service path name is derived from the entity class name. The name will then be pluralized and uncapitalized. For example, the entity Car service path name will be cars. The profile link is generated by Spring Data REST and contains application-specific metadata. If you want to use different path naming, you can use the @RepositoryRestResouce annotation in your repository class as shown in the next example:
package com.packt.cardatabase.domain;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.
RepositoryRestResource;
@RepositoryRestResource(path="vehicles")
public interface CarRepository extends CrudRepository<Car,
Long> {
}
Now, if you call the endpoint localhost:8080/api, you can see that endpoint is changed from /cars to /vehicles.
You can remove the different naming and we will continue with the default endpoint name, /cars.
Now, we'll start to examine different services more carefully. There are multiple tools available for testing and consuming RESTful web services. In this book, we are using the Postman (https://www.postman.com/downloads/) desktop app, but you can use tools that you are familiar with, such as cURL. Postman can be acquired as a desktop application or as a browser plugin. cURL is also available for Windows 10 by using Windows Ubuntu Bash.
If you make a request to the /cars endpoint, http://localhost:8080/api/cars, using the GET method (note, you can use a web browser for GET requests), you will get a list of all the cars, as shown in the following screenshot:
In the JSON response, you can see that there is an array of cars, and each car contains car-specific data. All the cars also have the _links attribute, which is a collection of links, and with these links, you can access the car itself or get the owner of the car. To access one specific car, the path will be http://localhost:8080/api/cars/{id}.
The GET request to http://localhost:8080/api/cars/3/owner returns the owner of the car with id 3. The response now contains owner data, a link to the owner, and links to other cars of the owner:
The Spring Data REST service provides all CRUD operations. The following table shows which HTTP methods you can use for different CRUD operations:
Next, we will look at how to delete a car from the database by using our RESTful web service. In a delete operation, you have to use the DELETE method and the link to the car that will be deleted (http://localhost:8080/api/cars/{id}).
The following screenshot shows how you can delete one car with id 3 by using the Postman desktop app (note, you have to check some car id from your database and use that instead). In Postman, you have to select the correct HTTP method from the drop-down list, enter the request URL, and then click the Send button:
If everything went correctly, you will see the response status 204 No Content in Postman. After the successful delete request, you will also see that there are now two cars left in the database if you make a GET request to the http://localhost:8080/api/cars/ endpoint. If you got the 404 Not Found status in the response, check that you are using a car ID that exists in the database.
When we want to add a new car to the database, we have to use the POST method, and the request URL is http://localhost:8080/api/cars. The header must contain the Content-Type field with the value application/json, and the new car object will be embedded in the request body in JSON format. Here is one car example:
{
"brand":"Toyota",
"model":"Corolla",
"color":"silver",
"registerNumber":"BBA-3122",
"year":2021,
"price":32000
}
If you click the Body tab and select raw in Postman, you can type a new car JSON string to the Body tab as shown in the following screenshot:
You also have to set a header by clicking the Headers tab in Postman, as shown in the following screenshot:
The response will send a newly created car object back and the status of the response will be 201 Created if everything went correctly. Now, if you again make a GET request to the http://localhost:8080/api/cars path, you will see that the new car exists in the database:
To update entities, we can use the PATCH method and the link to the car that we want to update (http://localhost:8080/api/cars/{id}). The header must contain the Content-Type field with the value application/json, and the car object with edited data will be given inside the request body. If you are using PATCH, you have to send only fields that are updated. If you are using PUT, you have to include all fields in the request body.
Let's edit the car that we created in the previous example, and we will change the color to white. The Postman request is shown in the following screenshot (note, we set the header as in the POST example and use the car id in the URL):
If update succeeded, the response status is 200 OK. If you now fetch the updated car by using the GET request, you will see that the color is updated.
Next, we will add an owner to the new car that we just created. We can use the PUT method and the http://localhost:8080/api/cars/{id}/owner path. In this example, the ID of the new car is 6, therefore the link is http://localhost:8080/api/cars/6/owner. The content of the body is now linked to an owner, for example, http://localhost:8080/api/owners/1.
The Content-Type value of the headers should be text/uri-list in this case.
Finally, you can make a GET request for the car's owner and you should see that now the owner is linked to the car as shown in the following screenshot:
In the previous chapter, we created queries to our repository. These queries can also be included in our service. To include queries, you have to add the @RepositoryRestResource annotation to the repository class. Query parameters are annotated with the @Param annotation. The following source code shows CarRepository with these annotations:
package com.packt.cardatabase.domain;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.
RepositoryRestResource;
@RepositoryRestResource
public interface CarRepository extends CrudRepository<Car,
Long> {
// Fetch cars by brand
List<Car> findByBrand(@Param("brand") String brand);
// Fetch cars by color
List<Car> findByColor(@Param("color") String color);
}
Now, when you make a GET request to the http://localhost:8080/api/cars path, you can see that there is a new endpoint called /search. Calling the http://localhost:8080/api/cars/search path returns the following response:
From the response, you can see that both queries are now available in our service. The following URL demonstrates how to fetch cars by brand: http://localhost:8080/api/cars/search/findByBrand?brand=Ford.
The following screenshot is the output of the preceding URL:
We have now created the RESTful API to our backend, and we will consume that later with our React frontend.
In this chapter, we created a RESTful web service with Spring Boot. First, we created a controller and one method that returns all cars in JSON format. Next, we used Spring Data REST to get a fully functional web service with all CRUD functionalities. We covered different types of requests that are needed to use CRUD functionalities of the service that we created. Finally, we also included our queries to RESTful web service.
In the next chapter, we will secure our backend using Spring Security.
Packt has other great resources available for learning about Spring Boot RESTful web services:
3.149.254.7