A Spring Boot 4 demo showcasing modern REST API development with external API integration, validation, and exception handling.
This demo demonstrates:
- RestClient Integration: Using Spring Boot 4's HTTP interface to consume external APIs
- Input Validation: Bean Validation with
@Valid,@NotBlank,@Email,@Size - Global Exception Handling:
@RestControllerAdvicewithProblemDetailresponses - JPA & MySQL: Database integration with Spring Data JPA
- Docker: Containerized MySQL database setup
- Java 25 or higher
- Docker & Docker Compose
- IntelliJ IDEA (or any IDE)
- OpenAI API Key (optional - for GPT integration features)
The application uses Docker Compose to run a MySQL 8.4 database:
docker compose up -dThe database will be available at localhost:3307 with credentials:
- Database:
mydb - Username:
ek - Password:
ek
If you want to use the DatamatikerGPT feature, add your OpenAI API key to application.properties:
openai_api_key=your-api-key-hereAlternatively, use an environment variable:
export OPENAI_API_KEY=your-api-key-hereNote: The application will start without an API key, but the
/api/gptendpoint will not work.
Using IntelliJ IDEA:
- Open the project in IntelliJ
- Run the
Applicationclass
The application will start at http://localhost:8080
GET /api/usersGET /api/users/{id}POST /api/users
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com"
}Validation Rules:
name: Required, 2-150 charactersemail: Required, valid email format
GET /api/users/{id}/todosFetches user from database and their todos from external API.
GET /api/todosGET /api/todos/{id}POST /api/todos
Content-Type: application/json
{
"userId": 1,
"title": "Learn Spring Boot",
"completed": false
}DELETE /api/todos/{id}GET /api/gpt?prompt=Explain what a RestClient isThe Spring Boot 4 approach using declarative HTTP clients:
@HttpExchange("/todos")
public interface TodosClient {
@GetExchange
List<TodoResponse> getTodos();
@GetExchange("/{id}")
TodoResponse getTodoById(@PathVariable Long id);
}Configuration in HttpConfig.java using RestClientHttpServiceGroupConfigurer.
Using Bean Validation annotations on Records:
public record CreateUserRequest(
@NotBlank(message = "Name must not be blank")
@Size(min = 2, max = 150)
String name,
@Email
@NotBlank
String email
) {}Controllers use @Valid to trigger validation:
@PostMapping
public ResponseEntity<UserResponse> createUser(@Valid @RequestBody CreateUserRequest request) {
// ...
}@RestControllerAdvice with ProblemDetail (RFC 7807):
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NotFoundException.class)
public ResponseEntity<ProblemDetail> handleNotFoundException(NotFoundException ex) {
// Returns standardized error response
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ProblemDetail> handleValidationException(MethodArgumentNotValidException ex) {
// Returns validation errors
}
}- Entity:
Userclass with JPA annotations - Repository:
UserRepository extends JpaRepository - Service:
UserServicewith business logic - Hibernate: Auto-creates tables with
spring.jpa.hibernate.ddl-auto=update
# Create a user
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Alice","email":"alice@example.com"}'
# Get all users
curl http://localhost:8080/api/users
# Get todos
curl http://localhost:8080/api/todos
# Ask DatamatikerGPT (if API key configured)
curl "http://localhost:8080/api/gpt?prompt=What%20is%20Spring%20Boot"Create a file requests.http in your project:
### Create User
POST http://localhost:8080/api/users
Content-Type: application/json
{
"name": "Test User",
"email": "test@example.com"
}
### Get All Users
GET http://localhost:8080/api/users
### Get User with Todos
GET http://localhost:8080/api/users/1/todosTry these exercises to deepen your understanding:
- Add Validation: Add more validation rules to
CreateUserRequest(e.g., min age, phone number format) - Custom Exceptions: Create a
DuplicateEmailExceptionand handle it inGlobalExceptionHandler - New Endpoint: Add a
PUT /api/users/{id}endpoint to update users - Query Parameters: Add filtering to
GET /api/users?name=John - Logging: Add logging to track API calls in
TodosClient - Testing: Write unit tests for
UserServiceand integration tests forUserController
- Ensure Docker is running:
docker ps - Check if MySQL container is up:
docker compose ps - Verify port 3307 is not in use:
lsof -i :3307
- Check if API key is set in
application.properties - Verify API key is valid at platform.openai.com
- Check logs for connection errors
- Ensure
@Validannotation is present in controller - Check that validation dependencies are in
pom.xml - Look for validation error messages in the response body