⬡ Hub
Skip to content

java

Java Microservices Project

This project demonstrates a simple microservices architecture implemented in Java using Spring Boot. It consists of four services:

  1. User Service: Manages user-related data.
  2. Product Service: Manages product-related data.
  3. Order Service: Handles order creation and management, demonstrating service-to-service communication with User and Product services.
  4. Notification Service: A placeholder service for sending notifications.

Architecture Overview

The architecture is based on a set of independently deployable services that communicate with each other.

+-------------------+       +-------------------+
|   User Service    |<----->|   Order Service   |
| (Port 8080)       |       | (Port 8082)       |
+-------------------+       +-------------------+
                            ^
                            |
                            v
+-------------------+       +-------------------+
|  Product Service  |<----->|   Order Service   |
| (Port 8081)       |       | (Port 8082)       |
+-------------------+       +-------------------+
                            ^
                            |
                            v
+-------------------+
| Notification Svc  |
| (Port 8083)       |
+-------------------+

Service-to-Service Communication

In a Kubernetes environment, service-to-service communication is facilitated by Kubernetes DNS. Each Service resource in Kubernetes gets a DNS name (e.g., user-service, product-service). Other services within the same Kubernetes cluster can resolve these DNS names to the respective service's ClusterIP, allowing them to communicate without needing to know the exact IP addresses.

For example, the Order Service communicates with the User Service and Product Service using their Kubernetes service names:

  • http://user-service:8080/users/{userId}
  • http://product-service:8081/products/{productId}

The port numbers (8080, 8081) correspond to the targetPort defined in each service's Kubernetes Service manifest.

Services Details

Maven Project Structure (POMs)

Each microservice in this Java project is an independent Maven project with its own pom.xml. These pom.xml files inherit from the spring-boot-starter-parent, which provides sensible defaults for Spring Boot applications. This approach allows for independent development, building, and deployment of each service.

1. User Service

  • Functionality: Provides REST endpoints for managing users.
  • Technology: Spring Boot
  • Endpoints:
    • GET /users: Get all users.
    • GET /users/{id}: Get user by ID.
  • Port: 8080

2. Product Service

  • Functionality: Provides REST endpoints for managing products.
  • Technology: Spring Boot
  • Endpoints:
    • GET /products: Get all products.
    • GET /products/{id}: Get product by ID.
  • Port: 8081

3. Order Service

  • Functionality: Handles order creation and retrieval. Demonstrates calling other microservices.
  • Technology: Spring Boot (using WebClient for HTTP calls)
  • Endpoints:
    • GET /orders: Get all orders.
    • GET /orders/{id}: Get order by ID.
    • GET /orders/create/{userId}/{productId}/{quantity}: Create a dummy order and call User/Product services.
  • Port: 8082

4. Notification Service

  • Functionality: A simple service to simulate sending notifications.
  • Technology: Spring Boot
  • Endpoints:
    • POST /notifications/send: Send a notification.
  • Port: 8083

Setup and Local Development

  1. Prerequisites:

    • Java 11 or higher
    • Maven
    • Docker
    • Kubernetes cluster (e.g., Minikube, Docker Desktop Kubernetes)
    • kubectl configured to connect to your cluster
  2. Build Services: Navigate to each service directory (user-service, product-service, order-service, notification-service) and run: bash mvn clean install This will build the JAR files for each service and run unit tests.

  3. Build Docker Images: From the root of each service directory, build the Docker image. Replace your-docker-registry with your actual Docker registry (e.g., myusername for Docker Hub). bash docker build -t your-docker-registry/user-service:0.0.1-SNAPSHOT . docker build -t your-docker-registry/product-service:0.0.1-SNAPSHOT . docker build -t your-docker-registry/order-service:0.0.1-SNAPSHOT . docker build -t your-docker-registry/notification-service:0.0.1-SNAPSHOT . Then push them to your registry: bash docker push your-docker-registry/user-service:0.0.1-SNAPSHOT docker push your-docker-registry/product-service:0.0.1-SNAPSHOT docker push your-docker-registry/order-service:0.0.1-SNAPSHOT docker push your-docker-registry/notification-service:0.0.1-SNAPSHOT Note: Update the image field in the kubernetes/deployment.yaml files for each service to point to your pushed images (e.g., image: your-docker-registry/user-service:0.0.1-SNAPSHOT).

  4. Deploy to Kubernetes: Apply the Kubernetes manifests for each service. You can do this individually or create a script. bash kubectl apply -f user-service/kubernetes/deployment.yaml kubectl apply -f user-service/kubernetes/service.yaml kubectl apply -f product-service/kubernetes/deployment.yaml kubectl apply -f product-service/kubernetes/service.yaml kubectl apply -f order-service/kubernetes/deployment.yaml kubectl apply -f order-service/kubernetes/service.yaml kubectl apply -f notification-service/kubernetes/deployment.yaml kubectl apply -f notification-service/kubernetes/service.yaml

  5. Access Services: Since all services are ClusterIP type, they are only accessible within the cluster. To access them from outside (e.g., for testing), you can use kubectl port-forward or set up an Ingress controller.

    Example for user-service: bash kubectl port-forward service/user-service 8080:8080 Then access http://localhost:8080/users in your browser.

CI/CD with Jenkins

Two Jenkinsfiles are provided:

  1. Jenkinsfile (Standard CI/CD Pipeline): This file defines a Jenkins Pipeline that automates the build, Docker image creation, and deployment to Kubernetes for all services. The pipeline includes the following stages:

    • Unit Tests: Runs mvn test for each service.
    • SonarQube Analysis: Performs static code analysis using SonarQube for each service. The pipeline is configured to continue even if the SonarQube quality gate fails, marking the build as UNSTABLE.
    • Package and Docker Build: Builds the JAR files and Docker images for each service.
    • Deploy to Kubernetes: Applies the Kubernetes manifests to deploy the services.
  2. Jenkinsfile.devsecops (DevSecOps Pipeline): This file extends the standard CI/CD pipeline by integrating additional security checks. The pipeline includes the following stages:

    • Unit Tests: Runs mvn test for each service.
    • Static Application Security Testing (SAST) - SonarQube: Performs static code analysis including security vulnerability detection using SonarQube.
    • Dependency Vulnerability Scanning (SCA): Scans project dependencies for known vulnerabilities using OWASP Dependency-Check. The pipeline is configured to continue even if vulnerabilities are found, marking the build as UNSTABLE.
    • Package and Docker Build: Builds the JAR files and Docker images for each service.
    • Container Image Scanning: Scans Docker images for vulnerabilities using Trivy. The pipeline is configured to continue even if vulnerabilities are found, marking the build as UNSTABLE.
    • Deploy to Kubernetes: Applies the Kubernetes manifests to deploy the services.

Steps to use the Jenkinsfile:

  1. Configure a Jenkins server with Docker and Kubernetes plugins.
  2. Ensure kubectl is configured on the Jenkins agent to access your Kubernetes cluster.
  3. Configure SonarQube integration in Jenkins (e.g., install SonarQube Scanner, configure SonarQube server connection).
  4. For Jenkinsfile.devsecops, ensure dependency-check-maven plugin is configured in pom.xml (or manually run) and Trivy is installed on the Jenkins agent.
  5. Create a new Pipeline job in Jenkins.
  6. Configure the job to use "Pipeline script from SCM" and point it to this repository, specifying either Jenkinsfile or Jenkinsfile.devsecops as the script path.
  7. Run the Jenkins job. It will execute the stages defined in the selected Jenkinsfile.

Important: Remember to replace your-docker-registry in the Jenkinsfile(s) and Kubernetes manifests with your actual Docker registry. Also, ensure your Jenkins setup has the necessary SonarQube credentials (sonarqube-token) and SONAR_SCANNER_HOME tool configured.

Files and Subdirectories