Added complete DevTrack Spring Boot project#1
Conversation
There was a problem hiding this comment.
Pull request overview
Adds an initial DevTrack Pro Spring Boot backend with REST APIs for tasks, focus sessions, and dashboard analytics, along with Maven wrapper/build configuration and a small JUnit test suite.
Changes:
- Introduces JPA entities, repositories, services, and controllers for Tasks and Focus Sessions.
- Adds an Analytics endpoint and DTO for dashboard statistics.
- Adds Maven wrapper/pom setup and initial Spring Boot + MVC/service tests.
Reviewed changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
src/main/java/com/devtrackpro/DevtrackProApplication.java |
Spring Boot application entrypoint. |
src/main/resources/application.properties |
App name, server port, and datasource/JPA defaults. |
src/main/java/com/devtrackpro/model/Task.java |
Task JPA entity with lifecycle defaults. |
src/main/java/com/devtrackpro/model/FocusSession.java |
Focus session JPA entity. |
src/main/java/com/devtrackpro/repository/TaskRepository.java |
Task JPA repository with status count query method. |
src/main/java/com/devtrackpro/repository/FocusSessionRepository.java |
Focus session repository with total-minutes aggregation query. |
src/main/java/com/devtrackpro/service/TaskService.java |
Task CRUD service logic. |
src/main/java/com/devtrackpro/service/FocusSessionService.java |
Focus session CRUD service logic. |
src/main/java/com/devtrackpro/service/AnalyticsService.java |
Aggregates dashboard stats from repositories. |
src/main/java/com/devtrackpro/dto/DashboardResponseDTO.java |
DTO for dashboard metrics. |
src/main/java/com/devtrackpro/controller/TaskController.java |
REST endpoints for task CRUD. |
src/main/java/com/devtrackpro/controller/FocusSessionController.java |
REST endpoints for focus session CRUD. |
src/main/java/com/devtrackpro/controller/AnalyticsController.java |
REST endpoint for dashboard stats. |
src/main/java/com/devtrackpro/exception/ResourceNotFoundException.java |
Custom runtime exception for missing resources. |
src/main/java/com/devtrackpro/exception/GlobalExceptionHandler.java |
Maps not-found exceptions to a JSON response. |
src/test/java/com/devtrackpro/DevtrackProApplicationTests.java |
Spring context load smoke test. |
src/test/java/com/devtrackpro/service/AnalyticsServiceTest.java |
Unit test for analytics aggregation logic (Mockito). |
src/test/java/com/devtrackpro/controller/TaskControllerTest.java |
MVC tests for task list/create endpoints. |
src/test/java/com/devtrackpro/controller/AnalyticsControllerTest.java |
MVC test for analytics dashboard endpoint. |
pom.xml |
Maven project definition and dependencies. |
.mvn/wrapper/maven-wrapper.properties |
Maven wrapper configuration. |
mvnw |
Maven wrapper script (Unix). |
mvnw.cmd |
Maven wrapper script (Windows). |
.gitignore |
Ignores build/tooling artifacts. |
.gitattributes |
Normalizes line endings for wrapper scripts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public interface FocusSessionRepository extends JpaRepository<FocusSession, Long> { | ||
|
|
||
| @Query("SELECT COALESCE(SUM(f.durationMinutes),0) FROM FocusSession f") | ||
| Integer getTotalFocusMinutes(); |
There was a problem hiding this comment.
JPQL SUM over an Integer field typically returns a Long. This query is likely to return a Long/Number, but the repository method is declared as Integer, which can cause a runtime type mismatch (ClassCastException) or truncation. Consider changing the return type to Long (or Number) and updating callers/DTO accordingly.
| Integer getTotalFocusMinutes(); | |
| Long getTotalFocusMinutes(); |
| public DashboardResponseDTO getDashboardStats() { | ||
| long totalTasks = taskRepository.count(); | ||
| long completedTasks = taskRepository.countByStatus("DONE"); | ||
| long totalSessions = focusSessionRepository.count(); | ||
| int totalMinutes = focusSessionRepository.getTotalFocusMinutes(); | ||
|
|
||
| return new DashboardResponseDTO( | ||
| totalTasks, | ||
| completedTasks, | ||
| totalSessions, | ||
| totalMinutes | ||
| ); |
There was a problem hiding this comment.
getTotalFocusMinutes() is assigned to an int. Given the repository query uses SUM, the natural type is Long, and totals can exceed Integer.MAX_VALUE. Align the types end-to-end (repository return type, service local variable, and DTO field) to avoid runtime casts/overflow.
| private long totalTasks; | ||
| private long completedTasks; | ||
| private long totalFocusSessions; | ||
| private int totalFocusMinutes; |
There was a problem hiding this comment.
totalFocusMinutes is modeled as an int, but the underlying data is aggregated via SUM and is naturally a long. Using int risks overflow and also makes it harder to align with a Long return type from JPA. Consider switching this field to long (and updating JSON/tests accordingly).
| private int totalFocusMinutes; | |
| private long totalFocusMinutes; |
| spring.application.name=devtrack-pro | ||
| spring.datasource.url=jdbc:postgresql://localhost:5432/devtrack | ||
| spring.datasource.username=postgres | ||
| spring.datasource.password=admin |
There was a problem hiding this comment.
This configuration hard-codes database credentials (including a password) in version control. Move credentials to environment variables / externalized config (e.g., ${DB_PASSWORD}) and consider using profile-specific property files so secrets are not committed.
| spring.datasource.password=admin | |
| spring.datasource.password=${DB_PASSWORD} |
| spring.jpa.hibernate.ddl-auto=update | ||
| spring.jpa.show-sql=true | ||
| spring.jpa.properties.hibernate.format_sql=true |
There was a problem hiding this comment.
spring.jpa.hibernate.ddl-auto=update and spring.jpa.show-sql=true are risky defaults for non-dev environments and can cause unexpected schema changes and verbose logging in production. Consider moving these to a dev profile (or defaulting to validate/none and show-sql=false) and enabling them only for local development.
| spring.jpa.hibernate.ddl-auto=update | |
| spring.jpa.show-sql=true | |
| spring.jpa.properties.hibernate.format_sql=true | |
| spring.jpa.hibernate.ddl-auto=${SPRING_JPA_HIBERNATE_DDL_AUTO:validate} | |
| spring.jpa.show-sql=${SPRING_JPA_SHOW_SQL:false} | |
| spring.jpa.properties.hibernate.format_sql=${SPRING_JPA_HIBERNATE_FORMAT_SQL:false} |
| Map.of( | ||
| "timestamp", LocalDateTime.now(), | ||
| "message", ex.getMessage(), | ||
| "status", 404 |
There was a problem hiding this comment.
The response body includes a hard-coded numeric status (404). Using HttpStatus.NOT_FOUND.value() (or similar) avoids magic numbers and keeps the payload consistent if the status ever changes.
| "status", 404 | |
| "status", HttpStatus.NOT_FOUND.value() |
| @SpringBootTest | ||
| class DevtrackProApplicationTests { | ||
|
|
||
| @Test | ||
| void contextLoads() { | ||
| } |
There was a problem hiding this comment.
This @SpringBootTest will load the full application context and, with the current committed Postgres spring.datasource.* settings, will attempt to connect to a local database during tests. In CI this will typically fail. Consider using an isolated test profile (e.g., H2/Testcontainers) or overriding datasource properties for tests so contextLoads() is reliable.
| import java.util.List; | ||
|
|
||
| import static org.mockito.Mockito.when; | ||
| import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; |
There was a problem hiding this comment.
There is an unused delete static import here. While it may not fail the Maven build by default, it adds noise and can fail under stricter compiler/linter settings. Consider removing it or adding a delete endpoint test that uses it.
| import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; |
| @GetMapping("/{id}") | ||
| public Task getById(@PathVariable Long id) { | ||
| return taskService.getTaskById(id); | ||
| } | ||
|
|
||
| @PutMapping("/{id}") | ||
| public Task update(@PathVariable Long id, @RequestBody Task task) { | ||
| return taskService.updateTask(id, task); | ||
| } | ||
|
|
||
| @DeleteMapping("/{id}") | ||
| public ResponseEntity<Void> delete(@PathVariable Long id) { | ||
| taskService.deleteTask(id); | ||
| return ResponseEntity.noContent().build(); | ||
| } |
There was a problem hiding this comment.
This controller exposes GET /{id}, PUT /{id}, and DELETE /{id} behavior, but the current test suite in TaskControllerTest only covers list and create. Adding MVC tests for these endpoints (including the 404 path) would improve coverage and help prevent regressions.
| @RestController | ||
| @RequestMapping("/api/sessions") | ||
| @RequiredArgsConstructor | ||
| @CrossOrigin("*") | ||
| public class FocusSessionController { | ||
|
|
||
| private final FocusSessionService service; | ||
|
|
||
| @PostMapping | ||
| public FocusSession create(@RequestBody FocusSession session) { | ||
| return service.create(session); | ||
| } | ||
|
|
||
| @GetMapping | ||
| public List<FocusSession> getAll() { | ||
| return service.getAll(); | ||
| } | ||
|
|
||
| @DeleteMapping("/{id}") | ||
| public void delete(@PathVariable Long id) { | ||
| service.delete(id); | ||
| } |
There was a problem hiding this comment.
There are no MVC tests covering the focus session endpoints (create/list/delete). Since other controllers have WebMvcTest coverage, adding a FocusSessionControllerTest (including 404 behavior on delete) would help keep the API stable.
No description provided.