RESTful Tutorial with Java 25 and Spring Boot
🚀 Building RESTful Services with Java 25 & Spring Boot — A Complete Guide
1. What is a RESTful Service?
REST (Representational State Transfer) is an architectural style for designing networked applications. A RESTful service:
-
Exposes resources via URLs
-
Uses HTTP methods (GET, POST, PUT, DELETE, PATCH)
-
Is stateless
-
Exchanges representations (mostly JSON)
-
Uses standard HTTP status codes
-
Follows resource-oriented design
Example Resources
GET /api/employees -> Get all employees
GET /api/employees/1 -> Get employee by id
POST /api/employees -> Create employee
PUT /api/employees/1 -> Update employee
DELETE /api/employees/1 -> Delete employee
2. Tech Stack
-
Java 25
-
Spring Boot 3.x+ (latest)
-
Spring Web
-
Spring Validation
-
Spring Data JPA (optional for DB)
-
Jackson (JSON serialization)
-
Maven or Gradle
-
H2 / PostgreSQL (optional)
3. Project Structure (Typical)
com.example.demo
├── DemoApplication.java
├── controller
│ └── EmployeeController.java
├── service
│ └── EmployeeService.java
├── repository
│ └── EmployeeRepository.java
├── model
│ └── Employee.java
├── dto
│ └── EmployeeRequest.java
└── exception
├── GlobalExceptionHandler.java
└── ResourceNotFoundException.java
4. Maven Dependencies (Key Ones)
-
spring-boot-starter-web
-
spring-boot-starter-validation
-
spring-boot-starter-data-jpa
-
h2 or postgresql
-
lombok (optional)
5. The Main Application
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
🔍 Annotation Explained
-
@SpringBootApplication = Combines:
-
@Configuration → Marks as config class
-
@EnableAutoConfiguration → Auto configures Spring Boot
-
@ComponentScan → Scans components in package
-
6. The Entity (Model)
@Entity
@Table(name = "employees")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
private String department;
private double salary;
// getters and setters
}
🔍 Annotations Explained
-
@Entity → Marks class as JPA entity
-
@Table → Maps to DB table
-
@Id → Primary key
-
@GeneratedValue → Auto ID generation
-
@Column → Column mapping & constraints
7. DTO for Request Validation
public class EmployeeRequest {
@NotBlank
private String name;
@NotBlank
private String department;
@Positive
private double salary;
// getters and setters
}
🔍 Validation Annotations
-
@NotBlank → Must not be null/empty
-
@Positive → Must be > 0
-
Works with @Valid in controller
8. Repository Layer
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
🔍 Annotations Explained
-
@Repository → Marks DAO layer, enables exception translation
-
JpaRepository → Gives CRUD, paging, sorting out-of-the-box
9. Service Layer
@Service
public class EmployeeService {
private final EmployeeRepository repository;
public EmployeeService(EmployeeRepository repository) {
this.repository = repository;
}
public List<Employee> getAll() {
return repository.findAll();
}
public Employee getById(Long id) {
return repository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Employee not found"));
}
public Employee create(Employee employee) {
return repository.save(employee);
}
public Employee update(Long id, Employee updated) {
Employee existing = getById(id);
existing.setName(updated.getName());
existing.setDepartment(updated.getDepartment());
existing.setSalary(updated.getSalary());
return repository.save(existing);
}
public void delete(Long id) {
repository.deleteById(id);
}
}
🔍 Annotations Explained
-
@Service → Marks business logic layer
-
Helps with separation of concerns
10. REST Controller (Core of REST API)
@RestController
@RequestMapping("/api/employees")
public class EmployeeController {
private final EmployeeService service;
public EmployeeController(EmployeeService service) {
this.service = service;
}
@GetMapping
public List<Employee> getAll() {
return service.getAll();
}
@GetMapping("/{id}")
public Employee getById(@PathVariable Long id) {
return service.getById(id);
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Employee create(@Valid @RequestBody EmployeeRequest request) {
Employee emp = new Employee();
emp.setName(request.getName());
emp.setDepartment(request.getDepartment());
emp.setSalary(request.getSalary());
return service.create(emp);
}
@PutMapping("/{id}")
public Employee update(@PathVariable Long id, @Valid @RequestBody EmployeeRequest request) {
Employee emp = new Employee();
emp.setName(request.getName());
emp.setDepartment(request.getDepartment());
emp.setSalary(request.getSalary());
return service.update(id, emp);
}
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void delete(@PathVariable Long id) {
service.delete(id);
}
}
11. Controller Annotations — Deep Dive
-
@RestController
-
= @Controller + @ResponseBody
-
Returns JSON directly
-
-
@RequestMapping("/api/employees")
-
Base URL mapping for controller
-
-
@GetMapping, @PostMapping, @PutMapping, @DeleteMapping
-
Shortcut for @RequestMapping(method = ...)
-
-
@PathVariable
-
Extracts value from URL path
-
-
@RequestBody
-
Converts JSON → Java object
-
-
@ResponseStatus
-
Sets HTTP status code
-
-
@Valid
-
Triggers bean validation
-
12. Exception Handling (Global)
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public Map<String, String> handleNotFound(ResourceNotFoundException ex) {
return Map.of("error", ex.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> handleValidation(MethodArgumentNotValidException ex) {
return Map.of("error", "Validation failed");
}
}
🔍 Annotations Explained
-
@RestControllerAdvice → Global exception handler for REST
-
@ExceptionHandler → Handles specific exception
-
@ResponseStatus → Sets HTTP status
13. HTTP Status Codes (Best Practice)
-
200 OK → Successful GET/PUT
-
201 CREATED → Resource created
-
204 NO CONTENT → Successful DELETE
-
400 BAD REQUEST → Validation error
-
404 NOT FOUND → Resource not found
-
500 INTERNAL SERVER ERROR → Server crash
14. JSON Serialization (Jackson)
Spring Boot automatically:
-
Converts Java → JSON
-
Converts JSON → Java
Using Jackson
You can control it with:
-
@JsonIgnore
-
@JsonProperty
-
@JsonInclude
15. REST Best Practices
✅ Use nouns, not verbs in URLs
✅ Use proper HTTP methods
✅ Return correct status codes
✅ Use DTOs for requests/responses
✅ Validate input
✅ Version your APIs (/api/v1/...)
✅ Use pagination for large lists
✅ Use proper error responses
16. Testing Endpoints (cURL Examples)
GET /api/employees
POST /api/employees
PUT /api/employees/1
DELETE /api/employees/1
POST body:
{
"name": "Ravi",
"department": "Engineering",
"salary": 120000
}
17 Why Java 25 + Spring Boot?
-
🔥 Virtual Threads (Project Loom) for massive concurrency
-
⚡ Faster startup & lower memory
-
🧠 Better GC & performance
-
🛠️ Mature ecosystem
-
🏢 Enterprise-ready
Comments
Post a Comment