🌱 Spring Into Action: From Zero to Hero

Welcome to the least boring Spring Boot tutorial you’ll ever read! We’ll build a real Todo application from scratch, evolving it from a simple API to a production-ready system.

πŸ€” What’s This All About?

Are you tired of tutorials that make Spring Boot sound like rocket science? Well, grab your coffee β˜• (or energy drink, we don’t judge), because we’re about to turn you from a Spring newbie into a Spring ninja β€” by actually building things.

πŸ’‘ Why This Book?

There are tons of Spring Boot tutorials out there β€” but most are either too shallow, too theoretical, or just plain boring.

This book is different:

Whether you’re a student, job-seeker, or dev who wants to finally get Spring Boot β€” this guide is made for you.

βœ… Prerequisites

πŸ“š Learning Path

1. 🏁 Spring Boot Quickstart πŸ”₯πŸ”₯πŸ”₯ (30 mins)

Your first steps into the Spring ecosystem, creating the foundation of our Todo application.

What You’ll Build

Key Concepts

Hands-on Tasks

@RestController
public class TodoController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello, Todo!";
    }
}

πŸ’‘ Outcome: A running Spring Boot application with your first endpoint.


2. 🌐 REST API Development πŸ”₯πŸ”₯πŸ”₯ (2 hrs)

Build a working REST API with full CRUD operations β€” all inside the controller β€” using in-memory data and simple business logic.

What You’ll Build

Key Concepts

πŸ’‘ Outcome: A working, self-contained REST API. In the next chapter, we’ll break it into services and repositories.


3. 🧠 Layered Architecture πŸ”₯πŸ”₯ (1 hr)

Refactor your Todo API into a clean, professional 3-layer architecture.

What You’ll Build

Project Structure

src/main/java/com/example/demo/
β”œβ”€β”€ controller/
β”‚   └── TodoController.java
β”œβ”€β”€ service/
β”‚   β”œβ”€β”€ TodoService.java
β”‚   └── TodoServiceImpl.java
└── repository/
    β”œβ”€β”€ TodoRepository.java
    └── TodoRepositoryImpl.java

Key Concepts

πŸ’‘ Outcome: A clean and scalable backend ready for database integration and advanced features.


🎯 Progress Tracking

Chapter Status Estimated Time Priority
1. Quickstart Foundation 30 mins πŸ”₯πŸ”₯πŸ”₯
2. REST API Core Feature 2 hrs πŸ”₯πŸ”₯πŸ”₯
3. Architecture Structure 1 hr πŸ”₯πŸ”₯

4. πŸ“Š Data Validation & Error Handling πŸ”₯πŸ”₯ (2 hrs)

Improve your Todo API by adding input validation and clear error handling.

What You’ll Build

Key Concepts

Example Validation (in a DTO or entity)

public class TodoRequest {
    @NotBlank(message = "Title is required")
    @Size(max = 100, message = "Title must be at most 100 characters")
    private String title;

    @Size(max = 500, message = "Description cannot exceed 500 characters")
    private String description;

    @NotNull(message = "Completion status is required")
    private Boolean completed;

    // getters and setters
}

Example Global Error Handler

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Object> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error -> {
            errors.put(error.getField(), error.getDefaultMessage());
        });
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(TodoNotFoundException.class)
    public ResponseEntity<Object> handleTodoNotFound(TodoNotFoundException ex) {
        Map<String, String> error = Map.of("error", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    // add other handlers as needed
}

πŸ’‘ Outcome: Your API will reject invalid input with clear messages and handle errors consistently for a better developer experience.


5. πŸ›’οΈ Persistent Storage with Spring Data JPA πŸ”₯πŸ”₯πŸ”₯ (3 hrs)

In this chapter, you’ll replace the in-memory store with a real database using Spring Data JPA β€” a powerful way to map Java objects to database tables.

🧱 What You’ll Build


🧠 Key Concepts Explained


βœ… Sample JPA Entity

@Entity
@Table(name = "todos")
public class Todo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull(message = "Title is required")
    @Size(min = 1, max = 100)
    @Column(nullable = false)
    private String title;

    @Size(max = 500)
    private String description;

    @Column(nullable = false)
    private boolean completed;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @Column(name = "created_at", nullable = false, updatable = false)
    @CreationTimestamp
    private LocalDateTime createdAt;

    // Getters and setters
}

πŸ“¦ Repository Interface

@Repository
public interface TodoRepository extends JpaRepository<Todo, Long> {
    List<Todo> findByUserIdOrderByCreatedAtDesc(Long userId);

    @Query("SELECT t FROM Todo t WHERE t.user.id = :userId AND t.completed = :completed")
    List<Todo> findByUserIdAndCompleted(@Param("userId") Long userId, @Param("completed") boolean completed);
}

βš™οΈ Notes


πŸ§ͺ Testing Tip

Once connected to a real DB (e.g. H2, PostgreSQL, MySQL), you can test with:

curl -X POST http://localhost:8080/api/todos \
  -H "Content-Type: application/json" \
  -d '{"title": "Finish JPA chapter", "completed": false}'

πŸ’‘ Outcome

You now have a production-ready Todo API with persistent storage, query filtering, and relational mapping β€” using clean, idiomatic Spring Data JPA.


6. πŸ§ͺ Testing Fundamentals πŸ”₯πŸ”₯ (2 hrs)

Ensure the reliability of your Todo application through comprehensive testing.

What You’ll Build

Key Concepts

Example: Unit Test for Service Layer

@ExtendWith(MockitoExtension.class)
class TodoServiceTest {
    @Mock
    private TodoRepository todoRepository;

    @InjectMocks
    private TodoServiceImpl todoService;

    @Test
    void createTodo_ShouldReturnSavedTodo() {
        Todo todo = new Todo("Test Todo", "Description", false);
        when(todoRepository.save(any(Todo.class))).thenReturn(todo);

        Todo result = todoService.create(todo);

        assertNotNull(result);
        assertEquals("Test Todo", result.getTitle());
        verify(todoRepository).save(any(Todo.class));
    }
}

Example: Controller Test with MockMvc

@WebMvcTest(TodoController.class)
class TodoControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private TodoService todoService;

    @Test
    void getAllTodos_ShouldReturnTodoList() throws Exception {
        List<Todo> todos = Arrays.asList(new Todo("Todo 1"), new Todo("Todo 2"));
        when(todoService.findAll()).thenReturn(todos);

        mockMvc.perform(get("/api/todos"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$", hasSize(2)))
               .andExpect(jsonPath("$[0].title", is("Todo 1")));
    }
}

Outcome

A well-tested Todo application with high confidence in your code’s correctness, reliable database integration, and clean API behavior.

Next: Deployment and Dockerization ➑️


7. πŸ” Security Essentials πŸ”₯πŸ”₯πŸ”₯ (2.5 hrs)

Protect your Todo application with authentication and authorization.

What You’ll Build

Key Concepts

Security Configuration

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/api/auth/**").permitAll()
                .anyRequest().authenticated()
            .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    // Other configurations (password encoder, authentication manager, etc.)
}

Secured Controller Method

@RestController
@RequestMapping("/api/todos")
public class TodoController {
    @GetMapping
    @PreAuthorize("hasRole('USER')")
    public List<Todo> getUserTodos(Authentication authentication) {
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        return todoService.getTodosByUsername(userDetails.getUsername());
    }
}

πŸ’‘ Outcome: A secure Todo application with user authentication and protected resources.


8. 🌐 Spring Data REST & Documentation πŸ”₯πŸ”₯ (2 hrs)

Simplify API development and improve documentation for your Todo application.

What You’ll Build

Key Concepts

Spring Data REST Repository

@RepositoryRestResource(collectionResourceRel = "todos", path = "todos")
public interface TodoRepository extends JpaRepository<Todo, Long> {
    List<Todo> findByUserUsername(@Param("username") String username);
    
    @Query("SELECT t FROM Todo t WHERE t.user.username = :username AND t.completed = :completed")
    List<Todo> findByUsernameAndCompleted(@Param("username") String username, @Param("completed") boolean completed);
}

OpenAPI Configuration

@Configuration
@OpenAPIDefinition(info = @Info(title = "Todo API", version = "v1"))
public class OpenApiConfig {
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                .components(new Components()
                        .addSecuritySchemes("bearerAuth",
                                new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")))
                .info(new Info().title("Todo API").version("v1"))
                .addSecurityItem(new SecurityRequirement().addList("bearerAuth"));
    }
}

πŸ’‘ Outcome: A self-documenting Todo API with simplified CRUD operations and interactive documentation.


9. ⚑ Caching & Performance πŸ”₯πŸ”₯ (2 hrs)

Optimize your Todo application for speed and efficiency.

What You’ll Build

Key Concepts

Caching Configuration

@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(10))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        
        return RedisCacheManager.builder(redisConnectionFactory)
                .cacheDefaults(cacheConfig)
                .build();
    }
}

Caching in Service Layer

@Service
public class TodoServiceImpl implements TodoService {
    @Cacheable(value = "todos", key = "#userId")
    public List<Todo> getUserTodos(Long userId) {
        return todoRepository.findByUserId(userId);
    }

    @CachePut(value = "todos", key = "#result.id")
    public Todo createTodo(Todo todo) {
        return todoRepository.save(todo);
    }

    @CacheEvict(value = "todos", key = "#id")
    public void deleteTodo(Long id) {
        todoRepository.deleteById(id);
    }
}

πŸ’‘ Outcome: A high-performance Todo application with optimized data access and reduced database load.


10. πŸš€ Configuration & Deployment πŸ”₯πŸ”₯ (2.5 hrs)

Prepare your Todo application for different environments and deployment scenarios.

What You’ll Build

Key Concepts

Application Properties for Multiple Environments

# application.yml
spring:
  profiles:
    active: ${SPRING_PROFILES_ACTIVE:dev}

---
spring:
  config:
    activate:
      on-profile: dev
  datasource:
    url: jdbc:h2:mem:tododb
    driver-class-name: org.h2.Driver
  jpa:
    database-platform: org.hibernate.dialect.H2Dialect

---
spring:
  config:
    activate:
      on-profile: prod
  datasource:
    url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
  jpa:
    database-platform: org.hibernate.dialect.PostgreSQLDialect

Dockerfile

FROM openjdk:11-jre-slim
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

Docker Compose

version: '3'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - DB_HOST=db
    depends_on:
      - db
  db:
    image: postgres:13
    environment:
      - POSTGRES_DB=tododb
      - POSTGRES_PASSWORD=secret

πŸ’‘ Outcome: A Todo application ready for deployment across various environments, from local development to production cloud services.


11. πŸ“Š Monitoring & Observability 🌿 (2 hrs)

Gain insights into your Todo application’s performance and health.

What You’ll Build

Key Concepts

Actuator Configuration

management:
  endpoints:
    web:
      exposure:
        include: health,metrics,prometheus
  endpoint:
    health:
      show-details: always
  metrics:
    export:
      prometheus:
        enabled: true

Custom Metric

@Service
public class TodoServiceImpl implements TodoService {
    private final MeterRegistry meterRegistry;

    public TodoServiceImpl(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    public Todo createTodo(Todo todo) {
        Todo savedTodo = todoRepository.save(todo);
        meterRegistry.counter("todos.created").increment();
        return savedTodo;
    }
}

πŸ’‘ Outcome: A Todo application with comprehensive monitoring and observability features.


12. πŸš€ Advanced Features 🌿 (3 hrs)

Enhance your Todo application with advanced Spring capabilities.

What You’ll Build

Key Concepts

Scheduled Reminder

@Service
public class ReminderService {
    @Scheduled(cron = "0 0 8 * * ?")  // Every day at 8 AM
    public void sendDailyReminders() {
        List<Todo> dueTodos = todoRepository.findDueTodos();
        // Logic to send reminders
    }
}

WebSocket Configuration

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS();
    }
}

πŸ’‘ Outcome: A feature-rich Todo application leveraging advanced Spring capabilities.


13. πŸ“ˆ API Evolution & Versioning 🌿 (2 hrs)

Prepare your Todo API for long-term maintenance and evolution.

What You’ll Build

Key Concepts

Versioned Controller

@RestController
@RequestMapping("/api/v1/todos")
public class TodoControllerV1 {
    // V1 endpoints
}

@RestController
@RequestMapping("/api/v2/todos")
public class TodoControllerV2 {
    // V2 endpoints with new features
}

Content Negotiation

@GetMapping(produces = {"application/vnd.myapp.todo.v1+json", "application/vnd.myapp.todo.v2+json"})
public ResponseEntity<Todo> getTodo(@RequestHeader("Accept") String acceptHeader) {
    if (acceptHeader.contains("v2")) {
        return ResponseEntity.ok(new TodoV2());
    }
    return ResponseEntity.ok(new TodoV1());
}

πŸ’‘ Outcome: A Todo API prepared for future changes and long-term maintenance.


14. 🌐 Microservices Foundation 🌿 (4 hrs)

Transform your monolithic Todo application into a microservices architecture.

What You’ll Build

Key Concepts

Eureka Service

@SpringBootApplication
@EnableEurekaServer
public class ServiceRegistryApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceRegistryApplication.class, args);
    }
}

API Gateway Configuration

spring:
  cloud:
    gateway:
      routes:
        - id: todo-service
          uri: lb://todo-service
          predicates:
            - Path=/api/todos/**
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**

πŸ’‘ Outcome: A foundation for scaling your Todo application into a microservices architecture.


Certainly! Here’s the corrected chapter index with proper numbering:


Todo App Evolution Through Chapters:

  1. Chapter 1: First endpoint returning β€œHello, Todo!”
  2. Chapter 2: REST API with full CRUD operations
  3. Chapter 3: Layered Architecture with Controller, Service, Repository
  4. Chapter 4: Validated Todo items with proper error handling
  5. Chapter 5: Persistent Todos with user relationships in a database
  6. Chapter 6: Comprehensively tested Todo features
  7. Chapter 7: Secure Todo access with user authentication
  8. Chapter 8: RESTful Todo API with auto-generated documentation
  9. Chapter 9: High-performance Todo operations with caching
  10. Chapter 10: Deployable Todo service across various environments
  11. Chapter 11: Observable Todo application with monitoring
  12. Chapter 12: Feature-rich Todo app with scheduled reminders and real-time updates
  13. Chapter 13: Evolvable Todo API ready for long-term maintenance
  14. Chapter 14: Scalable Todo platform with microservices architecture

Priority Guide:

This comprehensive learning path takes you from a basic Todo application to an enterprise-grade, scalable system, covering essential Spring Boot concepts and advanced software engineering practices.


Let’s start building something awesome! πŸš€