Spring Boot removed most of the tedious XML configuration that made classic Spring projects slow to start. Today it’s the de facto standard for building production Java microservices, and getting a working REST API running takes closer to 15 minutes than the days it used to.
What Spring Boot Actually Does
Spring Boot’s real innovation is “convention over configuration” — instead of manually wiring every component, it ships with sensible defaults based on what’s on your classpath, so you’re writing business logic almost immediately instead of configuration files.
What You Need Before Starting
A Java Development Kit (JDK 17 or 21 — both current LTS versions), an IDE (IntelliJ IDEA, Eclipse, or VS Code all work fine), and Maven for dependency management, which usually comes bundled with your IDE already.
Step 1: Generate the Project
The simplest starting point is Spring Initializr at start.spring.io. Select Maven Project, Java as the language, the latest stable Spring Boot 3.x version, and add the “Spring Web” dependency specifically — this pulls in everything needed for a REST API, including an embedded server. Click Generate, unzip the download, and open it in your IDE.
Step 2: Understand What You’re Looking At
The generated project follows a standard Maven layout: src/main/java holds your actual code, src/main/resources holds application.properties for configuration, and pom.xml is the Maven file listing your dependencies, anchored by the Spring Boot Starter Parent.
Your main application class will have an @SpringBootApplication annotation on it — worth understanding what this actually bundles together, since tutorials often gloss over it: it combines three separate annotations into one. @Configuration marks the class as a source of bean definitions, @EnableAutoConfiguration tells Spring Boot to automatically configure your app based on the dependencies it finds (this is the “convention over configuration” behavior in practice), and @ComponentScan tells Spring to look for other components in the same package and its subpackages. That single annotation is doing real, specific work, not just marking “this is the main class.”
Step 3: Create a Simple Data Model
Create Book.java:
public record Book(long id, String title, String author) {}
Java records, available since Java 14 and commonly used in modern Spring Boot projects, generate the constructor, getters, equals(), hashCode(), and toString() automatically — a concise way to model simple data without writing that boilerplate by hand.
Step 4: Build the Controller
Create BookController.java:
@RestController
public class BookController {
private final List<Book> books = new ArrayList<>(List.of(
new Book(1, "Spring Boot in Action", "Craig Walls"),
new Book(2, "Clean Code", "Robert C. Martin")
));
@GetMapping("/books")
public List<Book> getBooks() {
return books;
}
@PostMapping("/books")
public Book addBook(@RequestBody Book newBook) {
books.add(newBook);
return newBook;
}
}
@RestController tells Spring this class handles web requests and should serialize return values directly to JSON. @GetMapping and @PostMapping map HTTP GET and POST requests to their respective methods. @RequestBody tells Spring to deserialize the incoming JSON request body into a Book object automatically — this is what lets a client send data to your API, not just read from it, which the GET-only version of this tutorial never demonstrated.
Step 5: Run and Test It
Run the main method in your application class. Spring Boot starts an embedded Tomcat server on port 8080 by default — no separate server installation needed.
Test the GET endpoint by visiting http://localhost:8080/books in a browser. To test the POST endpoint, you’ll need a tool like Postman or curl, since browsers can’t easily send POST requests directly:
curl -X POST http://localhost:8080/books \
-H "Content-Type: application/json" \
-d '{"id":3,"title":"Effective Java","author":"Joshua Bloch"}'
You should get the new book back as a JSON response, and a subsequent GET request to /books should now show three books instead of two.
Common Errors and How to Fix Them
“Port 8080 already in use” means another process (often a previous run of your own app that didn’t shut down cleanly) is already bound to that port. Either stop that process or add server.port=8081 to application.properties to run on a different port.
“Could not find or load main class” usually means Maven hasn’t compiled your latest changes — try rebuilding the project (mvn clean install or your IDE’s rebuild option) before running again.
Dependency or version errors on startup often trace back to a Java version mismatch — check that your project’s configured Java version (in pom.xml) matches the JDK your IDE is actually using to run it.
Where to Go From Here
This tutorial covers an in-memory list, which resets every time the app restarts — genuinely fine for learning, not for anything real. The natural next steps: adding Spring Data JPA to persist books in an actual database instead of a list that disappears on restart, adding validation (@Valid and constraint annotations) so the API rejects malformed requests instead of accepting anything, and adding proper error handling so a request for a book that doesn’t exist returns a sensible 404 instead of an unhandled exception.
None of that complexity was necessary to get a working API running today, which is really the point of starting here: Spring Boot’s defaults get you to a functioning REST API fast, and each of those next steps can be added incrementally without needing to restructure what you’ve already built.
A Note on What “Production-Ready” Actually Requires
It’s worth being direct about the gap between this tutorial and something you’d actually deploy: a real production API needs the persistence and validation mentioned above, but also proper logging, health check endpoints (Spring Boot Actuator adds these with minimal setup), environment-specific configuration (different database credentials for development versus production), and some form of authentication if the API isn’t meant to be fully public. None of this needs to be built on day one, but treating a tutorial-stage API as deployment-ready without these pieces is a common and avoidable mistake for developers newer to backend work specifically.