Spring Boot: My First API

SS Saurav Sitaula

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 name
  • version: 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 access
  • spring-boot-starter-security - Authentication
  • spring-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

  1. 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.

  2. Use Spring Initializr. Don’t try to set up a project manually. Just don’t.

  3. IntelliJ IDEA is worth it. The Community Edition is free and has excellent Spring support. VS Code can work, but you’ll fight it.

  4. Annotations are your friends. @RestController, @GetMapping, @PostMapping - these annotations replace hundreds of lines of configuration.

  5. 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.

SS

Saurav Sitaula

Software Architect • Nepal

Back to all posts
Saurav.dev

© 2026 Saurav Sitaula.AstroNeoBrutalism