Introduction
REST (Representational State Transfer) is an architectural style used for designing networked applications. It relies on a stateless, client-server communication model and uses HTTP as its protocol. REST is widely adopted in web services, and Spring Boot makes it incredibly easy to build RESTful APIs.
In this article, we’ll explore how REST works, what each HTTP method means, and how to implement them using Spring Boot.
Core Concepts of REST
- Stateless: No session data is stored on the server between requests.
- Client-Server: The client and server are separate entities.
- Cacheable: Responses must define themselves as cacheable or not.
- Uniform Interface: Consistent way to interact with the service (typically via URIs and standard HTTP methods).
- Resource-Based: Everything is considered a resource, identified by a URI (e.g.,
/users/1
).
Common HTTP Methods in REST
Method | Description |
---|---|
GET | Fetches data from the server |
POST | Creates a new resource |
PUT | Updates or replaces a resource |
PATCH | Partially updates a resource |
DELETE | Deletes a resource |
What is Idempotency?
Idempotency means that making the same request multiple times has the same effect as making it once.
In RESTful design, this is important for safety and predictability—especially in situations like network retries. Let’s see how it applies to HTTP methods:
Method | Idempotent | Explanation |
---|---|---|
GET | Yes | Repeating a GET request does not change data. It only reads. |
PUT | Yes | Replacing a resource with the same data multiple times results in no change. |
DELETE | Yes | Deleting a resource multiple times results in the same state—it’s gone. |
POST | No | Repeating POST creates new resources each time. |
PATCH | No | Repeating may incrementally change data depending on the patch logic. |
Why Idempotency Matters
If a client times out after sending a request, it might retry. If the request isn’t idempotent (like a POST
), it could unintentionally create duplicate resources. That’s why methods like PUT
and DELETE
are designed to be idempotent.
Building a REST API with Spring Boot
Let’s build a simple User
API that supports all the HTTP methods.
Step 1: Project Setup
Make sure you have the following dependencies in your pom.xml
:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
Step 2: Create the User Model
public class User {
private Long id;
private String name;
private String email;
// Constructors, getters, setters
}
Step 3: Create the Controller
@RestController
@RequestMapping("/users")
public class UserController {
private Map<Long, User> userRepo = new HashMap<>();
private AtomicLong idGenerator = new AtomicLong();
// GET - Fetch all users
@GetMapping
public List<User> getAllUsers() {
return new ArrayList<>(userRepo.values());
}
// GET - Fetch user by ID
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userRepo.get(id);
return user != null ? ResponseEntity.ok(user) : ResponseEntity.notFound().build();
}
// POST - Create new user
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
long id = idGenerator.incrementAndGet();
user.setId(id);
userRepo.put(id, user);
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}
// PUT - Replace user
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User updatedUser) {
if (!userRepo.containsKey(id)) {
return ResponseEntity.notFound().build();
}
updatedUser.setId(id);
userRepo.put(id, updatedUser);
return ResponseEntity.ok(updatedUser);
}
// PATCH - Partially update user
@PatchMapping("/{id}")
public ResponseEntity<User> patchUser(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
User user = userRepo.get(id);
if (user == null) {
return ResponseEntity.notFound().build();
}
if (updates.containsKey("name")) {
user.setName((String) updates.get("name"));
}
if (updates.containsKey("email")) {
user.setEmail((String) updates.get("email"));
}
return ResponseEntity.ok(user);
}
// DELETE - Remove user
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
if (userRepo.remove(id) == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.noContent().build();
}
}
Testing the API
You can test the REST API using tools like Postman or cURL:
GET /users
– List all usersPOST /users
– Create a user (with body)PUT /users/1
– Replace the user with id 1PATCH /users/1
– Partially update the userDELETE /users/1
– Delete the user
Conclusion
The REST protocol provides a clean and scalable way to build APIs, and Spring Boot makes it incredibly easy to implement them. By understanding how HTTP methods map to CRUD operations, you can design intuitive and powerful APIs.