Module 3: Build Sprint 2
Understanding Your Second Ticket
This is the second Build Sprint of Labs. Now that you have completed the first ticket, it's time to start work on your second ticket.
Note: Each ticket builds on the previous one.
Second Ticket Details
View your second ticket details and requirements on GitHub:
Second Ticket DocumentationStep-by-Step Workflow
-
Familiarize Yourself with the Repository
- Read the documentation thoroughly to understand the repository. This may include API contracts, READMEs, or docs on Google/Notion.
- Check the README of the ticket you have been assigned to know what is expected of you.
-
Understanding the Deliverable
- Check the deployed version of the product to see the expected output and match it with what you have to build.
- Read the example of the expected output provided in the README.
-
Code Unit Test (if applicable)
- If a relevant test exists, follow the test-driven development approach to guide your development.
- Validate your code using the unit test to ensure you've produced the expected outcome.
-
Code the Component/Feature
- Code your deliverable, the feature described in the ticket.
-
Record a Loom Video
- Demonstrate the feature in the video.
- Provide a detailed explanation of your thought process while coding.
Submit your Sprint 2 Deliverables: Loom and Code
Technical Interview Simulation
You're in the middle of your first technical interview. The interviewer is going through your resume and stops at the section describing your Labs project. They turn to you and ask:
"How would you describe the project you built in BloomTech Labs and the contributions you had on it?"
Using Loom, record a video articulating to a hiring manager the product you'll be working on in Labs. Feel free to reference your code and ticket.
You should concisely answer the following questions:
- What were the deliverables for your ticket?
- What requirements did you have to keep in mind? Think tech stack, constraints, etc.
- How did you go about shipping your ticket?
- Why did you take the approach you took?
The video should be no longer than 5 minutes, and you must demo the project in the video.
Submission Details
Submit the links to your Loom video and code on GitHub using the form below.
You can access the submission form here.Note: If any one link is missing, the assignment will not be graded and you will have to resubmit.
Your code should:
- be on a forked version of the project repo.
- meet all the requirements listed on the ticket in the README file for this build sprint.
In your Loom video, you must:
- demo the code you created for this ticket.
- articulate how you coded this ticket and why you took that approach.
- showcase your workflow and what steps you took to code this ticket.
All submissions will be graded based on criteria set forth in the rubric below.
Never used Loom before?
How to use the Loom Chrome Extension
Build Sprint Grading Criteria
Criteria | Ratings | |
---|---|---|
This criterion is linked to a Learning OutcomePresenting Their Work The student clearly and accurately explains all aspects of their work, including their approach, design decisions, and results. |
Meets Expectations | Needs Improvement |
This criterion is linked to a Learning OutcomeOrganization The video is well-organized, easy to follow, and presents information in a logical and coherent manner. |
Meets Expectations | Needs Improvement |
This criterion is linked to a Learning OutcomeTechnical Knowledge The student demonstrates a solid understanding of the technical concepts and tools used in their work. They are able to answer technical questions. |
Meets Expectations | Needs Improvement |
This criterion is linked to a Learning OutcomeCode Quality The code is well-organized and readable, follows the best practices that they learned, and the code is readable |
Meets Expectations | Needs Improvement |
This criterion is linked to a Learning OutcomeFunctionality The code runs without errors and produces the expected results. The code is complete and meets the requirements of the assignment. |
Meets Expectations | Needs Improvement |
This criterion is linked to a Learning OutcomeCommenting Comments are clear and provide enough information to understand the purpose and function of the code. |
Meets Expectations | Needs Improvement |
This criterion is linked to a Learning OutcomeCorrectness The code is implemented in a correct, efficient and optimal way. |
Meets Expectations | Needs Improvement |
This criterion is linked to a Learning OutcomeTest Execution The student is able to execute tests and document issues or bugs found. They are able to explain how the tests are verifying the functionality of the system. |
Meets Expectations | Needs Improvement |
This criterion is linked to a Learning OutcomeCommunication & Delivery The student communicates effectively and professionally, speaking clearly, using appropriate nonverbal communication, and expressing themselves in a confident and engaging manner. They show active listening skills and can build rapport. |
Meets Expectations | Needs Improvement |
This criterion is linked to a Learning OutcomePreparation & Self-Presentation The student presents themselves in a professional and polished manner and is well-prepared. They project confidence and enthusiasm. |
Meets Expectations | Needs Improvement |
This criterion is linked to a Learning OutcomeAdaptability The student demonstrates an ability to adapt to new information and respond appropriately to unexpected questions or changes in the interview. They display flexibility and some initiative. |
Meets Expectations | Needs Improvement |
Approaching Your Second Feature
Learn how to implement JWT authentication and RESTful endpoints for the Bloom Coder Assignment App.
Implementation Checklist
- Add JWT dependency and implement JWT utilities
- Create JWT filter for request authentication
- Update Security Configuration for JWT
- Implement User Repository
- Update UserDetailsService implementation
- Configure application properties
- Implement RESTful endpoints
JWT Implementation Concepts
// Example of JWT token structure and claims @Component public class JwtUtil { // Token expiration time in seconds private static final long EXPIRATION_TIME = 86400000; // 24 hours // Secret key for signing tokens @Value("${jwt.secret}") private String secret; // Example of how to structure token claims public String generateToken(UserDetails userDetails) { // Claims are key-value pairs stored in the token Mapclaims = new HashMap<>(); // Example of adding user roles to claims claims.put("roles", userDetails.getAuthorities() .stream() .map(auth -> auth.getAuthority()) .collect(Collectors.toList())); // Token generation with claims return Jwts.builder() .setClaims(claims) .setSubject(userDetails.getUsername()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS256, secret) .compact(); } }
Security Configuration Concepts
// Example of configuring security for JWT authentication @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; @Autowired private UserDetailsService jwtUserDetailsService; @Autowired private JwtRequestFilter jwtRequestFilter; @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity // Disable CSRF for API endpoints .csrf().disable() // Allow specific endpoints without authentication .authorizeRequests() .antMatchers("/api/auth/**").permitAll() .anyRequest().authenticated() .and() // Add exception handling .exceptionHandling() .authenticationEntryPoint(jwtAuthenticationEntryPoint) .and() // Set session management to stateless .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // Add JWT filter httpSecurity.addFilterBefore( jwtRequestFilter, UsernamePasswordAuthenticationFilter.class ); } }
RESTful API Best Practices
Learn about RESTful API design principles and best practices for your Spring Boot application.
API Design Principles
- Resource-based URLs - Organize around resources, not actions
- HTTP Methods - Use proper HTTP methods (GET, POST, PUT, DELETE)
- Status Codes - Return appropriate HTTP status codes
- Versioning - Consider API versioning strategy
- Error Handling - Provide clear error messages and codes
- Documentation - Document your API with Swagger or similar tools
Example REST Controller
@RestController @RequestMapping("/api/assignments") public class AssignmentController { @Autowired private AssignmentService assignmentService; @GetMapping public ResponseEntity> getAllAssignments() { List
assignments = assignmentService.findAll(); return ResponseEntity.ok(assignments); } @GetMapping("/{id}") public ResponseEntity getAssignmentById(@PathVariable Long id) { try { AssignmentDTO assignment = assignmentService.findById(id); return ResponseEntity.ok(assignment); } catch (ResourceNotFoundException e) { return ResponseEntity.notFound().build(); } } @PostMapping public ResponseEntity createAssignment( @Valid @RequestBody AssignmentDTO assignmentDTO) { AssignmentDTO created = assignmentService.create(assignmentDTO); URI location = ServletUriComponentsBuilder .fromCurrentRequest() .path("/{id}") .buildAndExpand(created.getId()) .toUri(); return ResponseEntity.created(location).body(created); } @PutMapping("/{id}") public ResponseEntity updateAssignment( @PathVariable Long id, @Valid @RequestBody AssignmentDTO assignmentDTO) { try { AssignmentDTO updated = assignmentService.update(id, assignmentDTO); return ResponseEntity.ok(updated); } catch (ResourceNotFoundException e) { return ResponseEntity.notFound().build(); } } @DeleteMapping("/{id}") public ResponseEntity deleteAssignment(@PathVariable Long id) { try { assignmentService.delete(id); return ResponseEntity.noContent().build(); } catch (ResourceNotFoundException e) { return ResponseEntity.notFound().build(); } } }
Error Handling in Spring Boot
Learn about implementing global exception handling and error responses in your Spring Boot application.
Exception Handling Best Practices
- Global Exception Handler - Use @ControllerAdvice for centralized exception handling
- Custom Exceptions - Define domain-specific exceptions
- Error Response Structure - Return consistent error response format
- Logging - Log exceptions for debugging and monitoring
- Validation Errors - Handle validation errors consistently
Example Global Exception Handler
@ControllerAdvice public class GlobalExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntityhandleResourceNotFoundException( ResourceNotFoundException ex, WebRequest request) { ErrorResponse errorResponse = new ErrorResponse( HttpStatus.NOT_FOUND.value(), ex.getMessage(), request.getDescription(false), new Date() ); return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity handleValidationExceptions( MethodArgumentNotValidException ex, WebRequest request) { Map errors = new HashMap<>(); ex.getBindingResult().getAllErrors().forEach((error) -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); ErrorResponse errorResponse = new ErrorResponse( HttpStatus.BAD_REQUEST.value(), "Validation Error", errors.toString(), new Date() ); return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); } @ExceptionHandler(Exception.class) public ResponseEntity handleGlobalException( Exception ex, WebRequest request) { logger.error("Unhandled exception", ex); ErrorResponse errorResponse = new ErrorResponse( HttpStatus.INTERNAL_SERVER_ERROR.value(), "An unexpected error occurred", request.getDescription(false), new Date() ); return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); } }