✅ Lab 3 Java/Spring Boot Version Complete
Created a separate Java version of Lab 3 following the successful Lab 2 pattern for focused, stack-specific learning.
Changes Summary
New File: docs/labs/lab-03-generation-and-refactoring-java.md
- Size: 1,053 lines (complete Spring Boot adaptation)
- Commit: 85fefc1
Updated Files:
lab-03-generation-and-refactoring.md - Added cross-reference to Java version
docs/labs/README.md - Updated Lab 3 section with both versions
Java/Spring Boot Content
Part 1: Generate REST API Endpoints (CRUD Operations)
Service Layer Methods:
findAllTasks(TaskStatus status) with optional filtering
findTaskById(UUID id) returning Optional
updateTask(UUID id, UpdateTaskRequest request) with @transactional
deleteTask(UUID id) with EntityNotFoundException
Controller Endpoints:
- GET /api/tasks with optional
status query parameter
- GET /api/tasks/{id} returning 200 OK or 404 Not Found
- PUT /api/tasks/{id} with UpdateTaskRequest DTO
- DELETE /api/tasks/{id} returning 204 No Content
Spring Boot Patterns:
Testing:
- JUnit 5 unit tests for service layer with Mockito
- Integration testing patterns with @SpringBootTest
Part 2: Refactor Legacy Code
Before Issues:
- No Spring annotations
- Nested if statements (6+ levels)
- Thread.sleep() blocking operations
- Swallowed exceptions (empty catch blocks)
- No logging
- Magic numbers and poor naming
- String concatenation in loops
- Mixed concerns
After Improvements:
- @service with @slf4j annotations
- @requiredargsconstructor for constructor injection
- Guard clauses (early returns)
- Proper exception handling with logging
- ProcessingResult value object
- ProcessingType enum
- StringBuilder for efficiency
- Extracted methods:
processSingleTask(), isTaskValid(), executeTaskProcessing()
- SLF4J structured logging with parameters
Expected Refactored Structure:
@Service
@Slf4j
@RequiredArgsConstructor
public class RefactoredTaskProcessor {
private final TaskRepository taskRepository;
private final TaskOutputWriter taskOutputWriter;
public ProcessingResult processTaskBatch(List<TaskItem> tasks) {
// Guard clauses
// Process with proper error handling
// Return comprehensive result
}
}
Part 3: Object Calisthenics
Wrap Primitives:
- TaskId value object with @embeddable annotation
- Priority enum with validation
- TaskStatus enum
- JPA @EmbeddedId for value objects
First-Class Collections:
- TaskCollection wrapping List
- Immutable views with List.copyOf()
- Domain-specific operations (findById, filterByStatus)
No Abbreviations:
- Expanded:
var t → Task task
- Expanded:
var res → Optional<Task> result
- Expanded:
int cnt → int itemCount
Tell, Don't Ask:
- Replace getters with behavior methods
task.isCompleted() instead of checking status + completedAt
Part 4: Multi-File Refactoring
- Copilot Edits for consistent changes
- Working set management
- Review process for AI-generated changes
- Same concepts as .NET version
Extension Exercises
- Pagination: Spring Data Pageable with PageRequest
- Sorting: Sort.by() with multiple fields
- Response Mapper: Dedicated TaskResponseMapper component
Design Decision: Separate Files
Continuing the Lab 2 pattern:
✅ Better Focus: Java developers see only Spring Boot patterns
✅ Manageable Size: 758 (.NET) vs 1,053 (Java) lines
✅ Clear Examples: Spring-specific annotations and patterns
✅ Easy Comparison: Cross-links for developers learning both stacks
Epic #16 Progress
With this completion: 6 of 15 issues complete (40%)
Next Steps
Continue with:
Lab 3 ready for Workshop 2.0 with both .NET and Java/Spring Boot support! 🎉
✅ Lab 3 Java/Spring Boot Version Complete
Created a separate Java version of Lab 3 following the successful Lab 2 pattern for focused, stack-specific learning.
Changes Summary
New File:
docs/labs/lab-03-generation-and-refactoring-java.mdUpdated Files:
lab-03-generation-and-refactoring.md- Added cross-reference to Java versiondocs/labs/README.md- Updated Lab 3 section with both versionsJava/Spring Boot Content
Part 1: Generate REST API Endpoints (CRUD Operations)
Service Layer Methods:
findAllTasks(TaskStatus status)with optional filteringfindTaskById(UUID id)returning OptionalupdateTask(UUID id, UpdateTaskRequest request)with @transactionaldeleteTask(UUID id)with EntityNotFoundExceptionController Endpoints:
statusquery parameterSpring Boot Patterns:
Testing:
Part 2: Refactor Legacy Code
Before Issues:
After Improvements:
processSingleTask(),isTaskValid(),executeTaskProcessing()Expected Refactored Structure:
Part 3: Object Calisthenics
Wrap Primitives:
First-Class Collections:
No Abbreviations:
var t→Task taskvar res→Optional<Task> resultint cnt→int itemCountTell, Don't Ask:
task.isCompleted()instead of checking status + completedAtPart 4: Multi-File Refactoring
Extension Exercises
Design Decision: Separate Files
Continuing the Lab 2 pattern:
✅ Better Focus: Java developers see only Spring Boot patterns
✅ Manageable Size: 758 (.NET) vs 1,053 (Java) lines
✅ Clear Examples: Spring-specific annotations and patterns
✅ Easy Comparison: Cross-links for developers learning both stacks
Epic #16 Progress
With this completion: 6 of 15 issues complete (40%)
Next Steps
Continue with:
Lab 3 ready for Workshop 2.0 with both .NET and Java/Spring Boot support! 🎉