1. Overview
In this tutorial, we're going to take a quick look at two important HTTP methods – PUT and POST – that are frequently used within the REST architecture. It's no secret that developers sometimes struggle to choose between these two methods while designing a RESTful web service. Therefore, we'll address this issue with a simple implementation of a RESTful application in Spring Boot.
2. PUT vs POST Dilemma
In a typical REST architecture, a client sends requests in the form of HTTP methods to the server to create, retrieve, modify, or destroy resources. While both PUT and POST can be used to create resources, there are significant differences between them in terms of their intended applications.
According to the RFC 2616 standard, the POST method should be used to request the server to accept the enclosed entity as a subordinate of the existing resource identified by the Request-URI. This means the POST method call will create a child resource under a collection of resources.
On the other hand, the PUT method should be used to request the server to store the enclosed entity under the provided Request-URI. If the Request-URI points to an existing resource on the server, the supplied entity will be considered a modified version of the existing resource. Therefore, the PUT method call will either create a new resource or update an existing one.
Another important difference between the methods is that PUT is an idempotent method while POST is not. For instance, calling the PUT method multiple times will either create or update the same resource. On the contrary, multiple POST requests will lead to the creation of the same resource multiple times.
3. Sample Application
To demonstrate the difference between PUT and POST, we're going to create a simple RESTful web application using Spring Boot. The application will store the names and addresses of people.
3.1. Maven Dependencies
To begin with, we need to include the dependencies for Spring Web, Spring Data JPA, and the in-memory H2 database in our pom.xml file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
3.2. Domain Entity and Repository Interface
Let's start by creating the domain object first. For the address book, let's define an Entity class called Address that we'll use to store address information of individuals. For the sake of simplicity, we're going to use three fields – name, city, and postalCode – for our Address entity:
@Entity
public class Address {
private @Id @GeneratedValue Long id;
private String name;
private String city;
private String postalCode;
// constructors, getters, and setters
}
The next step is to access the data from the database. For simplicity, we'll leverage Spring Data JPA's JpaRepository. This will allow us to perform CRUD functionalities on the data without writing any additional code:
public interface AddressRepository extends JpaRepository<Address, Long> {
}
3.3. REST Controller
Finally, we need to define the API endpoints for our application. We'll create a RestController that will consume HTTP requests from the client and send back the appropriate response.
Here, we'll define a @PostMapping for creating new addresses and storing them in the database and a @PutMapping to update the content of the address book based on the request URI. If the URI is not found, it will create a new address and store it in the database:
@RestController
public class AddressController {
private final AddressRepository repository;
AddressController(AddressRepository repository) {
this.repository = repository;
}
@PostMapping("/addresses")
Address createNewAddress(@RequestBody Address newAddress) {
return repository.save(newAddress);
}
@PutMapping("/addresses/{id}")
Address replaceEmployee(@RequestBody Address newAddress, @PathVariable Long id) {
return repository.findById(id)
.map(address -> {
address.setCity(newAddress.getCity());
address.setPin(newAddress.getPostalCode());
return repository.save(address);
})
.orElseGet(() -> {
return repository.save(newAddress);
});
}
//additional methods omitted
}
3.4. cURL Requests
Now we can test our developed application by using cURL to send sample HTTP requests to our server.
For creating a new address, we'll enclose the data in JSON format and send it through a POST request:
curl -X POST --header 'Content-Type: application/json' \
-d '{ "name": "John Doe", "city": "Berlin", "postalCode": "10585" }' \
http://localhost:8080/addresses
Now, let's update the content of the address we created. We'll send a PUT request using the id of that address in the URL. In this example, we will update the city and the postalCode section of the address we just created — we'll suppose it was saved with id=1:
curl -X PUT --header 'Content-Type: application/json' \
-d '{ "name": "John Doe", "city": "Frankfurt", "postalCode": "60306" }' \
http://localhost:8080/addresses/1
4. Conclusion
In this tutorial, we learned about the conceptual differences between the HTTP methods PUT and POST. Additionally, we also learned how the methods can be implemented using the Spring Boot framework for developing RESTful applications.
In conclusion, we should use the POST method to create a new resource and the PUT method to update an existing resource. As always, the code for this tutorial is available over on GitHub.
The post HTTP PUT vs. POST in REST API first appeared on Baeldung.