Skip to content

PrashantVIT1/backend-order-service

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

132 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Backend Order Service

Java Spring Boot Build License: MIT Docker

A production-ready Spring Boot microservice designed to manage the lifecycle of orders in a distributed microservices architecture.
The service exposes RESTful APIs for creating, updating, retrieving, and deleting orders, and is fully containerized using Docker to ensure consistent behavior across development, testing, and deployment environments.

The application follows industry-standard layered architecture (Controller, Service, Repository) and is designed to be easily extensible for database integration, security, and cloud deployment. CI pipelines are configured using GitHub Actions to automate builds and ensure code quality.

Table of Contents

Architecture Overview

graph TD
    Client[Client / API Consumer]

    subgraph API Layer
        Controller[Order Controller]
        DTO[DTOs - Request / Response]
    end

    subgraph Business Layer
        Service[Order Service]
    end

    subgraph Data Layer
        Repository[Order Repository]
        DB[(PostgreSQL Database)]
    end

    Client -->|HTTP Request| Controller
    Controller -->|Request DTO| DTO
    DTO -->|Validated Data| Service
    Service -->|JPA Calls| Repository
    Repository -->|SQL Queries| DB
    Service -->|Response DTO| DTO
    DTO -->|HTTP Response| Client
Loading

The service follows a standard layered architecture:

  • Controller Layer
    Handles incoming HTTP requests and delegates processing to the service layer.

  • DTO Layer
    Defines request and response objects used to transfer data between the API layer and business layer.

  • Service Layer
    Contains the core business logic and orchestrates application workflows.

  • Repository Layer
    Manages persistence and database interaction using Spring Data JPA.

System Design Considerations

  • Stateless Service – allows horizontal scaling in containerized environments.
  • DTO Layer – prevents domain model leakage through API contracts.
  • Liquibase Migrations – ensures consistent database schema evolution.
  • Testcontainers Integration Tests – guarantees realistic database testing.
  • CI Pipeline – ensures build reliability and automated validation.

Key Highlights

  • RESTful APIs built with Spring Boot
  • Clean layered architecture (Controller, Service, Repository)
  • DTO-based API design for clear separation of concerns
  • PostgreSQL persistence with Liquibase database migrations
  • Containerized deployment using Docker
  • Integration testing using Testcontainers
  • CI pipeline implemented with GitHub Actions
  • OpenAPI/Swagger documentation for API exploration
  • Designed following microservices and cloud-ready best practices
  • JWT based authentication and authorization using Spring Security

Local Setup Instructions

1. Prerequisites

Ensure the following are installed:

  • Java 17
  • Maven
  • PostgreSQL
  • Docker (required for running integration tests using Testcontainers)

2. Database Setup

Create a PostgreSQL database:

  CREATE DATABASE orderdb;

No manual table creation is required. The database schema is automatically managed through Liquibase migrations during application startup.


3. Configure Database Credentials

Update your application.properties file:

    spring.datasource.url=${DB_URL:jdbc:mysql://localhost:3306/testdb}
    spring.datasource.username=${DB_USER:root}
    spring.datasource.password=${DB_PASSWORD:password}
    jwt.secret=${JWT_SECRET:dev-secret}

In production environments, credentials should be managed using environment variables or a secrets management service instead of hardcoding values.


4. Run the Application

Build and run the application:

  mvn clean install
  mvn spring-boot:run

The application will start at:

  http://localhost:8082

Swagger API documentation will be available at:

  http://localhost:8082/swagger-ui/index.html

5. Running Tests (Including Integration Tests)

To execute all unit and integration tests:

  mvn test

Integration tests use Testcontainers, which automatically:

  • Spins up a PostgreSQL Docker container
  • Applies Liquibase migrations
  • Tears down the container after execution.
  • Docker must be running locally for integration tests to execute successfully.

Tech Stack:

Category Technology
Language Java 17
Framework Spring Boot
Build Tool Maven
Database PostgreSQL
Testing JUnit5, Testcontainers
API Documentation Swagger / OpenAPI
Database Migration Liquibase
Containerization Docker, Docker Compose
CI/CD GitHub Actions
Code Quality SonarQube
API Testing Postman

Project Structure

backend-order-service/
└── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com.prashant.backendorderservice/
│   │   │       ├── auth/
│   │   │       │   ├── config/
│   │   │       │   │   ├── swagger/
│   │   │       │   │   │   └── AuthControllerDocs.java
│   │   │       │   │   ├── AppConfig.java
│   │   │       │   │   ├── OAuth2SuccessHandler.java
│   │   │       │   │   └── WebSecurityConfig.java
│   │   │       │   ├── controller/
│   │   │       │   │   └── AuthController.java
│   │   │       │   ├── dto/
│   │   │       │   │   ├── request/
│   │   │       │   │   │   └── LoginRequest.java
│   │   │       │   │   └── response/
│   │   │       │   │       ├── LoginResponse.java
│   │   │       │   │       └── SignupResponse.java
│   │   │       │   ├── entity/
│   │   │       │   │   ├── type/
│   │   │       │   │   │   └── AuthProvider.java
│   │   │       │   │   └── User.java
│   │   │       │   ├── exception/
│   │   │       │   │   ├── AuthExceptionHandler.java
│   │   │       │   │   ├── CustomAuthEntryPoint.java
│   │   │       │   │   ├── InvalidCredentialsException.java
│   │   │       │   │   └── UserAlreadyExistsException.java
│   │   │       │   ├── filter/
│   │   │       │   │   └── JwtAuthFilter.java
│   │   │       │   ├── repository/
│   │   │       │   │   └── UserRepository.java
│   │   │       │   ├── service/
│   │   │       │   │   ├── AuthService.java
│   │   │       │   │   └── CustomUserDetailsService.java
│   │   │       │   └── util/
│   │   │       │       └── AuthUtil.java
│   │   │       ├── orders/
│   │   │       │   ├── config/
│   │   │       │   │   └── swagger/
│   │   │       │   │       ├── OrderControllerDocs.java
│   │   │       │   │       └── UserOrderControllerDocs.java
│   │   │       │   ├── controller/
│   │   │       │   │   ├── OrderController.java
│   │   │       │   │   └── UserOrderController.java
│   │   │       │   ├── dto/
│   │   │       │   │   ├── request/
│   │   │       │   │   │   ├── CreateOrderRequest.java
│   │   │       │   │   │   └── UpdateOrderStatusRequest.java
│   │   │       │   │   └── response/
│   │   │       │   │       ├── OrderResponse.java
│   │   │       │   │       └── UpdateOrderStatusResponse.java
│   │   │       │   ├── entity/
│   │   │       │   │   ├── Order.java
│   │   │       │   │   └── OrderStatus.java          (enum)
│   │   │       │   ├── exception/
│   │   │       │   │   ├── custom/
│   │   │       │   │   │   ├── BusinessException.java
│   │   │       │   │   │   ├── OrderNotFoundException.java
│   │   │       │   │   │   └── OrderStatusInvalidException.java
│   │   │       │   │   └── OrdersExceptionHandler.java
│   │   │       │   ├── repository/
│   │   │       │   │   └── OrderRepository.java
│   │   │       │   ├── serializer/
│   │   │       │   │   └── OrderStatusDeserializer.java
│   │   │       │   └── service/
│   │   │       │       ├── OrderService.java
│   │   │       │       ├── OrderServiceOperations.java
│   │   │       │       ├── UsersOrderService.java
│   │   │       │       └── UsersOrderServiceOperations.java
│   │   │       ├── shared/
│   │   │       │   ├── config/
│   │   │       │   │   ├── exception/
│   │   │       │   │   │   └── ExceptionHandlerOrder.java
│   │   │       │   │   └── swagger/
│   │   │       │   │       ├── GlobalExceptionHandlerDocs.java
│   │   │       │   │       └── OpenApiConfig.java
│   │   │       │   ├── dto/
│   │   │       │   │   └── ErrorResponse.java
│   │   │       │   └── exception/
│   │   │       │       ├── GlobalExceptionHandler.java
│   │   │       │       └── RequestExceptionHandler.java
│   │   │       └── BackendOrderServiceApplication.java
│   │   └── resources/
│   │       ├── db.changelog/
│   │       │   ├── changes/
│   │       │   │   ├── 001-create-app-user-table.yaml
│   │       │   │   └── 001-create-orders-table.yaml
│   │       │   └── db.changelog-master.yaml
│   │       ├── application.yml
│   │       └── application.properties
│   └── test/
│       └── java/
│           └── com.prashant.backendorderservice/
│               ├── auth/
│               │   └── support/
│               │       ├── AuthenticatedE2ETest.java
│               │       └── SecuredControllerTest.java
│               ├── orders/
│               │   ├── controller/
│               │   │   ├── OrderControllerTest.java
│               │   │   └── UsersOrderControllerTest.java
│               │   ├── integration/
│               │   │   ├── OrderE2ETest.java
│               │   │   └── OrderRepositoryIntegrationTest.java
│               │   ├── repository/
│               │   │   └── OrderRepositoryTest.java
│               │   └── service/
│               │       ├── OrderServiceTest.java
│               │       └── UsersOrderServiceTest.java
│               └── BackendOrderServiceApplicationTests.java
│
├── pom.xml
└── README.md

CI/CD Workflow

CI/CD Workflow

Continuous Integration is implemented using GitHub Actions. The pipeline automatically:

  • Builds the application
  • Executes unit and integration tests
  • Performs static code analysis
  • Ensures code quality before merging changes

Swagger API documentation

Swagger UI: http://localhost:8082/swagger-ui/index.html

Swagger API documentation

Instructions to use JWT Token in swagger

  1. Create user by using

POST http://localhost:8082/auth/signup

image
  1. Go to

POST http://localhost:8082/auth/login

image

then copy this JWT token

image
  1. Now click on Authorize Button in the topleft corner
image

A popup will open. Paste JWT token here.

image
  1. Then click on Authorize
image
  1. Then this popup will open click on close
image
  1. Now all endpoints can be used.

  2. You can also logout. Click on Authorize and a popup opens. Then click here.

image

Endpoints

Error Response Format

All error responses follow a consistent structure for example:

{
  "timestamp": "2026-03-09T10:15:30",
  "status": 400,
  "error": "INVALID_ENUM_VALUE",
  "message": "Valid Order Status : CREATED, PROCESSING, SHIPPED, COMPLETED, CANCELLED",
  "path": "/orders/15/status"
}

In Detail

Authentication

Method Endpoint Status Code Description
POST /auth/signup 201 Create a new user
POST /auth/login 200 Login an existing user

POST http://localhost:8082/auth/signup

Request Body :

{
    "username":"praj12345",
    "password":"best_password_ever123"
}   
Status Code Reason
201 User created successfully
400 Empty Username/Password field
409 Use Different Username
500 INTERNAL SERVER ERROR

Response Body :

{
    "id": 25,
    "username": "praj12345"
}  

Example Reference:

image

POST http://localhost:8082/auth/login

Request Body :

{
  "username": "praj12345",
  "password": "best_password_ever123"
}   
Status Code Reason
200 User login successfully
400 Empty Username/Password field
401 Invalid username or password
500 INTERNAL SERVER ERROR

Response Body :

{
    "token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJwcmFqMTIzNDUiLCJ1c2VySWQiOiIyNSIsImlhdCI6MTc3MzY4MDIzNiwiZXhwIjoxNzczNjgwODM2fQ.8AW4aWZA1TcawmlieHuPdW8qgnjMcTuHJHMCpAvTgFN9SVwGWIo4UdHvJ6H7npkuXjueioksKpAVhHSsJsRulg",
    "userId": 25
} 

Example Reference:

image

> Note: All the protected endpoints needs access. To get the access authentication with JWT token is required

Steps to get the access

i) Login and copy the jwt token from response body

ii) Go to Header add JWT token in the given format below

Authorization : Bearer <token>
Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJwcmFqMTIzNDUiLCJ1c2VySWQiOiIyIiwiaWF0IjoxNzc0MTkzNzE3LCJleHAiOjE3NzQxOTQzMTd9.oi1EOu-L7AlMg7xC2pytzAwWai7K_As4BA-XD7QAG74uDKs5Q0oWcqWjEZoC7ZbqnGdsK6kucJyl8XiG66cacw

Orders

Method Endpoint Status Code Description
POST /user/orders 201 Create a new order
PATCH /user/orders/{id}/status 200 Update order status
GET /user/orders 200 Retrieve all the orders
GET /user/orders/{id} 200 Retrieve an order by ID
DELETE /user/orders/{id} 204 Delete an order
PATCH /admin/orders/{id}/status 200 Update order status
GET /admin/orders 200 Retrieve all the orders
GET /admin/orders/{id} 200 Retrieve an order by ID
DELETE /admin/orders/{id} 204 Delete an order

POST http://localhost:8082/user/orders

Request Body :

{
  "customerId": 14,
  "description": "Medicine and Hospital Equipment",
  "status": "CREATED"
}   
Status Code Reason
201 Order created successfully
400 Invalid request body / missing required fields

Response Body :

{
  "id": 15,
  "customerId": 14,
  "description": "Medicine and Hospital Equipment",
  "status": "CREATED"
}    

status is optional. Defaults to CREATED if not provided.

Example Reference:

POST method Postman

PATCH http://localhost:8082/admin/orders/{id}/status

Allowed Status Values:

    CREATED,
    PROCESSING,
    SHIPPED,
    COMPLETED,
    CANCELLED

Request Body :

{ 
      "status": "SHIPPED" 
} 
Status Code Reason
200 Status updated successfully
400 Invalid status value
404 Order not found with given ID

Response Body :

{
  "id": 15,
  "status": "SHIPPED",
  "updatedAt": "2026-02-06T17:28:06.2548106"
}   

Example Reference:

PATCH method Postman

GET http://localhost:8082/admin/orders

Status Code Reason
200 Order retrieved successfully

Response Body :

[
    {
      "id": 15,
      "customerId": 14,
      "description": "Medicine and Hospital Equipment",
      "status": "CREATED"
    }
]   

Example Reference:

image

GET http://localhost:8082/admin/orders/{id}

Status Code Reason
200 Order retrieved successfully
404 Order not found with given ID

Response Body :

{
  "id": 15,
  "customerId": 14,
  "description": "Medicine and Hospital Equipment",
  "status": "CREATED"
}    

Example Reference:

image

DELETE http://localhost:8082/admin/orders/{id}

Request Body :

Status Code Reason
204 Order deleted successfully
404 Order not found with given ID

Response Body :

      

Response Body is empty if no error.

Example Reference:

DELETE method Postman

Future Improvements

  • Introduce distributed tracing using OpenTelemetry
  • Implement event-driven communication using Kafka
  • Deploy using Kubernetes for scalable container orchestration
  • Add caching using Redis for improved performance

License

MIT © Prashant Raj

About

Backend Order Service is a Spring Boot microservice for managing order lifecycle operations. It exposes REST APIs using a clean layered architecture and is fully containerized with Docker. Includes GitHub Actions CI and is designed for real-world, production-ready microservices.

Resources

License

Code of conduct

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages