CRUD Operations in Microservices: Customer, Grocery, and Business Services ๐
Are you ready to embark on a journey to create a cutting-edge grocery business application using microservices architecture? You're in the right place! In this blog post, we will guide you through the process of building a microservices-based grocery business application, complete with three essential components: Customer, Grocery, and Business Services. But wait, that's not all โ we'll also unveil the magic behind order placements. Get ready to explore the world of CRUD operations and more!
Introduction
Picture this: You're on a mission to create an application that simplifies grocery shopping for your customers. The solution? Microservices! ๐๏ธ We'll break down this project into three mighty microservices: Customer, Grocery, and Business. These services will handle the CRUD (Create, Read, Update, Delete) operations for their respective entities. But that's not all โ we'll also unveil the art of order placement, allowing your customers to shop with ease.
Before starting if you are completely new to backend web development I would recommend you to start with the CRUD application, you can find my blog for the same.
Setting Up the Environment ๐
Let's start by gathering our tools and setting up your development environment. Here's what you need:
Programming Language: Choose your preferred language (e.g., JavaScript, Python, Java).
Frameworks: Select appropriate frameworks like Express.js, Flask, or Spring Boot.
Database: Pick a database engine that suits your needs (e.g., MongoDB, PostgreSQL, MySQL).
API Gateway: Consider using an API Gateway like Nginx or Kong for managing API requests.
Now that your environment is ready, let's dive into the code blocks for creating CRUD applications for each microservice.
Customer Service: Creating Customers ๐งโ๐คโ๐ง
In this section, we'll focus on the Customer microservice.
We will be following the MVC pattern for this application. Sharing an example:
In this, the customer's folder is a perfect example of the MVC pattern.
Customer Schema
In this code block, we define the schema for the Customer microservice using Mongoose, a popular Node.js library for MongoDB. The schema specifies the structure of customer documents, including fields like CustomerName
, CustomerBusiness
, and quantity
.
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const custModel = new Schema ({
customerName: {
type: String,
required: true,
},
customerOrder: {
type: String,
required: true
},
Quantity: {
type: Number,
required: true
}
}, {timestamps: true})
module.exports = mongoose.model('Customer', custModel)
Customer Controller
In this code block, we define the controller for the Customer microservice. It contains functions to handle CRUD operations such as creating, reading, updating, and deleting customer records.
const express = require('express')
const {default: mongoose} = require('mongoose')
const Customer1 = require('../Models/custSchema')
const getCustomer = async (req,res) => {
try{
const customer = await Customer1.find({}).sort({ createdAt: -1})
res.status(200).json(customer)
}
catch(error) {
return res.status(400).json(error)
//console.log(error)
}
}
const getSingleCustomer = async (req,res) => {
const { id } = req.params
if(!mongoose.Types.ObjectId.isValid(id))
{
return res.status(400).json({Error: 'Not a vlaid DB id.'})
}
const customer = await Customer1.findById(id)
if(!customer)
{
return res.status(404).json({Error: 'No such customer available'})
}
res.status(200).json(customer)
}
const addCustomer = async (req,res) => {
const {customerName, customerOrder, Quantity} = req.body
try {
const customer = await Customer1.create({customerName, customerOrder, Quantity})
res.status(200).json(customer)
}
catch(error) {
return res.status(500).json({Error: 'Internal Server Error'})
}
}
const updateCustomer = async (req,res) => {
const { id } = req.params
if(!mongoose.Types.ObjectId.isValid(id))
{
return res.status(400).json({Error: 'Not a vlaid DB id.'})
}
const customer = await Customer1.findOneAndUpdate({_id: id}, req.body, {
runValidators: true,
new: true
})
if(!customer)
{
return res.status(404).json({Error: 'No such customer available'})
}
res.status(200).json(customer)
}
const deleteCustomer = async (req,res) => {
const { id } = req.params
if(!mongoose.Types.ObjectId.isValid(id))
{
return res.status(400).json({Error: 'Not a vlaid DB id.'})
}
const customer = await Customer1.findOneAndDelete({_id: id})
if(!customer)
{
return res.status(404).json({Error: 'No such customer available'})
}
res.status(200).json(customer)
}
module.exports = {
getCustomer,
getSingleCustomer,
addCustomer,
updateCustomer,
deleteCustomer
}
Customer Routes
In this code block, we define the routes for the Customer microservice. These routes specify the API endpoints for performing CRUD operations on customer data.
const express = require('express')
const {
getCustomer,
getSingleCustomer,
addCustomer,
updateCustomer,
deleteCustomer
} = require('../Controllers/custControllers')
const router = express.Router()
router.get('/', getCustomer)
router.get('/:id', getSingleCustomer)
router.post('/', addCustomer)
router.patch('/:id', updateCustomer)
router.delete('/:id', deleteCustomer)
module.exports = router
Server
const express = require('express')
const mongoose = require('mongoose')
require('dotenv').config()
const app = express()
app.use(express.json())
const custRoutes = require('./Routes/custRoutes')
// app.use((req,res,next) => {
// console.log(req.method, res.path)
// next()
// })
app.use('/api/customer/business', custRoutes)
mongoose.connect(process.env.MONG_URI)
.then(() => {
app.listen((process.env.PORT), () => {
console.log('Connected to DB and listening to port', process.env.PORT)
})
})
.catch((error) => {
console.log(error)
})
Your Customer Service is ready to roll! It can now handle customer data effortlessly, thanks to the CRUD operations.
This is the customer services, .env will contain the PORT on which the services will be hosted and MONG_URL will contain your database URL.
Grocery Service: Satisfying Your Grocery Needs ๐
Now, let's shift our focus to the Grocery microservice.
Grocery Schema
In this code block, we define the schema for the Grocery microservice using Mongoose. This schema outlines the structure of grocery documents, including fields like groceryName
, manufacturer
, and availableQuantity
.
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const grocerySchema = new Schema ({
Name: {
type: String,
required: true
},
Manufacturer: {
type: String,
required: true
},
Quantity: {
type: Number,
required: true
}
}, {timestamps: true})
module.exports = mongoose.model('Grocery', grocerySchema)
Grocery Controller
In this code block, we define the controller for the Grocery microservice. This controller contains functions to handle CRUD operations for groceries, including creating, reading, updating, and deleting grocery records.
const express = require('express')
const {default: mongoose} = require('mongoose')
const Grocery = require('..//Models/groSchema')
const getGrocery = async (req,res) => {
try{
const grocery = await Grocery.find({}).sort({ createdAt: -1})
res.status(200).json(grocery)
}
catch(error) {
return res.status(400).json(error)
//console.log(error)
}
}
const getSingleGrocery = async (req,res) => {
const { id } = req.params
if(!mongoose.Types.ObjectId.isValid(id))
{
return res.status(400).json({Error: 'Not a vlaid DB id.'})
}
const grocery = await Grocery.findById(id)
if(!grocery)
{
return res.status(404).json({Error: 'No such grocery available'})
}
res.status(200).json(grocery)
}
const addGrocery = async (req,res) => {
const {Name, Manufacturer, Quantity} = req.body
try {
const grocery = await Grocery.create({Name, Manufacturer, Quantity})
res.status(200).json(grocery)
}
catch(error) {
return res.status(500).json({Error: 'Internal Server Error'})
}
}
const updateGrocery = async (req,res) => {
const { id } = req.params
if(!mongoose.Types.ObjectId.isValid(id))
{
return res.status(400).json({Error: 'Not a vlaid DB id.'})
}
const grocery = await Grocery.findOneAndUpdate({_id: id}, req.body, {
runValidators: true,
new: true
})
if(!grocery)
{
return res.status(404).json({Error: 'No such grocery available'})
}
res.status(200).json(grocery)
}
const deleteGrocery = async (req,res) => {
const { id } = req.params
if(!mongoose.Types.ObjectId.isValid(id))
{
return res.status(400).json({Error: 'Not a vlaid DB id.'})
}
const grocery = await Grocery.findOneAndDelete({_id: id})
if(!grocery)
{
return res.status(404).json({Error: 'No such grocery available'})
}
res.status(200).json(grocery)
}
module.exports = {
getGrocery,
getSingleGrocery,
addGrocery,
updateGrocery,
deleteGrocery
}
Grocery Routes
const express = require('express')
const {
getGrocery,
getSingleGrocery,
addGrocery,
updateGrocery,
deleteGrocery
} = require('../Controllers/groController')
const router = express.Router()
router.get('/', getGrocery)
router.get('/:id', getSingleGrocery)
router.post('/', addGrocery)
router.patch('/:id', updateGrocery)
router.delete('/:id', deleteGrocery)
module.exports = router
Server
const express = require('express')
const mongoose = require('mongoose')
require('dotenv').config()
const app = express()
app.use(express.json())
const groRoutes = require('./Routes/groceryRoutes')
// app.use((req,res,next) => {
// console.log(req.method, res.path)
// next()
// })
app.use('/api/grocery', groRoutes)
mongoose.connect(process.env.MONG_URI)
.then(() => {
app.listen((process.env.PORT), () => {
console.log('Connected to DB and listening to port', process.env.PORT)
})
})
.catch((error) => {
console.log(error)
})
Your Grocery Service is now equipped to manage grocery items efficiently, thanks to the power of CRUD!
Business Service: The Power of Order Placement ๐ผ
The Business microservice is where the magic happens! It orchestrates order placements, connecting customer and grocery data seamlessly.
Business Schema
In this code block, we define the schema for the Business microservice. This schema outlines the structure of business documents, including fields like CustomerName
, GroceryName
, GroceryID
, CustomerID
and Quantity
.
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const busSchema = new Schema ({
CustomerName: {
type: mongoose.SchemaTypes.String,
required: true
},
CustomerID :{
type: mongoose.SchemaTypes.ObjectId,
required: true
},
GroceryName: {
type: mongoose.SchemaTypes.String,
required: true
},
GroceryID :{
type: mongoose.SchemaTypes.ObjectId,
required: true
},
Quantity: {
type: mongoose.SchemaTypes.Number,
required: true
},
orderDate: {
type: String,
required: true
}
}, {timestamps: true})
module.exports = mongoose.model('Business', busSchema)
Business Controller
In this code block, we define the controller for the Business microservice. This controller contains functions to handle various operations related to business data, including order placements and retrieval of orders.
const {default: mongoose} = require('mongoose')
const express = require('express')
const Business = require('../Models/busSchema')
const getBusinesss = async (req,res) => {
const business = await Business.find({}).sort({ createdAt: -1})
return res.status(200).json(business)
}
const getSingleBusiness = async (req,res) => {
const { id } = req.params
if(!mongoose.Types.ObjectId.isValid(id))
{
return res.status(400).json({Error: 'Not a vlaid DB id.'})
}
const business = await Business.findById(id)
if(!business)
{
return res.status(404).json({Error: 'No such medicine available'})
}
res.status(200).json(business)
}
const addBusiness = async (req,res) => {
const {CustomerName, CustomerID, GroceryName, GroceryID, Quantity, orderDate} = req.body
try{
const business = await Business.create({CustomerName, CustomerID, GroceryName, GroceryID ,Quantity, orderDate})
res.status(201).json(business)
}
catch(error) {
return res.status(400).json("error")
}
}
const updateBusiness = async (req,res) => {
const { id } = req.params
if(!mongoose.Types.ObjectId.isValid(id))
{
return res.status(400).json({Error: 'Not a vlaid DB id.'})
}
const business = await Business.findOneAndUpdate({_id: id}, req.body, {
runValidators: true,
new: true
})
if(!business)
{
return res.status(404).json({Error: 'No such medicine available'})
}
res.status(200).json(business)
}
const deleteBusiness = async (req,res) => {
const { id } = req.params
if(!mongoose.Types.ObjectId.isValid(id))
{
return res.status(400).json({Error: 'Not a vlaid DB id.'})
}
const business = await Business.findOneAndDelete({_id: id})
if(!business)
{
return res.status(404).json({Error: 'No such medicine available'})
}
res.status(200).json(business)
}
module.exports = {
getBusinesss,
getSingleBusiness,
addBusiness,
updateBusiness,
deleteBusiness
}
Business Routes
In this code block, we define the routes for the Business microservice. These routes specify the API endpoints for placing orders and retrieving order data.
const express = require('express')
const {
getBusinesss,
getSingleBusiness,
addBusiness,
updateBusiness,
deleteBusiness
} = require('../Controller/busController')
const router = express.Router()
router.get('/', getBusinesss)
router.get('/:id', getSingleBusiness)
router.post('/', addBusiness)
router.patch('/:id', updateBusiness)
router.delete('/:id', deleteBusiness)
module.exports = router
Server
const express = require('express')
const {default: mongoose} = require('mongoose')
require('dotenv').config()
const axios = require('axios')
const app = express()
app.use(express.json())
const Business = require('./Models/busSchema')
const busRoutes = require('./Routes/busRoutes')
// app.use((req,res,next) => {
// console.log(req.method, res.path)
// next()
// })
app.use('/api/business', busRoutes)
app.get('/api/grobus/:id', async (req,res) => {
const { id } = req.params
const business = await Business.findById(id)
if(business) {
axios.get('http://localhost:9000/api/customer/business/' + business.CustomerID).then((response) => {
var orderObject = {customerName: response.data.customerName, quantity: response.data.Quantity}
axios.get('http://localhost:8000/api/grocery/' + business.GroceryID).then((response) => {
orderObject.GroceryName = response.data.Name
res.json(orderObject)
console.log('Successfully added.')
})
})
}else {
res.send('Invalid Order')
}
})
mongoose.connect(process.env.MONG_URI)
.then(() => {
app.listen((process.env.PORT), () => {
console.log('Connected to DB and listening to port', process.env.PORT)
})
})
.catch((error) => {
console.log(error)
})
Here we use Axios to integrate the two CRUD apps: Customer and Grocery.
The Business Service is where the magic happens! It orchestrates order placements, connecting customer and grocery data seamlessly.
Working and Output ๐ ๏ธ
Adding Customers
Adding Groceries
Adding the order in Business
In this, we use Axios to integrate the grocery and customer to place an order. The code blocks as shown above are:
app.get('/api/grobus/:id', async (req,res) => {
const { id } = req.params
const business = await Business.findById(id)
if(business) {
axios.get('http://localhost:9000/api/customer/business/' + business.CustomerID).then((response) => {
var orderObject = {customerName: response.data.customerName, quantity: response.data.Quantity}
axios.get('http://localhost:8000/api/grocery/' + business.GroceryID).then((response) => {
orderObject.GroceryName = response.data.Name
res.json(orderObject)
console.log('Successfully added.')
})
})
}else {
res.send('Invalid Order')
}
})
Now finally fetching the details from the customer and grocery and placing an order, we get:
This is the final output and yes our order is placed, this is how microservices work.
Conclusion ๐
You've embarked on a remarkable journey to create a microservices-based grocery business application. Your microservices are equipped to handle CRUD operations for customers, groceries, and orders, making your application flexible, scalable, and easy to maintain.
As you dive deeper into microservices, remember to consider essential factors like data consistency, fault tolerance, and monitoring. Implement security measures to safeguard sensitive customer and business data.
Now, it's your turn! Continuously test, monitor, and optimize your application to meet the demands of your grocery business. Provide your customers with an exceptional shopping experience and watch your grocery empire thrive!
Happy coding! ๐๐
CRUD and Github repo ๐
With this comprehensive blog post, you have a step-by-step guide to building a microservices-based grocery business application, complete with CRUD operations and order placement functionality. Feel free to adapt and expand upon these concepts to create a robust and efficient system for your grocery business.