Spring Boot: My First API
A frontend developer's journey into backend development with Java and Spring Boot. From npm install to Maven dependencies, from JavaScript objects to Java classes. How I built my first REST API to power my React projects.
The Problem: My React App Needed Data
By 2020, I was comfortable with React. I’d built dashboards, forms, and even tackled state management. But there was a problem I kept avoiding:
Where does the data actually come from?
I’d been using mock data, JSON files, and free public APIs. But at some point, I needed to build my own backend. My own API. My own… server.
The word “server” terrified me.
Why Java? Why Not Node.js?
Look, I know what you’re thinking. “You already know JavaScript. Just use Express.js!”
Fair point. But here’s the thing: my company used Java. Most enterprise companies use Java. And I wanted to understand what the “backend team” was actually doing when they handed me API documentation.
Plus, I’d heard Spring Boot made Java “less painful.” That’s a low bar, but I was willing to try.
The First Shock: Installation
In JavaScript land, you install Node.js and you’re done. Maybe 5 minutes.
Java? Oh boy.
1. Install JDK (but which version? 8? 11? 17?)
2. Set JAVA_HOME environment variable
3. Add Java to PATH
4. Verify with java -version
5. Install Maven (or Gradle, but we'll get to that)
6. Set MAVEN_HOME
7. Add Maven to PATH
8. Verify with mvn -version
9. Question your life choices
I spent an entire afternoon on this. JAVA_HOME alone took me an hour because I kept setting it to the wrong directory.
Future me note: Just use SDKMAN or Homebrew. Save yourself the pain.
Spring Initializr: The Lifesaver
Just when I was about to give up, I discovered start.spring.io.
It’s like create-react-app but for Spring Boot. You pick your options, click generate, and download a zip file with a working project structure.
My selections:
- Project: Maven
- Language: Java
- Spring Boot: 2.x.x (latest stable)
- Dependencies:
- Spring Web
- Spring Boot DevTools
Unzip. Open in IntelliJ. Wait for Maven to download half the internet.
The Project Structure That Confused Me
my-api/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/mycompany/myapi/
│ │ │ └── MyApiApplication.java
│ │ └── resources/
│ │ └── application.properties
│ └── test/
├── pom.xml
└── mvnw
In React, I had src/ and package.json. Simple.
Here? Nested folders. A pom.xml that looked like alien hieroglyphics. A resources folder? What resources?
But the key file was MyApiApplication.java:
package com.mycompany.myapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApiApplication {
public static void main(String[] args) {
SpringApplication.run(MyApiApplication.class, args);
}
}
That’s it. That’s the entire application entry point. Run this, and you have a server running on port 8080.
Wait, that’s it?
My First Controller
In Express.js, you’d write:
app.get('/api/hello', (req, res) => {
res.json({ message: 'Hello World' });
});
In Spring Boot:
package com.mycompany.myapi.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/api/hello")
public String hello() {
return "Hello World";
}
}
More lines? Yes. But also… kind of readable? The @GetMapping("/api/hello") tells you exactly what it does. No callback functions, no req, res parameters to remember.
I ran the application, opened http://localhost:8080/api/hello, and saw:
Hello World
I just built a backend. Me. A frontend developer.
Returning JSON (Not Just Strings)
Okay, returning a string is cute. But React needs JSON. Here’s where Java’s verbosity kicked in:
// First, create a class for your response
public class HelloResponse {
private String message;
private String timestamp;
// Constructor
public HelloResponse(String message, String timestamp) {
this.message = message;
this.timestamp = timestamp;
}
// Getters (required for JSON serialization)
public String getMessage() {
return message;
}
public String getTimestamp() {
return timestamp;
}
}
In JavaScript, I’d just return { message: 'Hello', timestamp: new Date() }. In Java, I need a whole class with constructors and getters.
But then, the magic:
@RestController
public class HelloController {
@GetMapping("/api/hello")
public HelloResponse hello() {
return new HelloResponse(
"Hello World",
LocalDateTime.now().toString()
);
}
}
Spring automatically converts my HelloResponse object to JSON:
{
"message": "Hello World",
"timestamp": "2020-02-15T14:30:00"
}
No JSON.stringify(). No explicit serialization. Just return the object and Spring handles it.
The pom.xml: Maven’s Package.json
Remember package.json? Where you list your dependencies and run scripts?
pom.xml is Java’s version. Except it’s XML. Because Java developers in 2004 thought XML was the future.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<groupId>com.mycompany</groupId>
<artifactId>my-api</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
npm install express becomes:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Verbose? Absolutely. But once you understand the structure, it’s just:
groupId: Who made it (like npm scope)artifactId: The package nameversion: The version (optional with Spring Boot starters)
Spring Boot Starters: Batteries Included
Here’s what sold me on Spring Boot: starters.
Instead of figuring out which 15 dependencies you need for a web application, you add ONE starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
This single line gives you:
- An embedded Tomcat server
- Spring MVC for handling requests
- Jackson for JSON serialization
- Validation support
- Error handling
It’s like a curated bundle of everything you need. No more dependency hell.
Other starters I’d eventually use:
spring-boot-starter-data-jpa- Database accessspring-boot-starter-security- Authenticationspring-boot-starter-test- Testing utilities
Connecting to My React App
The moment of truth. Could my React app actually talk to this Spring Boot API?
React code:
useEffect(() => {
fetch('http://localhost:8080/api/hello')
.then(res => res.json())
.then(data => setMessage(data.message));
}, []);
Run React on port 3000. Run Spring Boot on port 8080. Open the browser and…
CORS error.
Access to fetch at 'http://localhost:8080/api/hello' from origin
'http://localhost:3000' has been blocked by CORS policy.
Of course. Nothing is ever easy.
The fix in Spring Boot:
@RestController
@CrossOrigin(origins = "http://localhost:3000")
public class HelloController {
// ...
}
Or globally in a configuration class:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE");
}
}
Refresh React. Data flows. It works.
What I Wish I’d Known Earlier
-
Spring Boot is not the same as Spring. Spring is a massive framework. Spring Boot is the “just make it work” layer on top. Always use Spring Boot for new projects.
-
Use Spring Initializr. Don’t try to set up a project manually. Just don’t.
-
IntelliJ IDEA is worth it. The Community Edition is free and has excellent Spring support. VS Code can work, but you’ll fight it.
-
Annotations are your friends.
@RestController,@GetMapping,@PostMapping- these annotations replace hundreds of lines of configuration. -
Maven downloads A LOT. The first build takes forever because it’s downloading dependencies. Let it finish. Go get coffee.
The Journey Continues
I had a working API. A single endpoint that returned JSON. My React app could fetch from it.
But this was just “Hello World.” I needed to handle different HTTP methods, parse request bodies, validate input, and actually store data somewhere.
Next up: building a real CRUD API.
P.S. — If you’re a frontend developer terrified of backend development, I get it. I was you. But Spring Boot is genuinely approachable once you get past the initial setup. The Java ecosystem is verbose, yes, but it’s also incredibly well-documented. You’ve got this.
Saurav Sitaula
Software Architect • Nepal