{"id":26070285,"url":"https://github.com/fresult/gout-together","last_synced_at":"2026-04-29T04:35:14.390Z","repository":{"id":262609385,"uuid":"887479395","full_name":"fResult/Gout-Together","owner":"fResult","description":"This project is for learning Java, Spring Boot from Java Backend Developer Boot Camp [2024] BY TP Coder","archived":false,"fork":false,"pushed_at":"2025-01-30T11:56:24.000Z","size":740,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-08T23:14:07.859Z","etag":null,"topics":["java","junit5","mockito","mockmvc","spring-boot","spring-security","spring-security-oauth2"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fResult.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2024-11-12T20:18:40.000Z","updated_at":"2025-01-30T11:56:27.000Z","dependencies_parsed_at":"2024-12-05T11:22:22.718Z","dependency_job_id":"9b81bf1f-e424-46d1-8c40-fa47980c849f","html_url":"https://github.com/fResult/Gout-Together","commit_stats":null,"previous_names":["fresult/gout-together"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fResult/Gout-Together","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fResult%2FGout-Together","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fResult%2FGout-Together/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fResult%2FGout-Together/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fResult%2FGout-Together/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fResult","download_url":"https://codeload.github.com/fResult/Gout-Together/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fResult%2FGout-Together/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262608599,"owners_count":23336533,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","junit5","mockito","mockmvc","spring-boot","spring-security","spring-security-oauth2"],"created_at":"2025-03-08T23:15:45.186Z","updated_at":"2026-04-29T04:35:14.384Z","avatar_url":"https://github.com/fResult.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gout Together Backend\n\nThis project is for learning Java, Spring Boot\nfrom [Java Backend Developer Boot Camp \\[2024\\]](https://www.youtube.com/playlist?list=PLm3A9eDaMzukMQtdDoeOR-HbFN35vieQY)\nBY [TP Coder](https://www.youtube.com/@tpcoder)\n\nCourse Code Example: \u003chttps://github.com/marttp/20240629-GoutTogether\u003e\n\n## API Usage\n\nDownload Postman Collection from the [Gout-Together.postman_collection.json](https://raw.githubusercontent.com/fResult/Gout-Together/refs/heads/main/Gout-Together.postman_collection.json) file, then import to your [Postman](https://www.postman.com/downloads).\n\n```bash\n# Download the Postman Collection to current (working) directory\ncurl -O https://raw.githubusercontent.com/fResult/Gout-Together/refs/heads/main/Gout-Together.postman_collection.json\n\n# Download the Postman Collection to your specific directory\ncurl -o /path/to/your/target/directory/Gout-Together.postman_collection.json https://raw.githubusercontent.com/fResult/Gout-Together/refs/heads/main/Gout-Together.postman_collection.json\n```\n\n## Prerequisites\n\n- JDK 24 or later\n- Gradle 8.14 or later\n- Docker (for running Database, Grafana, and OpenTelemetry Collector)\n\n## Related commands\n\n### Start the Database\n\n```bash\ndocker-compose -f docker/compose.yml --env-file .env up -d\n```\n\n### Build Jar and Get the OpenTelemetry Agent\n\n```bash\n./gradlew clean build\n```\n\n### Environment Variables\n\n#### Add Environment File\n\n```bash\ncp .envTemplate .env\n```\n\n#### Generate RSA Keypair\n\n```shell\nopenssl genrsa -out src/main/resources/private_key.pem 4096\nopenssl rsa -pubout -in src/main/resources/private_key.pem -out src/main/resources/public_key.pem\nopenssl pkcs8 -topk8 -in src/main/resources/private_key.pem -inform pem -out src/main/resources/private_key_pkcs8.pem -outform pem -nocrypt\n```\n\n#### Assign Public/Private Key for Spring Security Config\n\n```shell\nbase64 -i src/main/resources/private_key_pkcs8.pem # Then put the Base64 text to the `OAUTH_PRIVATE_KEY_BASE64` env var\nbase64 -i src/main/resources/public_key.pem # Then put the Base64 text to the `OAUTH_PUBLIC_KEY_BASE64` env var\n```\n\n### Start the application\n\n#### In development mode with OpenTelemetry Java Agent\n\nAs we already declared the required environment variables in the `.env` file, we can start application with the\nfollowing\ncommand.\n\n```bash\n./gradlew bootRun\n```\n\nSince this is for learning purpose, the environment variables in the `.env` file are:\n\n```env\nJAVA_TOOL_OPTIONS=\"-javaagent:build/agent/opentelemetry-javaagent.jar\"\nOTEL_SERVICE_NAME=gout\nOTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317\nOTEL_EXPORTER_OTLP_PROTOCOL=grpc\nOTEL_RESOURCE_ATTRIBUTES=\"service.name=gout,service.instance.id=gout,env=dev\"\n# Logs are disabled by default\nOTEL_LOGS_EXPORTER=otlp\nOTEL_METRIC_EXPORT_INTERVAL=500\nOTEL_BSP_SCHEDULE_DELAY=500\n\n```\n\n#### In Build mode with OpenTelemetry Java Agent\n\n```bash\njava -javaagent:build/agent/opentelemetry-javaagent.jar -jar build/libs/app.jar\n```\n\n### Visit to Grafana on local machine\n\n- \u003chttp://localhost:3000\u003e\n\n## My Summary\n\n### Things I learned from attending the course\n\n- OpenTelemetry Java Agent\n- Spring Security implementation\n- Unit Testing with JUnit 5 and Mockito\n- Configuring authorization with OAuth2ResourceServer\n- Integration Testing\n- Pessimistic Locking for data consistency\n- Implementing idempotency keys to prevent duplicate transaction processing\n\n### Things I did different and learned further\n\n- Used the Gradle Kotlin instead of the Gradle Groovy\n- PasswordEncoder: using Argon2PasswordEncoder instead of BCryptPasswordEncoder\n- Added more assertion, including asserting error message in Unit Tests\n- Resolved circular dependency using `@Lazy` annotation\n- Implemented [Virtual Thread](https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html) and `CompletableFuture` for concurrent database operations\n    - See: [WalletServiceImpl.getConsumerAndTourCompanyWallets()](https://github.com/fResult/Gout-Together/blob/f4ef3ffebc4bee2ad9919b78996cfa1c659e484f/src/main/java/dev/fResult/goutTogether/wallets/services/WalletServiceImpl.java#L202-L224)\n- Handled complex exception propagation in multi-threaded scenarios\n    - Implemented in [ErrorHelper.throwMatchedException()](https://github.com/fResult/Gout-Together/blob/f4ef3ffebc4bee2ad9919b78996cfa1c659e484f/src/main/java/dev/fResult/goutTogether/common/helpers/ErrorHelper.java#L24-L38)\n    - Applied in [service layer](https://github.com/fResult/Gout-Together/blob/f4ef3ffebc4bee2ad9919b78996cfa1c659e484f/src/main/java/dev/fResult/goutTogether/wallets/services/WalletServiceImpl.java#L225-L227)\n- Created custom application properties\n    - Implemented in: [MyApplicationProperties.java](https://github.com/fResult/Gout-Together/blob/f4ef3ffebc4bee2ad9919b78996cfa1c659e484f/src/main/java/dev/fResult/goutTogether/common/configs/MyApplicationProperties.java)\n    - Applied in [SecurityConfig.java](https://github.com/fResult/Gout-Together/blob/34161612b0706213de18d278ebc5c15681c4b324/src/main/java/dev/fResult/goutTogether/common/configs/SecurityConfig.java#L52-L56)\n\n### Test Coverage\n![Image to display percentage of code coverage](https://github.com/user-attachments/assets/ef5c0b2d-3fd4-4af7-804d-7819b5c4b1b8)\n\n\u003cfooter\u003e\n  \u003cdiv align=center\u003e\n    \u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e.\u003cbr\u003e\u003cbr\u003e\n  \u003c/div\u003e\n\n  \u003cp align=center\u003e\n    [This Space Intentionally Left Blank]\n  \u003c/p\u003e\n\n  \u003cp align=center\u003e\n    The bottom of every page is padded so readers can maintain a consistent eyeline.\n  \u003c/p\u003e\n\u003c/footer\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffresult%2Fgout-together","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffresult%2Fgout-together","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffresult%2Fgout-together/lists"}