A professional full-stack Customer Management System implemented with:
- Java 8
- Spring Boot microservices
- MariaDB
- JUnit
- React JS
- Axios
- Maven
- Docker / Docker Compose
This project is built as a microservices-based platform with a modern React UI.
customer-service(port8081)- Customer CRUD
- Family-member relationship handling
- Address handling with city/country master references
- Internal bulk upsert API for import pipeline
import-service(port8082)- Receives
.xlsxuploads - Streams Excel parsing using Apache POI SAX/event model
- Batches records and forwards to
customer-service
- Receives
frontend(port5173via container port 80)- Dark-theme professional UI
- Create / Update customer
- View customer details
- Table view of customers
- Bulk import panel
mariadb(port3306)- Schema and master data bootstrap from SQL scripts
customer_management_platform/
backend/
pom.xml
customer-service/
import-service/
frontend/
database/
ddl/
dml/
docker-compose.yml
README.md
- API contract (OpenAPI):
docs/openapi.yaml - API contract (detailed guide):
docs/api-contract.md - Postman collection:
docs/postman/customer_management_platform.postman_collection.json - Postman environment:
docs/postman/customer_management_platform.postman_environment.json - Documentation index:
docs/README.md
A Customer has:
name(mandatory)dateOfBirth(mandatory)nicNumber(mandatory, unique)mobileNumbers(0..n)familyMembers(0..n, references other customers)addresses(0..n)addressLine1addressLine2cityCode/countryCode(master data backed)
Master data is stored in:
citiescountries
These are maintained in DB and not exposed as dedicated frontend screens.
- DDL:
database/ddl/01_schema.sql - DML:
database/dml/01_master_data.sql
The compose setup mounts these into MariaDB initialization directories.
cityCode and countryCode used by customer addresses must exist in the master tables.
Seeded by database/dml/01_master_data.sql:
| Type | Code | Name |
|---|---|---|
| Country | LK |
Sri Lanka |
| Country | IN |
India |
| Country | US |
United States |
| City | CMB |
Colombo |
| City | KDY |
Kandy |
| City | JFN |
Jaffna |
| City | BLR |
Bengaluru |
If an unknown cityCode or countryCode is sent, customer-service returns 400 Bad Request.
Base URL: http://localhost:8081
POST /api/customers- create customerPUT /api/customers/{id}- update customerGET /api/customers/{id}- view single customerGET /api/customers?page=0&size=20- paginated table list
POST /internal/customers/bulk-upsert
Payload:
{
"customers": [
{
"name": "John Doe",
"dateOfBirth": "1990-01-10",
"nicNumber": "NIC-10001"
}
]
}Base URL: http://localhost:8082
POST /api/import/customers?batchSize=1000(multipart form-data)- field:
file(.xlsx) - expected columns in first sheet:
namedate_of_birth(yyyy-MM-ddorM/d/yyyy)nic_number
- field:
Response example:
{
"rowsRead": 1000,
"rowsAccepted": 997,
"rowsRejected": 3,
"created": 900,
"updated": 97
}To keep memory usage stable and avoid request overload:
- Uses Apache POI event streaming parser (not full workbook object graph for reading)
- Processes rows in batches (
100to5000, default1000) - Sends chunked upsert calls to
customer-service - Uses configured HTTP connect/read timeouts between services
- Performs deduplicated NIC lookup in each upsert batch to reduce DB round trips
Recommended production hardening for very large files:
- Move to async job model (queue + job table + progress endpoint)
- Use gzip upload and object storage staging
- Add retry/backoff and idempotency keys
- Tune DB indexes and pool sizes for sustained throughput
cd /Users/nadeesha_medagama/IdeaProjects/customer_management_platform
docker compose up --build -dAccess:
- Frontend:
http://localhost:5173 - Customer API:
http://localhost:8081 - Import API:
http://localhost:8082 - MariaDB:
localhost:3306
Stop:
cd /Users/nadeesha_medagama/IdeaProjects/customer_management_platform
docker compose downUse three separate terminals so both backend services and the frontend run in parallel.
- MariaDB must be running on
localhost:3306. - Database
customer_dband user credentials must match the values below. - Schema and master data should be loaded from:
database/ddl/01_schema.sqldatabase/dml/01_master_data.sql
cd /Users/nadeesha_medagama/IdeaProjects/customer_management_platform/backend
export DB_URL="jdbc:mariadb://localhost:3306/customer_db"
export DB_USER="cmp_user"
export DB_PASSWORD="cmp_password"
mvn -pl customer-service spring-boot:runcd /Users/nadeesha_medagama/IdeaProjects/customer_management_platform/backend
export CUSTOMER_SERVICE_BULK_URL="http://localhost:8081/internal/customers/bulk-upsert"
mvn -pl import-service spring-boot:runcd /Users/nadeesha_medagama/IdeaProjects/customer_management_platform/frontend
npm install
npm run devAccess after startup:
- Frontend:
http://localhost:5173 - Customer API:
http://localhost:8081 - Import API:
http://localhost:8082
These tests verify critical backend contracts and data integrity guarantees, including:
- Required backend API routes in
docs/openapi.yaml - Mandatory customer request fields and bulk import limits
- Key SQL constraints in
database/ddl/01_schema.sql(NIC uniqueness, mandatory identity fields, family-link integrity) - Internal import-to-customer-service wiring in
docker-compose.yml
Run from repository root:
cd /Users/nadeesha_medagama/IdeaProjects/customer_management_platform
npm install
npm test- Backend unit/integration tests:
cd /Users/nadeesha_medagama/IdeaProjects/customer_management_platform/backend
mvn -q test- Frontend production build:
cd /Users/nadeesha_medagama/IdeaProjects/customer_management_platform/frontend
npm install --silent
npm run build --silent- Kept architecture as two backend microservices to separate core customer management from heavy file ingestion concerns.
- Used free and stable open-source dependencies only (Spring Boot, Apache POI, React, Axios, MariaDB).
- Added master-data based city/country references to minimize UI complexity and centralize consistency.
- Added internal bulk upsert endpoint to reduce DB calls for import operations.
- Delivered dark theme with a clean, professional UI layout and responsive behavior.
{
"name": "Nadeesha",
"dateOfBirth": "1995-06-20",
"nicNumber": "NIC-778899",
"mobileNumbers": ["+94771234567", "+94770000000"],
"familyMemberNics": ["NIC-123456"],
"addresses": [
{
"addressLine1": "No 12, Main Street",
"addressLine2": "Ward Place",
"cityCode": "CMB",
"countryCode": "LK"
}
]
}- For first-time family-member linking, create those referenced family customers first.
- Frontend supports selecting a customer from table and updating via same form.
- Import service supports create/update behavior by NIC match.
Use:
- Collection:
docs/postman/customer_management_platform.postman_collection.json - Environment:
docs/postman/customer_management_platform.postman_environment.json
- Method:
POST - URL:
{{customer_service_base}}/api/customers(orhttp://localhost:8081/api/customers) - Header:
Content-Type: application/json - Body (raw JSON):
{
"name": "Nadeesha",
"dateOfBirth": "1995-06-20",
"nicNumber": "NIC-778899",
"mobileNumbers": ["+94771234567", "+94770000000"],
"familyMemberNics": [],
"addresses": [
{
"addressLine1": "No 12, Main Street",
"addressLine2": "Ward Place",
"cityCode": "CMB",
"countryCode": "LK"
}
]
}Expected: 200 OK and response contains addresses[].cityCode/countryCode plus resolved names.
- Method:
GET - URL:
{{customer_service_base}}/api/customers?page=0&size=20
Check response content[] item for your nicNumber and verify:
addresses[].cityCode = CMBaddresses[].city = Colomboaddresses[].countryCode = LKaddresses[].country = Sri Lanka
Resend create request with invalid codes, for example cityCode: "XXX".
Expected: 400 Bad Request with an error message indicating invalid address master data.
This project is ready for local development and API verification with Postman using the documented master data codes.
For a smooth workflow:
- Start
customer-servicebeforeimport-service. - Keep DB seed data intact (
citiesandcountries) for address validation. - Use the provided Postman collection/environment for quick regression checks.
- Run backend and frontend tests before packaging or deployment.
Thank you for using the Customer Management Platform.
