The service accepts two types of transactions:
-
Loads: Add money to a user (credit)
-
Authorizations: Conditionally remove money from a user (debit)
Every load or authorization PUT should return the updated balance following the transaction. Authorization declines should be saved, even if they do not impact balance calculation.
This section covers the steps required to get the project up and running on your local machine for development and testing purposes.
Before proceeding, ensure you have the following installed:
- MySQL.
- Java JDK 17 or higher: Necessary to run Java applications. You can download it from Oracle's website or use OpenJDK.
- Maven 4.0 or higher: Required for managing the project's build. Download and installation instructions can be found on the Apache Maven Project website.
To start, clone the project repository from GitHub to your local machine. Alternatively, navigate to the project folder and open a terminal.
git clone https://github.com/tranhlok/bank-balance.git
cd bank-balance-backend
sudo service mysql start
Run the mysql_secure_installation script from the command line. Pick your username and password for the server.
sudo mysql_secure_installation
Open the MySQL shell or MySQL Workbench and create a new database for your project:
CREATE DATABASE your_database_name;
USE your_database_name;
Update your application’s configuration files (application.properties) to point to your MySQL server. Replace your_database_name, your_username, and your_password with the previously configured values.
spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
This command also run the unit tests.
mvn clean install
mvn spring-boot:run
The project is structured as a Spring Boot application, utilizing Maven for dependency management and build configuration (pom.xml). The application is configured with Spring MVC to handle HTTP requests and uses Spring Data JPA for data persistence.
- AccountController.java: Manages API requests related to bank accounts such as creating and retrieving accounts.
- TransactionController.java: Handles transactions, including creating and fetching transaction data.
- PingController.java: A simple controller to check the health of the service.
- Account.java: Represents the bank account with attributes like id, balance, and account type.
- Transaction.java: Represents a transaction, detailing attributes such as amount, transaction type, and associated account.
- AccountRepository.java: Interface for database operations related to the Account entity.
- TransactionRepository.java: Interface for handling the persistence of Transaction entities.
- AccountService.java and TransactionService.java: These services handle the business logic for account and transaction operations respectively.
- WebSecurityConfig.java: Configures web security, likely managing authentication and authorizing access to various parts of the application.
- LoginRequest.java and UserResponse.java: These classes are used for handling data exchange in user authentication processes.
- service.yml: Contains application configurations and service definitions, possibly defining properties like server port or database configurations.
- RESTful API Design: The controllers expose RESTful endpoints for managing accounts and transactions, providing a clear interface for front-end services or external applications.
- Security: Implementation of security protocols to ensure that endpoints are protected against unauthorized access.
- Data Persistence: Utilizes JPA repositories for robust data handling and operations, allowing easy integration with relational databases.
The security of the application is managed using Spring Security with JWT (JSON Web Tokens) for authentication and authorization. This ensures secure access to the application's resources.
- WebSecurityConfig.java: Configures security settings, including URL access rules, and integrates the JWT authentication filter.
- JwtAuthenticationEntryPoint.java: Handles what happens if authentication fails (for example, returning a 401 unauthorized error to users who try to access a protected resource without credentials).
- JwtAuthenticationFilter.java: Intercepts requests to read JWTs from headers, validate them, and set up security context if the token is valid. This filter ensures that every secure endpoint is accessed with a valid token.
- JwtTokenUtil.java: Utility class to generate, parse, and validate JWT tokens. It includes methods for extracting username, expiration date from the token, and checking its expiration.
- Authentication: When users log in, JwtTokenUtil generates a token that encapsulates user credentials and is returned to the user.
- Authorization: For each request, JwtAuthenticationFilter checks the presence of a valid JWT in the request header, validates it, and allows the request to proceed if the token is valid.
- Exception Handling: JwtAuthenticationEntryPoint handles exceptions when a request lacks a valid authentication token, ensuring that unauthenticated requests do not proceed.
- These components are tightly integrated with the rest of the application, ensuring that security is maintained at all layers and that interactions with critical endpoints such as those handled by AccountController and TransactionController are secure.
The application uses Spring Data JPA for managing data persistence, which simplifies the interaction with the database by abstracting boilerplate CRUD operations and providing a more intuitive way of handling data.
- The application uses Spring Data JPA repositories to abstract and encapsulate database access. This allows the service to focus on business logic and service delivery rather than database connectivity and query details.
- Account.java: Represents the account entity with attributes such as account ID, balance, and account type. This class is annotated with JPA annotations to define the table mapping (@Entity), primary key (@Id), and column mappings (@Column).
- Transaction.java: Defines the transaction entity which includes details like transaction amount, type, and the associated account. Similar to Account, this entity is mapped to a database table with appropriate JPA annotations. Repositories
- AccountRepository.java: Extends JpaRepository, providing CRUD operations for Account entities. It leverages JPA to automatically generate queries based on method names, such as findAll(), findById(), etc.
- TransactionRepository.java: Similar to AccountRepository, it provides automated CRUD operations for Transaction entities, simplifying the management of transaction data.
- Data Source Configuration: In application.properties, where database connection settings such as URL, username, and password are specified.
- Spring Data Configuration: In CurrentBankingServiceApplication.java or through configuration files, where @EnableJpaRepositories is likely used to enable JPA repository support and @EntityScan to specify the packages to scan for entity classes.
- Spring Data JPA integrates seamlessly with Spring's transaction management. It uses @Transactional annotations to define the scope and boundary of transactions at the repository or service layer, ensuring data consistency and integrity.
- Reduced Boilerplate Code: Automatic repository implementation significantly reduces the need for explicit SQL.
- Easy to Extend: Adding new entities and repositories can be done with minimal configuration.
- Strong Integration: Works well with other parts of the Spring ecosystem, such as Spring Security and Spring MVC, providing a unified framework experience.
After initializing the database and maven build, we can go ahead and test the project in Postman
Register for an account by sending a POST request to url: http://localhost:8080/api/accounts/login. Send the following in the body, replace name and password
{
"name": "testing",
"password": "xxx"
}
It will return an account number if the name is valid, as seen below:
{
"name": "testing",
"accountNumber": "ACCT-1714675480013"
}
Login into an account by sending a POST request to url: http://localhost:8080/api/accounts/login We can use the account number and name from last request in the body to login, use the same password as before.
{
"accountNumber": "ACCT-1714675480013",
"password": "xxx"
}
It will return a bearer token like the following:
{
"token": "TokenValue"
}
url: http://localhost:8080/api/transactions/deposit . Add the token above to Authorization -> bearer token in postman. send a simple amount like:
{
"amount" : 200
}
url: http://localhost:8080/api/transactions/deposit . Add the token above to Authorization -> bearer token in postman. send a simple amount
{
"amount" : 200
}
it will return Withdrawal successful when there is enough money to execute the command.
- Cloud Hosting Platform: Utilize a major cloud provider like AWS, Azure, or Google Cloud for hosting the application with services tailored to web applications and databases.
- Containerization: Package the application into Docker containers for consistency across development, testing, and production environments.
- Orchestration with Kubernetes: Manage and scale the containerized application automatically using Kubernetes, taking advantage of its load balancing, auto-scaling, and self-healing features.
- CI/CD Pipeline: Implement a CI/CD workflow with Jenkins, GitHub Actions, or GitLab CI to automate building, testing, and deploying the application.
- Monitoring and Logging: Use tools like Prometheus and Grafana for monitoring, and ELK stack or cloud-native solutions for logging, to keep track of the application’s performance and health.
- Security Measures: Ensure all communication is encrypted and manage access using IAM roles, alongside regular updates and security patches to safeguard the application.
Speical thanks to Dang Duong
(
)\ ) * )
(()/( ` ) /(( )
/(_)) ( ( ( )(_))( ( /( (
(_)) )\ )\ (_(_()|()\ )(_)) )\ )
| | ((_) ((_) |_ _|((_|(_)_ _(_/(
| |__/ _ \/ _| | | | '_/ _` | ' \))
|____\___/\__| |_| |_| \__,_|_||_|