{"id":29099289,"url":"https://github.com/thenoblet/project-tracker","last_synced_at":"2026-04-14T14:31:43.999Z","repository":{"id":297624236,"uuid":"996286069","full_name":"thenoblet/project-tracker","owner":"thenoblet","description":"The Project Tracker API is a comprehensive backend solution for BuildMaster, a rapidly growing startup that needs better visibility into team performance and project progress","archived":false,"fork":false,"pushed_at":"2025-06-26T21:38:19.000Z","size":3795,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-26T23:08:10.471Z","etag":null,"topics":["java","mongodb","postgresql","spring","spring-boot","spring-data-jpa","spring-mvc","spring-security","springframework"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thenoblet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-04T18:18:44.000Z","updated_at":"2025-06-16T21:32:09.000Z","dependencies_parsed_at":"2025-06-26T22:59:23.212Z","dependency_job_id":"1803c217-4d0a-460e-beba-7978c2b25aa8","html_url":"https://github.com/thenoblet/project-tracker","commit_stats":null,"previous_names":["thenoblet/project-tracker"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/thenoblet/project-tracker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thenoblet%2Fproject-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thenoblet%2Fproject-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thenoblet%2Fproject-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thenoblet%2Fproject-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thenoblet","download_url":"https://codeload.github.com/thenoblet/project-tracker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thenoblet%2Fproject-tracker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31801232,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T11:13:53.975Z","status":"ssl_error","status_checked_at":"2026-04-14T11:13:53.299Z","response_time":153,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","mongodb","postgresql","spring","spring-boot","spring-data-jpa","spring-mvc","spring-security","springframework"],"created_at":"2025-06-28T16:02:13.784Z","updated_at":"2026-04-14T14:31:43.987Z","avatar_url":"https://github.com/thenoblet.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Project Tracker API\r\n\r\n![Java](https://img.shields.io/badge/Java-21-blue)\r\n![Spring Boot](https://img.shields.io/badge/Spring_Boot-3.1-green)\r\n![Spring Data JPA](https://img.shields.io/badge/Spring_Data_JPA-3.1-blue)\r\n![MongoDB](https://img.shields.io/badge/MongoDB-6.0-green)\r\n![License](https://img.shields.io/badge/License-MIT-yellow)\r\n\r\n## Overview\r\n\r\nThe Project Tracker API is a comprehensive backend solution for BuildMaster, a rapidly growing startup that needs better visibility into team performance and project progress. This Spring Boot application provides robust project management capabilities with relational data persistence (using Spring Data JPA with PostgresSQL) and NoSQL integration (MongoDB for audit logs).\r\n\r\n## Features\r\n\r\n- **Multi-entity management**: Projects, Tasks, and Developers with proper JPA relationships\r\n- **Advanced querying**: Pagination, sorting, and custom JPQL queries\r\n- **Performance optimisation**: Caching and transaction management\r\n- **Audit logging**: All changes tracked in MongoDB\r\n- **RESTful API**: Comprehensive endpoints for all operations\r\n\r\n## Performance and Optimisation Reports\r\n\r\nPerformance reports were created both **before and after optimisations** using JMeter (for load testing) and JProfiler (for runtime profiling).\r\n\r\n### What was tested\r\n\r\n* Load tests with JMeter simulating up to **200 concurrent users**, targeting critical endpoints in `/projects`, `/tasks`, and `/users`.\r\n* Profiling with JProfiler to analyse:\r\n\r\n  * **Heap \u0026 memory allocations**\r\n  * **Garbage Collection frequency \u0026 pauses**\r\n  * **CPU hot methods**\r\n  * **Thread activity \u0026 potential bottlenecks**\r\n \r\nClick on the links below to look at reports\r\n* [JMeter Report](https://github.com/thenoblet/project-tracker/blob/2238ed789d4f7819ec466ed95b1c897728353b3b/src/main/java/gtp/docs/reports/jmeter-performance-report.md)\r\n* [JProfiler Report](https://github.com/thenoblet/project-tracker/blob/2238ed789d4f7819ec466ed95b1c897728353b3b/src/main/java/gtp/docs/reports/jprofiler-profiling-report.md)\r\n\r\n---\r\n\r\n## Entity Model\r\n\r\n```mermaid\r\nerDiagram\r\n    PROJECT ||--o{ TASK : \"has many\"\r\n    USER ||--o{ TASK : \"assigned to\"\r\n    USER ||--o{ USER_SKILLS : \"has\"\r\n    USER ||--o{ UserRole : assigned\r\n\r\n    PROJECT {\r\n        UUID id PK\r\n        String name \"NotBlank, Size(2-255)\"\r\n        String description \"Size(2-500)\"\r\n        LocalDate startDate \"NotNull, FutureOrPresent\"\r\n        LocalDate deadline \"NotNull, FutureOrPresent\"\r\n        ProjectStatus status \"Default: ACTIVE\"\r\n        LocalDateTime createdAt \"NotNull\"\r\n        LocalDateTime updatedAt \"NotNull\"\r\n    }\r\n\r\n    USER {\r\n        UUID id PK\r\n        String name \"Size(max=50)\"\r\n        String email \"NotBlank, Unique\"\r\n        String password \"Nullable\"\r\n        Role role \"NotNull, Enum\"\r\n        boolean oauth2user \"Default: false\"\r\n        Integer taskCount \"Formula-based\"\r\n        LocalDateTime createdAt\r\n        LocalDateTime updatedAt\r\n    }\r\n\r\n    TASK {\r\n        UUID id PK\r\n        String title \"NotBlank, Size(2-255)\"\r\n        String description \"Size(2-500)\"\r\n        Status status \"Default: TODO\"\r\n        Priority priority \"Default: LOW\"\r\n        LocalDate dueDate \"NotNull\"\r\n        UUID project_id FK\r\n        UUID user_id FK\r\n        LocalDateTime createdAt \"NotNull\"\r\n        LocalDateTime updatedAt \"NotNull\"\r\n    }\r\n\r\n    USER_SKILLS {\r\n        UUID user_id FK\r\n        String skill\r\n    }\r\n    \r\n    AUDIT_LOG {\r\n        String id PK\r\n        String actionType\r\n        String entityType\r\n        String entityId\r\n        Instant timestamp\r\n        String actorName\r\n        String payload\r\n    }\r\n\r\n    UserRole { \r\n        ROLE_ADMIN\r\n        ROLE_MANAGER \r\n        ROLE_DEVELOPER \r\n        ROLE_CONTRACTOR \r\n        }\r\n\r\n\r\n```\r\n---\r\n## Tech Stack\r\n\r\n- **Backend**: Spring Boot 3.1\r\n- **Database**:\r\n    - Relational: PostgreSQL\r\n    - NoSQL: MongoDB\r\n- **ORM**: Spring Data JPA (Hibernate)\r\n- **Caching**: Spring Cache\r\n- **API Documentation**: OpenAPI 3.0 (Swagger)\r\n- **Testing**: JUnit 5\r\n\r\n---\r\n## Getting Started\r\n\r\n### Prerequisites\r\n\r\n- Java 21\r\n- Maven 3.8+\r\n- Docker (for MongoDB container, Postgre )\r\n- Configure .env for application.properties\r\n### Installation\r\n\r\n1. Clone the repository:\r\n   ```bash\r\n   git clone https://github.com/thenoblet/project-tracker.git\r\n   cd project-tracker\r\n   ```\r\n\r\n2. Start Docker:\r\n   ```bash\r\n   docker compose up\r\n   ```\r\n\r\n3. Build and run the application:\r\n   ```bash\r\n   mvn spring-boot:run\r\n   ```\r\n---\r\n## API ENDPOINTS\r\n\r\n| Method | Endpoint                          | Description                                  | Parameters/Request Body                     |\r\n|--------|-----------------------------------|----------------------------------------------|---------------------------------------------|\r\n| GET    | `/api/v1/projects`                | Get paginated list of projects               | `pageable`, `includeTasks` (query)          |\r\n| POST   | `/api/v1/projects`                | Create a new project                         | `CreateProjectRequest` (body)               |\r\n| GET    | `/api/v1/projects/{id}`           | Get project by ID                            | `id` (path)                                 |\r\n| PUT    | `/api/v1/projects/{id}`           | Update entire project                        | `id` (path), `UpdateProjectRequest` (body)  |\r\n| PATCH  | `/api/v1/projects/{id}`           | Partial update of project                    | `id` (path), `UpdateProjectRequest` (body)  |\r\n| DELETE | `/api/v1/projects/{id}`           | Delete project                               | `id` (path)                                 |\r\n| PATCH  | `/api/v1/projects/{id}/status`    | Update project status                        | `id` (path), `status` (query)               |\r\n| GET    | `/api/v1/projects/{id}/tasks`     | Get tasks for project                        | `id` (path), filters (query), `pageable`    |\r\n| GET    | `/api/v1/projects/{id}/tasks/overdue` | Get overdue tasks for project             | `id` (path), `pageable`                     |\r\n\r\n\r\nVisit [ALL API ENDPOINTS](src/main/java/gtp/docs/ENDPOINTS.md) to see the full list of all endpoints\r\n\r\nFor complete API documentation, visit the Swagger UI at `http://localhost:8080/swagger-ui.html` when the application is running.\r\n\r\n---\r\n\r\n## Authentication Sequence Diagram\r\n\r\n````mermaid\r\nsequenceDiagram\r\n    actor User\r\n    participant Client\r\n    participant AuthController\r\n    participant AuthService\r\n    participant Database\r\n    participant JwtProvider\r\n    participant GoogleOAuth\r\n\r\n    Note over User,GoogleOAuth: Email/Password Login\r\n    User-\u003e\u003eClient: Enter credentials\r\n    Client-\u003e\u003eAuthController: POST /login\r\n    AuthController-\u003e\u003eAuthService: login(request)\r\n    AuthService-\u003e\u003eDatabase: findByEmail() + validate password\r\n    Database--\u003e\u003eAuthService: User details\r\n    AuthService-\u003e\u003eJwtProvider: generateToken()\r\n    JwtProvider--\u003e\u003eAuthService: JWT\r\n    AuthService--\u003e\u003eClient: JWT + user info\r\n\r\n    Note over User,GoogleOAuth: Google OAuth2 Login\r\n    User-\u003e\u003eClient: Click \"Sign in with Google\"\r\n    Client-\u003e\u003eGoogleOAuth: Redirect to Google\r\n    GoogleOAuth--\u003e\u003eClient: Authorization code\r\n    Client-\u003e\u003eAuthController: OAuth2 callback\r\n    AuthController-\u003e\u003eDatabase: findOrCreateUser()\r\n    Database--\u003e\u003eAuthController: User details\r\n    AuthController-\u003e\u003eJwtProvider: generateToken()\r\n    JwtProvider--\u003e\u003eAuthController: JWT\r\n    AuthController--\u003e\u003eClient: JWT + user info\r\n\r\n    Note over User,GoogleOAuth: Protected Endpoints\r\n    Client-\u003e\u003eAuthController: Request with JWT header\r\n    AuthController-\u003e\u003eJwtProvider: validateToken()\r\n    JwtProvider--\u003e\u003eAuthController: Valid\r\n    AuthController--\u003e\u003eClient: Protected data\r\n````\r\n\r\n---\r\n\r\n## Advanced Features\r\n\r\n### Caching\r\n\r\nFrequently accessed endpoints are cached for better performance:\r\n\r\n```java\r\n@Cacheable(\"projects\")\r\n@GetMapping(\"/{id}\")\r\npublic Project getProjectById(@PathVariable UUID id) {\r\n    // ...\r\n}\r\n```\r\n\r\n### Transaction Management\r\n\r\nComplex operations are wrapped in transactions:\r\n\r\n```java\r\n@Transactional\r\npublic void deleteProjectWithTasks(UUID projectId) {\r\n    taskRepository.deleteByProjectId(projectId);\r\n    projectRepository.deleteById(projectId);\r\n}\r\n```\r\n\r\n### Audit Logging\r\n\r\nAll changes are automatically logged to MongoDB:\r\n\r\n```java\r\n@PostPersist\r\npublic void afterPersist() {\r\n    auditLogService.logCreate(this);\r\n}\r\n```\r\n\r\n### Custom Queries\r\n\r\nExample of a custom query to find overdue tasks:\r\n\r\n```java\r\n@Query(\"SELECT t FROM Task t WHERE t.dueDate \u003c CURRENT_DATE AND t.status \u003c\u003e 'DONE'\")\r\nList\u003cTask\u003e findOverdueTasks();\r\n```\r\n\r\n## Testing\r\n\r\nThe project includes comprehensive tests:\r\n\r\n- Unit tests with JUnit 5\r\n- Integration tests with `@DataJpaTest`\r\n\r\nRun all tests with:\r\n\r\n```bash\r\nmvn test\r\n```\r\n\r\n## Performance Best Practices\r\n\r\n1. **Pagination**: All list endpoints support pagination\r\n2. **Lazy Loading**: Properly configured entity relationships\r\n3. **Batch Fetching**: Optimized for N+1 query problems\r\n4. **Indexing**: Proper database indexes on frequently queried fields\r\n5. **Caching**: For frequently accessed but rarely changed data\r\n\r\n## Deployment\r\n\r\n### Docker\r\n\r\nBuild a Docker image:\r\n\r\n```bash\r\ndocker build -t project-tracker .\r\n```\r\n\r\nRun with MySQL and MongoDB:\r\n\r\n```bash\r\ndocker-compose up\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthenoblet%2Fproject-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthenoblet%2Fproject-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthenoblet%2Fproject-tracker/lists"}