Welcome to CarSharingApp! This is an API (backend service) for managing a city car sharing service. It allows users to register, browse available cars, rent and return cars, and pay for rentals. Administrators can manage cars, users, rentals, and monitor payments. The goal is to replace an outdated manual, paper-based process with a modern online system.
| Tool | Version | Purpose |
|---|---|---|
| Java | 17 | Programming language |
| Spring Boot | 3.5.4 | Main application framework |
| Spring Security | 6.5.2 | Security & Authentication (JWT) |
| Spring Data JPA | 3.5.2 | Database access layer |
| MySQL | 9.3.0 | Relational database |
| Liquibase | 4.31.1 | Database migrations |
| JJWT | 0.12.6 | JWT token management |
| Lombok | 1.18.38 | Boilerplate reduction |
| MapStruct | 1.5.5.Final | DTO <-> Entity mapping |
| OpenAPI (SpringDoc) | 2.8.14 | API documentation and UI |
| Checkstyle | 3.3.0 | Code style validation |
| Docker | 28.3.2 | Containerization |
| Testcontainers | 1.18.0 | Integration testing with Docker |
| JUnit 5 | 5.12.2 | Unit testing framework |
| Telegram Bots | 6.9.7.1 | Telegram integration |
| Stripe Java | 29.5.0 | Stripe Checkout integration |
| Apache Commons Lang | 3.20.0 | Utility helpers |
Here is a list of what you can do with the API, based on your role.
POST /auth/registration- Register a new userPOST /auth/login- Log in and receive a JWT access token
GET /cars- List available carsGET /cars/{id}- Get car detailsGET /rentals/my?is_active=...- List my rentals with optional active filterGET /rentals/my/{id}- Get my specific rentalPOST /rentals- Create a rental (decreases car inventory)GET /payments/my- List my paymentsPOST /payments- Create a payment session for a rental (Stripe)GET /payments/success?session_id=...- Success redirect handler for StripeGET /payments/cancel?session_id=...- Cancel redirect handler for Stripe
POST /cars- Add a new carPUT /cars/{id}- Update car info and inventoryDELETE /cars/{id}- Delete a carGET /users/me- View my profilePATCH /users/me- Update my profilePUT /users/{id}/role- Update user roleGET /rentals?userId={id}&is_active=...- View rentals for any user or all usersGET /rentals/{id}- Get any rental by IDPOST /rentals/{id}/return- Return a car (mark as completed)GET /payments- View all payments or filter byuserId
-
Car
- model: String
- brand: String
- type: Enum [SEDAN, SUV, HATCHBACK, UNIVERSAL]
- inventory: int
- dailyFee: decimal (USD)
-
User
- email: String
- firstName: String
- lastName: String
- password: String
- roles: Set [MANAGER, CUSTOMER]
-
Rental
- rentalDate: LocalDate
- returnDate: LocalDate
- actualReturnDate: LocalDate
- car: Car (Many-to-One)
- user: User (Many-to-One)
-
Payment
- status: Enum [PENDING, PAID]
- type: Enum [PAYMENT, FINE]
- rental: Rental (One-to-One)
- sessionUrl: String
- sessionId: String
- amountToPay: decimal (USD)
This project can be run in Docker. If you prefer, you can also run it locally with your own JDK and database. The steps below assume Docker.
Prerequisites:
- Git
- Docker
- Docker Compose
-
Clone the repository
git clone https://github.com/Rom-Cola/CarSharingApp.git cd CarSharingApp -
Configure environment variables
-
Copy
.env.templateto.envand fill in the values. -
Description of variables used by Docker Compose and Spring:
Variable Description Example MYSQLDB_ROOT_PASSWORDRoot password for MySQL service root_pass_123MYSQLDB_DATABASEApplication database name car_sharing_dbMYSQLDB_USERApplication DB username app_userMYSQLDB_PASSWORDApplication DB password app_user_passMYSQL_LOCAL_PORTHost port mapped to MySQL container 3306MYSQL_DOCKER_PORTMySQL port inside container (do not change) 3306SPRING_LOCAL_PORTHost port for the app 8088SPRING_DOCKER_PORTApp port inside container (do not change) 8080DEBUG_PORTRemote debug port exposed by the app container 5005JWT_SECRETSecret for signing JWT tokens long-random-string TELEGRAM_BOT_TOKENToken of your Telegram bot 12345:abc...TELEGRAM_BOT_USERNAMEUsername/handle of the bot my_bot_nameTELEGRAM_CHAT_IDTarget chat ID for notifications -1001234567890STRIPE_SECRET_KEYStripe secret API key sk_test_...
-
-
Package the Application into a .jar File: This is very important first step. Before Docker can build an image of your application, the application itself must be compiled and packaged into a
.jarfile.To do this, run the correct command for your operating system from the root folder of the project. You do not need to have Maven installed, as the project uses the Maven Wrapper (
mvnw).- Linux/macOS/Git Bash:
./mvnw clean package
- Windows CMD/PowerShell:
mvnw clean package
- Linux/macOS/Git Bash:
-
Build and Run the Application (Docker Compose): Use Docker Compose to build the images and start the containers. Ensure your
.envis present and configured before running the command below.docker-compose up --build
The first run may take a few minutes to pull base images and initialize MySQL.
-
Open API docs (Swagger)
- Once the app is running, open Swagger UI in your browser at:
http://localhost:<SPRING_LOCAL_PORT>/swagger-ui/index.html- Default example (if
SPRING_LOCAL_PORT=8088):http://localhost:8088/swagger-ui/index.html
-
Stop the application
docker-compose down
- Stateless authentication using JWT access tokens
- Role-based access control (CUSTOMER vs MANAGER)
- Sensitive configuration via environment variables, not committed to VCS
- Create payment sessions for rentals using Stripe Checkout
- Store
sessionUrlandsessionIdfor follow-up checks - Implement success and cancel redirect endpoints (
/payments/success,/payments/cancel) withsession_idquery param - For fines, compute the amount as: overdueDays × dailyFee × FINE_MULTIPLIER
- Send notifications to admins for:
- New rentals created
- Overdue rentals (scheduled daily check)
- Successful payments
- Daily job (cron
0 0 9 * * *) to detect overdue rentals and send Telegram notifications
- Unit Tests: JUnit + Mockito for service/business logic isolation
- Integration Tests: Testcontainers for controller and repository tests against real MySQL in Docker
- All tests are isolated
Run tests with Maven:
./mvnw test(or mvnw test on Windows)
In this project, I focused on four key challenges: implementing truly stateless security with JWT and clear roles (CUSTOMER, MANAGER);
integrating Stripe Checkout with reliable persistence of sessionUrl/sessionId and proper handling of success/cancel flows; setting up operational notifications via Telegram, including scheduled checks for overdue rentals;
and fully containerizing the development environment and database with Docker. Solving these made the API scalable, payment flows transparent, operationally observable, and local runs predictable and fast.
