What is a REST API?
Imagine a restaurant. You (the client) don't go into the kitchen to cook your food. Instead, you tell the waiter (API) what you want, and they bring it from the kitchen (server).
REST API works the same way. It's a set of rules for how clients and servers communicate over the internet, using standard HTTP methods.
CLIENT (Browser/Mobile App)
│
│ HTTP Request
│ GET /api/users/123
▼
┌─────────────────────────────┐
│ REST API (Waiter) │
│ Understands HTTP methods │
│ Routes to right handler │
└─────────────────────────────┘
│
│ Database Query
▼
┌─────────────────────────────┐
│ SERVER (Kitchen) │
│ Processes the request │
│ Returns JSON response │
└─────────────────────────────┘
HTTP Methods (CRUD Operations)
HTTP Method Purpose Example
───────────────────────────────────────────────────
GET Read data GET /api/users (get all users)
GET /api/users/123 (get user 123)
POST Create new POST /api/users (create new user)
Body: {"name": "John"}
PUT Update entire PUT /api/users/123 (replace user 123)
resource Body: {"name": "Jane", "email": "jane@mail.com"}
PATCH Partial update PATCH /api/users/123 (update email only)
Body: {"email": "new@mail.com"}
DELETE Remove DELETE /api/users/123 (delete user 123)
HTTP Status Codes
Status codes tell the client what happened with their request.
CODE MEANING WHEN TO USE
─────────────────────────────────────────────────────
2xx - SUCCESS
200 OK Request succeeded
201 Created New resource created (POST)
204 No Content Success, nothing to return (DELETE)
4xx - CLIENT ERRORS
400 Bad Request Invalid data sent by client
401 Unauthorized Not logged in / invalid token
403 Forbidden Logged in but not allowed
404 Not Found Resource doesn't exist
409 Conflict Duplicate entry, constraint violation
5xx - SERVER ERRORS
500 Internal Server Error Something broke on the server
503 Service Unavailable Server is overloaded or down
Building REST APIs with Spring Boot
1. Create a Controller
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// GET all users
@GetMapping
public List<User> getAllUsers() {
return userService.findAll();
}
// GET single user by ID
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.findById(id);
if (user == null) {
return ResponseEntity.notFound().build(); // 404
}
return ResponseEntity.ok(user); // 200
}
// POST - Create new user
@PostMapping
public ResponseEntity<User> createUser(@RequestBody @Valid User user) {
User created = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(created); // 201
}
// PUT - Update entire user
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(
@PathVariable Long id,
@RequestBody @Valid User user) {
User updated = userService.update(id, user);
return ResponseEntity.ok(updated); // 200
}
// DELETE - Remove user
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build(); // 204
}
}
Request Validation
Always validate incoming data to prevent bad data entering your system.
public class User {
@NotBlank(message = "Name is required")
@Size(min = 2, max = 50, message = "Name must be 2-50 characters")
private String name;
@NotBlank(message = "Email is required")
@Email(message = "Please provide a valid email")
private String email;
@Min(value = 18, message = "Must be at least 18 years old")
private int age;
// getters and setters
}
// In controller, use @Valid annotation
@PostMapping
public ResponseEntity<User> createUser(@RequestBody @Valid User user) {
// If validation fails, Spring returns 400 Bad Request automatically
}
Exception Handling
Handle errors gracefully and return meaningful error messages.
// Global exception handler
@RestControllerAdvice
public class GlobalExceptionHandler {
// Handle resource not found
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
ErrorResponse error = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
ex.getMessage(),
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
// Handle validation errors
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(
MethodArgumentNotValidException ex) {
String message = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(e -> e.getField() + ": " + e.getDefaultMessage())
.collect(Collectors.joining(", "));
ErrorResponse error = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
message,
LocalDateTime.now()
);
return ResponseEntity.badRequest().body(error);
}
}
// Error response DTO
public class ErrorResponse {
private int status;
private String message;
private LocalDateTime timestamp;
// constructor, getters
}
REST API Best Practices
- Use nouns, not verbs: /api/users not /api/getUsers
- Use plural names: /api/users not /api/user
- Use proper HTTP methods: GET for reading, POST for creating
- Return appropriate status codes: 201 for created, 404 for not found
- Version your API: /api/v1/users for future compatibility
- Use pagination: Don't return 10,000 records at once
- Validate all input: Never trust client data
- Use DTOs: Don't expose your entity structure directly
Pagination Example
@GetMapping
public Page<User> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "id") String sortBy) {
Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
return userService.findAll(pageable);
}
// Response includes:
// {
// "content": [...users...],
// "totalElements": 100,
// "totalPages": 10,
// "size": 10,
// "number": 0 (current page)
// }
Master REST APIs with Expert Mentorship
Our Full Stack Java program covers REST API design and implementation with Spring Boot. Build production-ready APIs with guidance from industry experts.
Explore Java Program