Skip to content
Spring Boot sb getting-started 3 min read

Your First Application

The fastest way to understand Spring Boot is to build something that runs. In this guide you will create a minimal “Hello World” REST application, start the embedded server, and call a JSON endpoint with curl, all from a single annotated class.

What you need

A project generated from Spring Initializr with the Spring Web dependency, plus Java 17+ installed. If you have not set that up yet, see installation. The generated project already contains a main class and a pom.xml (or build.gradle) wired to spring-boot-starter-parent 3.5.x.

The application entry point

Every Spring Boot application starts from a class annotated with @SpringBootApplication that calls SpringApplication.run.

package com.devcraftly.hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloApplication {

    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}

@SpringBootApplication is a meta-annotation that combines three things:

  • @Configuration — marks the class as a source of bean definitions.
  • @EnableAutoConfiguration — turns on Spring Boot’s auto-configuration.
  • @ComponentScan — scans the package of this class (and sub-packages) for components.

Tip: Keep this class at the root of your package tree (for example com.devcraftly.hello). Component scanning starts here, so controllers and services in sibling packages are discovered automatically. See project structure.

Adding a REST controller

A controller exposes HTTP endpoints. Mark the class with @RestController so every method’s return value is serialized straight into the HTTP response body.

package com.devcraftly.hello;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    @GetMapping("/hello")
    public Greeting hello(@RequestParam(defaultValue = "World") String name) {
        return new Greeting("Hello, " + name + "!");
    }
}

The return type is a small immutable DTO modeled as a Java record. Spring Boot uses Jackson (auto-configured by spring-boot-starter-web) to turn it into JSON.

package com.devcraftly.hello;

public record Greeting(String message) {
}

Note: @RestController is @Controller plus @ResponseBody. Without it, Spring would try to resolve the return value as a view name instead of writing it to the response body. Records are a clean fit for read-only responses, see Java records.

Running the application

Use the Maven or Gradle wrapper that ships with the project so everyone builds with the same tool version.

# Maven
./mvnw spring-boot:run

# Gradle
./gradlew bootRun

On startup, Spring Boot launches the embedded Tomcat server (bundled by the web starter) on port 8080.

Output:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 :: Spring Boot ::                (v3.5.0)

INFO  Tomcat initialized with port 8080 (http)
INFO  Tomcat started on port 8080 (http) with context path '/'
INFO  Started HelloApplication in 1.18 seconds (process running for 1.5)

No external server, no WAR deployment, the embedded container is part of the process.

Calling the endpoint

With the app running, hit the endpoint from another terminal.

curl "http://localhost:8080/hello"

Output:

{"message":"Hello, World!"}

Pass a query parameter and Spring binds it to the name argument:

curl "http://localhost:8080/hello?name=Devcraftly"

Output:

{"message":"Hello, Devcraftly!"}

You can inspect the full HTTP exchange with curl -i to confirm the content type:

curl -i "http://localhost:8080/hello"

Output:

HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked

{"message":"Hello, World!"}

Notice the Content-Type: application/json header, set automatically because the method returned an object rather than a String.

Packaging it as a runnable JAR

To run the app outside your IDE, build the executable “fat JAR” and launch it directly.

./mvnw clean package
java -jar target/hello-0.0.1-SNAPSHOT.jar

This produces a self-contained artifact with the embedded server inside it. Packaging, layered jars, and WAR builds are covered in detail in running & packaging.

Warning: If port 8080 is already in use, startup fails with Web server failed to start. Port 8080 was already in use. Change it with server.port=8081 in your properties, or free the port.

What just happened

In under 30 lines of code you got a configured web server, JSON serialization, request binding, and a runnable artifact. That density is the whole point of Spring Boot: declare intent, let auto-configuration assemble the rest. From here you can add validation, data access, and security, each behind another well-behaved starter.

Last updated June 13, 2026
Was this helpful?