Banking Application using Spring boot Microservices
Create
one banking application with payment gateway aswell using springboot
microservices in detail CURD operations.
Here's
a detailed guide to building a Banking Application with a Payment Gateway
using Spring Boot Microservices. This project will involve multiple
microservices handling different functionalities such as user accounts,
transactions, and payment processing.
Project
Overview
Microservices
Involved:
- Account
Service -
Manages user accounts (CRUD operations).
- Transaction
Service -
Handles deposits, withdrawals, and transfers.
- Payment
Gateway Service
- Processes payments via an external gateway.
- API
Gateway - Routes
requests to respective services.
- Discovery
Service (Eureka)
- Enables service discovery.
Technology
Stack
- Spring
Boot
- Spring
Cloud (Eureka, API Gateway)
- Spring
Data JPA (MySQL)
- Spring
Security (JWT for authentication)
- Feign
Clients (for inter-service communication)
- Kafka
(for async communication)
- Docker
& Kubernetes (for deployment)
1.
Account Service (Manages User Accounts)
Endpoints:
Method |
Endpoint |
Description |
POST |
/accounts |
Create
a new account |
GET |
/accounts/{id} |
Get
account details |
PUT |
/accounts/{id} |
Update
account details |
DELETE |
/accounts/{id} |
Delete
an account |
Code
for Account Service
Entity:
Account.java
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public
class Account {
@Id
@GeneratedValue(strategy =
GenerationType.IDENTITY)
private Long id;
private String accountNumber;
private String accountHolder;
private double balance;
}
Repository:
AccountRepository.java
@Repository
public
interface AccountRepository extends JpaRepository<Account, Long> {
Optional<Account>
findByAccountNumber(String accountNumber);
}
Service:
AccountService.java
@Service
public
class AccountService {
@Autowired
private AccountRepository
accountRepository;
public Account createAccount(Account
account) {
return accountRepository.save(account);
}
public Account getAccount(Long id) {
return accountRepository.findById(id)
.orElseThrow(() -> new
RuntimeException("Account not found")); }
public void deleteAccount(Long id) {
accountRepository.deleteById(id);
}
}
Controller:
AccountController.java
@RestController
@RequestMapping("/accounts")
public
class AccountController {
@Autowired
private AccountService accountService;
@PostMapping
public ResponseEntity<Account>
createAccount(@RequestBody Account account) {
return
ResponseEntity.ok(accountService.createAccount(account));
}
@GetMapping("/{id}")
public ResponseEntity<Account>
getAccount(@PathVariable Long id) {
return
ResponseEntity.ok(accountService.getAccount(id));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void>
deleteAccount(@PathVariable Long id) {
accountService.deleteAccount(id);
return
ResponseEntity.noContent().build();
}
}
2.
Transaction Service (Deposits, Withdrawals, Transfers)
Endpoints:
Method |
Endpoint |
Description |
POST |
/transactions/deposit |
Deposit
amount into an account |
POST |
/transactions/withdraw |
Withdraw
amount from an account |
POST |
/transactions/transfer |
Transfer
money between accounts |
Transaction
DTO
@Data
public
class TransactionRequest {
private String fromAccount;
private String toAccount;
private double amount;
}
Transaction
Service
@Service
public
class TransactionService {
@Autowired
private AccountRepository
accountRepository;
@Transactional
public void
transferFunds(TransactionRequest request) {
Account sender =
accountRepository.findByAccountNumber(request.getFromAccount())
.orElseThrow(() -> new
RuntimeException("Sender account not found"));
Account receiver =
accountRepository.findByAccountNumber(request.getToAccount())
.orElseThrow(() -> new
RuntimeException("Receiver account not found"));
if (sender.getBalance() <
request.getAmount()) {
throw new
RuntimeException("Insufficient funds");
}
sender.setBalance(sender.getBalance() -
request.getAmount());
receiver.setBalance(receiver.getBalance() + request.getAmount());
accountRepository.save(sender);
accountRepository.save(receiver);
} }
Transaction
Controller
@RestController
@RequestMapping("/transactions")
public
class TransactionController {
@Autowired
private TransactionService
transactionService;
@PostMapping("/transfer")
public ResponseEntity<String>
transferFunds(@RequestBody TransactionRequest request) {
transactionService.transferFunds(request);
return ResponseEntity.ok("Transfer
successful");
}
}
3.
Payment Gateway Service
Endpoints:
Method |
Endpoint |
Description |
POST |
/payment/pay |
Process
a payment |
Feign
Client for External Payment Gateway
@FeignClient(name
= "external-payment", url =
"https://api.externalgateway.com")
public
interface PaymentGatewayClient {
@PostMapping("/process")
ResponseEntity<String>
processPayment(@RequestBody PaymentRequest request);
}
Payment
Service
@Service
public
class PaymentService {
@Autowired
private PaymentGatewayClient
paymentGatewayClient;
public String makePayment(PaymentRequest
request) {
ResponseEntity<String> response =
paymentGatewayClient.processPayment(request);
return response.getBody(); } }
Payment
Controller
@RestController
@RequestMapping("/payment")
public
class PaymentController {
@Autowired
private PaymentService paymentService;
@PostMapping("/pay")
public ResponseEntity<String>
processPayment(@RequestBody PaymentRequest request) {
return
ResponseEntity.ok(paymentService.makePayment(request));
}
}
4.
API Gateway (Spring Cloud Gateway)
- Routes
requests to respective services
- Handles
authentication (JWT Security)
Gateway
Configuration (application.yml)
spring:
cloud:
gateway:
routes:
- id: account-service
uri: lb://ACCOUNT-SERVICE
predicates:
- Path=/accounts/**
- id: transaction-service
uri: lb://TRANSACTION-SERVICE
predicates:
- Path=/transactions/**
- id: payment-service
uri: lb://PAYMENT-SERVICE
predicates:
- Path=/payment/**
5.
Service Discovery (Eureka)
Eureka
Server (EurekaApplication.java)
@SpringBootApplication
@EnableEurekaServer
public
class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
Eureka
Clients (application.yml)
eureka:
client:
serviceUrl:
defaultZone:
http://localhost:8761/eureka/
instance:
prefer-ip-address: true
Deployment
(Docker & Kubernetes)
- Dockerize
each service (Dockerfile)
FROM
openjdk:17
COPY
target/*.jar app.jar
ENTRYPOINT
["java", "-jar", "/app.jar"]
- Deploy
with Kubernetes (deployment.yaml)
apiVersion:
apps/v1
kind:
Deployment
metadata:
name: account-service
spec:
template:
spec:
containers:
- name: account-service
image: account-service:latest
Conclusion
✅
Fully functional banking system with payment integration
✅ Microservices
architecture with Eureka, API Gateway
✅ Security
via JWT Authentication
✅ Asynchronous
processing via Kafka
✅ Scalable
via Docker & Kubernetes
Kafka
notifications, Swagger API documentation, or Prometheus monitoring? 🚀
Great!
Let's enhance our Banking Application with Payment Gateway by adding the
following features:
- Kafka
Notifications -
Asynchronous event-driven communication for transactions.
- Swagger
API Documentation
- Easy-to-use API documentation.
- Prometheus
Monitoring & Grafana Dashboard - Metrics and visualization for performance
monitoring.
1.
Kafka Notifications for Transactions
Kafka
allows real-time event streaming. We will use it to publish transaction
events and notify users.
Step
1: Add Kafka Dependencies
Add
the following dependencies to your pom.xml for Kafka integration:
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
Step
2: Configure Kafka in application.yml
spring:
kafka:
bootstrap-servers: localhost:9092
producer:
key-serializer:
org.apache.kafka.common.serialization.StringSerializer
value-serializer:
org.apache.kafka.common.serialization.StringSerializer
consumer:
group-id: banking-app-group
auto-offset-reset: earliest
key-deserializer:
org.apache.kafka.common.serialization.StringDeserializer
value-deserializer:
org.apache.kafka.common.serialization.StringDeserializer
Step
3: Create a Kafka Producer in Transaction Service
@Service
public
class TransactionService {
@Autowired
private KafkaTemplate<String, String>
kafkaTemplate;
public void
transferFunds(TransactionRequest request) {
// Logic for fund transfer (same as
before)
// Publish event to Kafka
kafkaTemplate.send("transaction-events",
"Transaction from " +
request.getFromAccount() + " to " + request.getToAccount() +
" of amount $" +
request.getAmount());
}
}
Step
4: Create a Kafka Consumer (Notification Service)
@Component
@KafkaListener(topics
= "transaction-events", groupId = "banking-app-group")
public
class NotificationService {
@KafkaHandler
public void consumeTransactionEvents(String
eventMessage) {
System.out.println("Notification
Received: " + eventMessage);
}
}
✅
Now, each transaction will trigger a Kafka event and notify users
asynchronously.
2.
Swagger API Documentation
Swagger
provides interactive API documentation via SpringDoc OpenAPI.
Step
1: Add Swagger Dependency
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.2.0</version>
</dependency>
Step
2: Enable Swagger in application.yml
springdoc:
swagger-ui:
path: /swagger-ui.html
Step
3: Add API Documentation to Controllers
Annotate
your controllers with Swagger documentation:
@Tag(name
= "Transaction Service", description = "Handles transactions
between accounts")
@RestController
@RequestMapping("/transactions")
public
class TransactionController {
@Operation(summary = "Transfer funds
between accounts")
@PostMapping("/transfer")
public ResponseEntity<String>
transferFunds(@RequestBody TransactionRequest request) {
transactionService.transferFunds(request);
return ResponseEntity.ok("Transfer
successful");
}
}
Step
4: Access Swagger UI
- Run
the application and open:
http://localhost:8080/swagger-ui.html
✅
Now you have an interactive UI to test APIs and view request/response
models.
3.
Prometheus & Grafana Monitoring
Prometheus
monitors CPU usage, memory, transaction count, etc., and Grafana
visualizes the data.
Step
1: Add Prometheus Dependencies
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
Step
2: Enable Prometheus in application.yml
management:
endpoints:
web:
exposure:
include:
"prometheus,health,metrics"
metrics:
tags:
application: "banking-app"
Step
3: Add Custom Metrics in Transaction Service
@Autowired
private
MeterRegistry meterRegistry;
public
void transferFunds(TransactionRequest request) {
transferCount.increment();
meterRegistry.counter("transaction.success.count").increment();
}
Step
4: Run Prometheus in Docker
Create
a prometheus.yml config file:
global:
scrape_interval: 5s
scrape_configs:
- job_name: "banking-app"
metrics_path:
"/actuator/prometheus"
static_configs:
- targets: ["localhost:8080"]
Run
Prometheus:
docker
run -d --name=prometheus -p 9090:9090 -v
$(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
Step
5: Run Grafana
docker
run -d -p 3000:3000 --name=grafana grafana/grafana
- Open http://localhost:3000
(Default Login: admin/admin)
- Add Prometheus
as a data source (http://localhost:9090).
- Create
dashboards for CPU, Memory, Transactions.
✅
Now, you can monitor and visualize system health in Grafana!
Final
Microservices Architecture
┌──────────────────────────┐
│ API Gateway │
└──────────────────────────┘
│
───────────────────────────────────────
│ │ │
▼ ▼ ▼
┌────────────┐ ┌──────────────┐ ┌──────────────┐
│
AccountSvc │ │ TransactionSvc│ │ PaymentSvc │
└────────────┘ └──────────────┘ └──────────────┘
│
┌────────────────────┐
│ Kafka (Event
Bus) │
└────────────────────┘
│
┌────────────────┐
│ NotificationSvc │
└────────────────┘
│
┌───────────────┬───────────────┐
│ │ │
┌──────────┐
┌──────────────┐ ┌──────────┐
│ Prometheus │ │ Grafana (UI) │ │ Swagger UI│
└──────────┘
└──────────────┘ └──────────┘
Summary
of Added Features
✅
Kafka Event-Driven Transactions - Asynchronous processing &
notifications.
✅ Swagger
API Documentation - Interactive API testing.
✅ Prometheus
& Grafana - Real-time system monitoring.
Deploy
this project on AWS with CI/CD pipeline using Jenkins & Kubernetes? 🚀
Deploying
the Banking Application on AWS with CI/CD Pipeline (Jenkins + Kubernetes)
Now,
let's take the Banking Microservices Application and deploy it on AWS
using Jenkins for CI/CD and Kubernetes for orchestration.
1.
Setting Up AWS Infrastructure
Step
1: Provision AWS Resources
We
need the following AWS services:
- EC2 - To run Jenkins and Kubernetes
cluster (EKS).
- EKS
(Elastic Kubernetes Service)
- To manage Kubernetes deployments.
- RDS
(MySQL/PostgreSQL)
- For database storage.
- S3
Bucket - For
storing artifacts (optional).
- IAM
Roles - For
granting permissions.
Step
2: Install AWS CLI & Kubectl
On
your local machine or AWS EC2 instance:
#
Install AWS CLI
curl
"https://awscli.amazonaws.com/AWSCLIV2.pkg" -o
"AWSCLIV2.pkg"
sudo
installer -pkg AWSCLIV2.pkg -target /
#
Install Kubectl
curl
-LO "https://dl.k8s.io/release/$(curl -L -s
https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod
+x kubectl
sudo
mv kubectl /usr/local/bin/
Step
3: Set Up Kubernetes Cluster (EKS)
aws
eks --region us-east-1 create-cluster --name banking-cluster --role-arn
arn:aws:iam::123456789012:role/EKSRole
2.
Dockerizing Microservices
Each
microservice must be containerized using Docker.
Step
1: Create a Dockerfile for Account Service
FROM
openjdk:17
COPY
target/account-service.jar account-service.jar
ENTRYPOINT
["java", "-jar", "/account-service.jar"]
Step
2: Build & Push Docker Image to AWS ECR
#
Login to AWS ECR
aws
ecr get-login-password --region us-east-1 | docker login --username AWS
--password-stdin <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com
#
Build Docker image
docker
build -t account-service .
#
Tag and push to ECR
docker
tag account-service:latest
<AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/account-service
docker
push <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/account-service
🔹 Repeat this process for all microservices
(Transaction, Payment, etc.)
3.
Kubernetes Deployment Configuration
Each
microservice needs a Deployment and Service YAML file.
Step
1: Create account-deployment.yaml
apiVersion:
apps/v1
kind:
Deployment
metadata:
name: account-service
spec:
replicas: 2
selector:
matchLabels:
app: account-service
template:
metadata:
labels:
app: account-service
spec:
containers:
- name: account-service
image:
<AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/account-service:latest
ports:
- containerPort: 8081
---
apiVersion:
v1
kind:
Service
metadata:
name: account-service
spec:
selector:
app: account-service
ports:
- protocol: TCP
port: 80
targetPort: 8081
type: LoadBalancer
Step
2: Apply Kubernetes Config
kubectl
apply -f account-deployment.yaml
🔹 Repeat this process for all microservices.
4.
Setting Up CI/CD Pipeline with Jenkins
Step
1: Install Jenkins on AWS EC2
sudo
yum update -y
sudo
yum install -y java-17-amazon-corretto
sudo
wget -O /etc/yum.repos.d/jenkins.repo
https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo
yum install -y jenkins
sudo
systemctl enable jenkins
sudo
systemctl start jenkins
🔹 Access Jenkins at
http://<EC2-PUBLIC-IP>:8080
Step
2: Install Required Jenkins Plugins
- Pipeline
- Git
- Docker
Pipeline
- Kubernetes
CLI
- Amazon
ECR Plugin
Step
3: Create a Jenkins Pipeline (Jenkinsfile)
pipeline
{
agent any
environment {
AWS_ACCOUNT_ID = '123456789012'
REGION = 'us-east-1'
REPO_NAME = 'account-service'
}
stages {
stage('Clone Repository') {
steps {
git
'https://github.com/your-repo/banking-app.git'
}
}
stage('Build & Test') {
steps {
sh 'mvn clean package'
}
}
stage('Docker Build & Push') {
steps {
sh 'docker build -t
$AWS_ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:latest .'
sh 'aws ecr get-login-password
--region $REGION | docker login --username AWS --password-stdin
$AWS_ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com'
sh 'docker push
$AWS_ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:latest'
}
}
stage('Deploy to Kubernetes') {
steps {
sh 'kubectl apply -f
k8s/account-deployment.yaml'
}
}
}
}
Step
4: Configure Webhook (GitHub Actions or BitBucket)
- Go
to GitHub Repository → Settings → Webhooks
- Add
Jenkins URL (http://<EC2-PUBLIC-IP>:8080/github-webhook/)
5.
Monitoring with Prometheus & Grafana
Step
1: Deploy Prometheus on Kubernetes
Create
prometheus-deployment.yaml:
apiVersion:
v1
kind:
Service
metadata:
name: prometheus
spec:
selector:
app: prometheus
ports:
- protocol: TCP
port: 9090
---
apiVersion:
apps/v1
kind:
Deployment
metadata:
name: prometheus
spec:
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
containers:
- name: prometheus
image: prom/prometheus
ports:
- containerPort: 9090
kubectl
apply -f prometheus-deployment.yaml
Step
2: Deploy Grafana
kubectl
create deployment grafana --image=grafana/grafana
kubectl
expose deployment grafana --type=LoadBalancer --port=3000
🔹 Access Grafana at
http://<LoadBalancer-IP>:3000
Final
CI/CD Flow
1️⃣ Developer pushes code to GitHub
2️⃣ GitHub
Webhook triggers Jenkins
3️⃣ Jenkins
pulls code, builds, tests, and pushes Docker images to ECR
4️⃣ Jenkins
deploys new images to Kubernetes
5️⃣ Prometheus
& Grafana monitor services
🎯 Key Benefits
✅
AWS Scalable Deployment via Kubernetes (EKS)
✅ Automated
CI/CD Pipeline with Jenkins & Docker
✅ Microservices
Communication via Eureka & API Gateway
✅ Asynchronous
Event Processing via Kafka
✅ Real-time
Monitoring via Prometheus & Grafana
No comments:
Post a Comment