Building RESTful APIs with Spring Boot
Spring Boot has become the go-to framework for building production-ready Java applications with minimal configuration. In this post, we'll explore how to create a clean, maintainable REST API using Spring Boot's powerful features.
Why Spring Boot?
Spring Boot eliminates much of the boilerplate configuration that traditional Spring applications require. It offers:
- Auto-configuration that sets up sensible defaults
- Embedded servers like Tomcat, so no external deployment is needed
- Starter dependencies that simplify your build configuration
- Production-ready features such as metrics and health checks
Setting Up the Project
The easiest way to bootstrap a project is through Spring Initializr. Add the spring-boot-starter-web dependency to your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Creating a Simple Controller
Let's build a controller that manages a collection of books. Spring's annotations make this concise and readable.
@RestController
@RequestMapping("/api/books")
public class BookController {
private final BookService bookService;
public BookController(BookService bookService) {
this.bookService = bookService;
}
@GetMapping
public List<Book> getAllBooks() {
return bookService.findAll();
}
@GetMapping("/{id}")
public ResponseEntity<Book> getBook(@PathVariable Long id) {
return bookService.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Book createBook(@RequestBody @Valid Book book) {
return bookService.save(book);
}
}
Dependency Injection
Notice that we inject BookService through the constructor. Constructor injection is preferred over field injection because it makes dependencies explicit and supports immutability.
@Service
public class BookService {
private final BookRepository repository;
public BookService(BookRepository repository) {
this.repository = repository;
}
public List<Book> findAll() {
return repository.findAll();
}
public Optional<Book> findById(Long id) {
return repository.findById(id);
}
public Book save(Book book) {
return repository.save(book);
}
}
Handling Errors Gracefully
A robust API needs consistent error handling. Use @RestControllerAdvice to centralize exception management.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BookNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(BookNotFoundException ex) {
ErrorResponse error = new ErrorResponse("BOOK_NOT_FOUND", ex.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
}
Conclusion
Spring Boot dramatically reduces the effort required to build reliable REST APIs. By leveraging auto-configuration, dependency injection, and centralized error handling, you can focus on business logic rather than infrastructure. Start small, iterate, and let the framework handle the heavy lifting.
Top comments (0)