Understand how Spring Boot Embedded Servers allow web applications to run as standalone applications without requiring a separately installed and configured external web server. Spring Boot applications can package the server inside the application and start it automatically when the application runs.
For a typical Spring Boot web application, the web starter brings the required web infrastructure, including an embedded server. By default, Spring Boot uses Tomcat for servlet-based web applications unless the server dependency is replaced or customized. This allows an application to be started directly as a Java application or executable JAR.
What is an Embedded Server?
An embedded server is a web server (Tomcat, Jetty, Undertow) packaged inside the application as a library. When main() runs, Spring Boot starts the server and deploys the application on it. There is no external server and no WAR deployment.
Why is it used?
It removes server installation and configuration, and the app runs anywhere Java is available with java -jar.
Features
- No external server installation
- Runs as a standalone executable JAR
- Port, context path, and threads configured through properties
- Auto-configured by Spring Boot
- Same runtime on developer machine, test server, and Docker
Types
- Tomcat: Default in spring-boot-starter-web
- Jetty: Lightweight alternative
- Undertow: High-performance alternative
- Netty: Used by reactive (WebFlux) apps
Hands-on Experiment: Run a REST application using embedded Tomcat and change its server port
The following steps are involved in developing this hands-on experiment.
Step 1: Generate the Project
Step 2: Project Structure
Step 3: pom.xml
Step 4: application.properties
Step 5: Create Entity Class
Step 6: Create Repository Interface
Step 7: Create Service Class
Step 8: Create Controller Class
Step 9: Main Application Class
Step 10: Run the Main Application Class
Step 1: Configure the Project on Spring Initializr
Go to start.spring.io and set:
- Project: Maven
- Language: Java
- Spring Boot version: 3.2.x
- Group: net.codejava
- Artifact: embedded-server
- Name: embedded-server
- Package name: net.codejava.embedded-server
- Packaging: Jar
- Java: 17
- Dependencies: Spring Web, Spring Data JPA, MySQL Driver
Click Generate to download the ZIP, then extract and import it into your IDE as a Maven project.
Step 2: Generated Project Structure

Step 3: Explore pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>4.1.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>net.codejava</groupId> <artifactId>embedded-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name/> <description/> <url/> <licenses> <license/> </licenses> <developers> <developer/> </developers> <scm> <connection/> <developerConnection/> <tag/> <url/> </scm> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webmvc</artifactId> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webmvc-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Step 4: application.properties
spring.application.name=embedded-server
# DataSource Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/sys
spring.datasource.username=root
spring.datasource.password=password
# JPA / Hibernate Configuration
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
# Server Configuration
server.port=8081Code language: PHP (php)
Step 5: Create Entity Class
package net.codejava.embedded_server.entity;
import jakarta.persistence.*;
import java.time.LocalDate;
@Entity
@Table(name = "employees")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
private String department;
private Integer age;
private Double salary;
private LocalDate joiningDate;
public Employee() {}
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getDepartment() { return department; }
public void setDepartment(String department) { this.department = department; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public Double getSalary() { return salary; }
public void setSalary(Double salary) { this.salary = salary; }
public LocalDate getJoiningDate() { return joiningDate; }
public void setJoiningDate(LocalDate joiningDate) { this.joiningDate = joiningDate; }
}
Step 6: Create Repository Interface
package net.codejava.embedded_server.repository;
import net.codejava.embedded_server.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {}
Step 7: Create Service class
package net.codejava.embedded_server.service;
import net.codejava.embedded_server.entity.Employee;
import net.codejava.embedded_server.repository.EmployeeRepository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class EmployeeService {
private final EmployeeRepository repository;
public EmployeeService(EmployeeRepository repository) { this.repository = repository; }
public Employee save(Employee e) { return repository.save(e); }
public List<Employee> findAll() { return repository.findAll(); }
public Employee findById(Long id) { return repository.findById(id).orElse(null); }
public void delete(Long id) { repository.deleteById(id); }
}
Step 8: Create Controller class
package net.codejava.embedded_server.controller;
import net.codejava.embedded_server.entity.Employee;
import net.codejava.embedded_server.service.EmployeeService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/employees")
public class EmployeeController {
private final EmployeeService service;
public EmployeeController(EmployeeService service) { this.service = service; }
@PostMapping
public Employee create(@RequestBody Employee e) { return service.save(e); }
@GetMapping
public List<Employee> getAll() { return service.findAll(); }
@GetMapping("/{id}")
public ResponseEntity<Employee> getById(@PathVariable Long id) {
Employee e = service.findById(id);
return e != null ? ResponseEntity.ok(e) : ResponseEntity.notFound().build();
}
@PutMapping("/{id}")
public Employee update(@PathVariable Long id, @RequestBody Employee e) {
e.setId(id);
return service.save(e);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) { service.delete(id); }
}
Step 9: Main Application
package net.codejava.embedded_server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class EmbeddedServerApplication {
public static void main(String[] args) {
SpringApplication.run(EmbeddedServerApplication.class, args);
}
}
Step 10: Run the EmbeddedServerApplication

Change port number to 9090

The REST API should be available on port 9090.
This demonstrates that the embedded server is controlled through Spring Boot configuration
