Wednesday, April 9, 2025

Banking Application using Spring boot Microservices

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:

  1. Account Service - Manages user accounts (CRUD operations).
  2. Transaction Service - Handles deposits, withdrawals, and transfers.
  3. Payment Gateway Service - Processes payments via an external gateway.
  4. API Gateway - Routes requests to respective services.
  5. 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:

  1. Kafka Notifications - Asynchronous event-driven communication for transactions.
  2. Swagger API Documentation - Easy-to-use API documentation.
  3. 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

  1. Open http://localhost:3000 (Default Login: admin/admin)
  2. Add Prometheus as a data source (http://localhost:9090).
  3. 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

Java 9 and Java11 and Java17, Java 21 Features

 Java 9 and Java11 and Java17 features along with explanation and examples in realtime scenarios Here's a detailed breakdown of Java 9, ...