{"id":21076427,"url":"https://github.com/rapter1990/bookdelivery","last_synced_at":"2025-05-16T06:32:22.198Z","repository":{"id":193699047,"uuid":"689310989","full_name":"Rapter1990/bookdelivery","owner":"Rapter1990","description":"Case Study - Sample Book Delivery App (Spring Boot, Spring Security , Mysql, JUnit, Integration Test, Docker, Test Container, AOP, CI/CD, Prometheus, Grafana, Github Actions)","archived":false,"fork":false,"pushed_at":"2023-11-02T18:29:47.000Z","size":4269,"stargazers_count":46,"open_issues_count":0,"forks_count":9,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-24T06:33:55.176Z","etag":null,"topics":["aop","ci-cd","continuous-deployment","continuous-integration","docker","docker-compose","github-actions","grafana","integration-test","java","junit","monolith","mysql","pessimistic-locking","prometheus","spring-boot","spring-mvc","spring-security","swagger","test-container"],"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/Rapter1990.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}},"created_at":"2023-09-09T12:11:08.000Z","updated_at":"2024-04-13T00:48:40.000Z","dependencies_parsed_at":"2023-11-08T10:01:11.281Z","dependency_job_id":null,"html_url":"https://github.com/Rapter1990/bookdelivery","commit_stats":{"total_commits":279,"total_committers":3,"mean_commits":93.0,"dds":0.4336917562724014,"last_synced_commit":"a039c20564a3f91750341e53c5da74e901d64e1c"},"previous_names":["rapter1990/bookdelivery"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rapter1990%2Fbookdelivery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rapter1990%2Fbookdelivery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rapter1990%2Fbookdelivery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rapter1990%2Fbookdelivery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Rapter1990","download_url":"https://codeload.github.com/Rapter1990/bookdelivery/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225413310,"owners_count":17470556,"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":["aop","ci-cd","continuous-deployment","continuous-integration","docker","docker-compose","github-actions","grafana","integration-test","java","junit","monolith","mysql","pessimistic-locking","prometheus","spring-boot","spring-mvc","spring-security","swagger","test-container"],"created_at":"2024-11-19T19:28:20.365Z","updated_at":"2024-11-19T19:28:21.020Z","avatar_url":"https://github.com/Rapter1990.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Case Study - Book Delivery\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"screenshots/book_delivey_main_image.png\" alt=\"Main Information\" width=\"700\" height=\"500\"\u003e\n\u003c/p\u003e\n\n### 📖 Information\n\n\u003cul style=\"list-style-type:disc\"\u003e\n  \u003cli\u003e\u003cb\u003eBook Delivery\u003c/b\u003e is a kind of Spring Boot with covering important and useful features\u003c/li\u003e \n  \u003cli\u003eHere is the explanation of the example\n       \u003cul\u003eThere are 2 roles named \u003cb\u003eAdmin\u003c/b\u003e and \u003cb\u003eCustomer\u003c/b\u003e\u003c/ul\u003e\n       \u003cul\u003e\u003cb\u003eAdmin\u003c/b\u003e handles with creating book, updating stock of book and updating book information, getting all books and book by id, showing statistic by customer's order and all orders while \u003cb\u003eCustomer\u003c/b\u003e tackle with creating order, showing own orders, getting all books and book by id except for their own authentication process covering the process of register, login, refresh token and logout\u003c/ul\u003e\n  \u003c/li\u003e\n\u003c/ul\u003e\n\n### Explore Rest APIs\n\n\u003ctable style=\"width:100%\"\u003e\n  \u003ctr\u003e\n      \u003cth\u003eMethod\u003c/th\u003e\n      \u003cth\u003eUrl\u003c/th\u003e\n      \u003cth\u003eDescription\u003c/th\u003e\n      \u003cth\u003eRequest Body\u003c/th\u003e\n      \u003cth\u003eHeader\u003c/th\u003e\n      \u003cth\u003eValid Path Variable\u003c/th\u003e\n      \u003cth\u003eNo Path Variable\u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\n      \u003ctd\u003e/api/v1/auth/register\u003c/td\u003e\n      \u003ctd\u003eRegister of both Admin and Customer\u003c/td\u003e\n      \u003ctd\u003eSignupRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\n      \u003ctd\u003e/api/v1/auth/login\u003c/td\u003e\n      \u003ctd\u003eLogin of both Admin and Customer\u003c/td\u003e\n      \u003ctd\u003eLoginRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\n      \u003ctd\u003e/api/v1/auth/refreshtoken\u003c/td\u003e\n      \u003ctd\u003eRefresh Token of both Admin and Customer\u003c/td\u003e\n      \u003ctd\u003eTokenRefreshRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\n      \u003ctd\u003e/api/v1/auth/logout\u003c/td\u003e\n      \u003ctd\u003eLogout of both Admin and Customer\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003etoken\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\n      \u003ctd\u003e/api/v1/books\u003c/td\u003e\n      \u003ctd\u003eCreate Book from Admin\u003c/td\u003e\n      \u003ctd\u003eBookCreateRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePUT\u003c/td\u003e\n      \u003ctd\u003e/api/v1/books/stock-amount/{bookId}\u003c/td\u003e\n      \u003ctd\u003eUpdate Stock of Book from Admin\u003c/td\u003e\n      \u003ctd\u003eBookUpdateStockRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003ebookId\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePUT\u003c/td\u003e\n      \u003ctd\u003e/api/v1/books/{bookId}\u003c/td\u003e\n      \u003ctd\u003eUpdate Book from Admin\u003c/td\u003e\n      \u003ctd\u003eBookUpdateRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003ebookId\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePUT\u003c/td\u003e\n      \u003ctd\u003e/api/v1/books/{bookId}\u003c/td\u003e\n      \u003ctd\u003eUpdate Book from Admin\u003c/td\u003e\n      \u003ctd\u003eBookUpdateRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003ebookId\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\n      \u003ctd\u003e/api/v1/books/{bookId}\u003c/td\u003e\n      \u003ctd\u003eGet Book by Id from Admin and Customer\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003ebookId\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\n      \u003ctd\u003e/api/v1/books/{bookId}\u003c/td\u003e\n      \u003ctd\u003eGet Books from Admin and Customer\u003c/td\u003e\n      \u003ctd\u003ePaginationRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\n      \u003ctd\u003e/api/v1/customers\u003c/td\u003e\n      \u003ctd\u003eCreate Customer from Admin\u003c/td\u003e\n      \u003ctd\u003eCustomerCreateRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\n      \u003ctd\u003e/api/v1/orders\u003c/td\u003e\n      \u003ctd\u003eCreate Order from Customer\u003c/td\u003e\n      \u003ctd\u003eCreateOrderRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\n      \u003ctd\u003e/api/v1/orders/{orderId}\u003c/td\u003e\n      \u003ctd\u003eGet Order by Id from Admin and Customer\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003eorderId\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\n      \u003ctd\u003e/api/v1/orders/{orderId}\u003c/td\u003e\n      \u003ctd\u003eGet Orders by Customer Id from Admin and Customer\u003c/td\u003e\n      \u003ctd\u003ePaginationRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003ecustomerId\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\n      \u003ctd\u003e/api/v1/orders/between-dates\u003c/td\u003e\n      \u003ctd\u003eGet Orders by between dates from Admin and Customer\u003c/td\u003e\n      \u003ctd\u003ePaginationRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003ecustomerId\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\n      \u003ctd\u003e/api/v1/orders/between-dates\u003c/td\u003e\n      \u003ctd\u003eGet Orders by between dates from Admin and Customer\u003c/td\u003e\n      \u003ctd\u003ePaginationRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\n      \u003ctd\u003e/api/v1/statistics/{customerId}\u003c/td\u003e\n      \u003ctd\u003eGet Order Statistics By CustomerId from Admin and Customer\u003c/td\u003e\n      \u003ctd\u003ePaginationRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003ecustomerId\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n  \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\n      \u003ctd\u003e/api/v1/statistics\u003c/td\u003e\n      \u003ctd\u003eGet Order Statistics from Admin\u003c/td\u003e\n      \u003ctd\u003ePaginationRequest\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n  \u003ctr\u003e\n\u003c/table\u003e\n\n\n\n### Technologies\n\n---\n- Java 17\n- Spring Boot 3.0\n- Restful API\n- Lombok\n- Maven\n- Junit5\n- Mockito\n- Integration Tests\n- Docker\n- Docker Compose\n- CI/CD (Github Actions)\n- Prometheus and Grafana\n- Postman\n- Actuator\n- Swagger 3\n\n\n### How to test Pessimistic Lock using ApacheHttpServer?\nWe implemented a pessimistic lock mechanism to avoid scenarios where multiple users attempt to order books simultaneously,\nensuring that their actions are synchronized properly to prevent data conflicts.\nSo with a pessimstic lock, if multiple users attempt to order one last stock of a book, only one of them will be able to order.\n\n### Install Apache 2 on Linux \u0026 Test\nInstallation\n\n```\nsudo apt-get install apache2\n```\n\nTo test, you need to make requests to the create order endpoint.\nSo you're going to need a valid payload json which is shown below.\n(Do not forget to change the bookId with a valid one)\n\n```json\n{\n  \"orderDetailSet\": [\n    {\n      \"bookId\": \"3a0e7efc-1e32-404c-9a70-d9fb63262c6e\",\n      \"amount\": 1\n    }\n  ]\n}\n```\n\nNow we can test the create order endpoint, and see if the locking mechanism works\n\n- \u003cb\u003en\u003c/b\u003e represents the number of requests to be made to the URL specified\n- \u003cb\u003ec\u003c/b\u003e represents the number of requests to send at a time. Here, it's set to 2, so ApacheBench will send 2 requests concurrently.\n\nHere is the example shown below for testing\n```\nab -n 100 -c 2 -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX0NVU1RPTUVSIl0sInVzZXJGdWxsTmFtZSI6ImN1c3RvbWVyX2Z1bGxuYW1lIiwiaWQiOjIsImVtYWlsIjoiY3VzdG9tZXJAYm9va2RlbGl2ZXJ5LmNvbSIsInVzZXJuYW1lIjoiY3VzdG9tZXJfMSIsInN1YiI6ImN1c3RvbWVyXzEiLCJpYXQiOjE2OTQ4ODkyNTMsImV4cCI6MTY5NDg4OTg1M30.UokFWxgZnSnYZsbAlwbfhQj1F54QrEOU5_5KzHyRmtY\" -T \"application/json\" -p post_data.json http://localhost:1221/api/v1/orders\n```\n\n### Swagger\n\n```\nhttp://localhost:1221/swagger-ui/index.html\n```\n\n### Prerequisites\n\n#### Define Variable in .env file\n\n```\nDATABASE_USERNAME={DATABASE_USERNAME}\nDATABASE_PASSWORD={DATABASE_PASSWORD}\n```\n\n---\n- Maven or Docker\n---\n\n\n### Docker Run\nThe application can be built and run by the `Docker` engine. The `Dockerfile` has multistage build, so you do not need to build and run separately.\n\nPlease follow directions shown below in order to build and run the application with Docker Compose file;\n\n```sh\n$ cd bookdelivery\n$ docker-compose up -d\n```\n\nIf you change anything in the project and run it on Docker, you can also use this command shown below\n\n```sh\n$ cd bookdelivery\n$ docker-compose up --build\n```\n\n---\n### Maven Run\nTo build and run the application with `Maven`, please follow the directions shown below;\n\n```sh\n$ cd bookdelivery\n$ mvn clean install\n$ mvn spring-boot:run\n```\n\n### Screenshots\n\n\u003cdetails\u003e\n\u003csummary\u003eClick here to show the screenshots of project\u003c/summary\u003e\n    \u003cp\u003e Figure 1 \u003c/p\u003e\n    \u003cimg src =\"screenshots/prometheues.PNG\"\u003e\n    \u003cp\u003e Figure 2 \u003c/p\u003e\n    \u003cimg src =\"screenshots/prometheues_1.PNG\"\u003e\n    \u003cp\u003e Figure 3 \u003c/p\u003e\n    \u003cimg src =\"screenshots/grafana_1.PNG\"\u003e\n    \u003cp\u003e Figure 4 \u003c/p\u003e\n    \u003cimg src =\"screenshots/grafana_2.PNG\"\u003e\n    \u003cp\u003e Figure 5 \u003c/p\u003e\n    \u003cimg src =\"screenshots/grafana_3.PNG\"\u003e\n    \u003cp\u003e Figure 6 \u003c/p\u003e\n    \u003cimg src =\"screenshots/grafana_4.PNG\"\u003e\n    \u003cp\u003e Figure 7 \u003c/p\u003e\n    \u003cimg src =\"screenshots/grafana_5.PNG\"\u003e\n    \u003cp\u003e Figure 8 \u003c/p\u003e\n    \u003cimg src =\"screenshots/grafana_6.PNG\"\u003e\n    \u003cp\u003e Figure 9 \u003c/p\u003e\n    \u003cimg src =\"screenshots/grafana_7.PNG\"\u003e\n    \u003cp\u003e Figure 10 \u003c/p\u003e\n    \u003cimg src =\"screenshots/grafana_8.PNG\"\u003e\n    \u003cp\u003e Figure 11 \u003c/p\u003e\n    \u003cimg src =\"screenshots/grafana_9.PNG\"\u003e\n\u003c/details\u003e\n\n\n### Contributors\n\n- [Sercan Noyan Germiyanoğlu](https://github.com/Rapter1990)\n- [Ahmet Aksünger](https://github.com/AhmetAksunger)\n- [Muhammet Oğuzhan Aydoğdu](https://github.com/moaydogdu)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frapter1990%2Fbookdelivery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frapter1990%2Fbookdelivery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frapter1990%2Fbookdelivery/lists"}