This sample demonstrates how to configure and use multiple OData services with cross-service communication and validation.
- ✅ Three independent OData services
- ✅ Cross-service data validation
- ✅ Automatic stock management
- ✅ Service aliases for clean code
- ✅ Auto-fill from product master
- ✅ Value help integration
multi-service/
├── ui5.yaml
├── package.json
└── webapp/
└── localService/
├── sales/ # Sales Order Service
│ ├── metadata.xml
│ └── data/
│ ├── SalesOrders.json
│ ├── SalesOrderItems.js # Cross-service validation
│ └── Customers.json
├── products/ # Product Master Service
│ ├── metadata.xml
│ └── data/
│ ├── Products.json
│ └── Categories.json
└── valuehelp/ # Value Help Service
├── metadata.xml
└── data/
├── Currencies.json
└── Countries.json
- Install dependencies:
npm install- Start the mockserver:
npm start- Open browser:
http://localhost:8080
POST http://localhost:8080/sap/opu/odata/sap/SALES_ORDER_SRV/SalesOrderItems
Content-Type: application/json
{
"OrderID": "SO-001",
"ItemNo": "10",
"ProductID": "MAT-1000",
"Quantity": "2.000"
}Expected: Success with auto-filled Description, UnitPrice, and Amount
POST http://localhost:8080/sap/opu/odata/sap/SALES_ORDER_SRV/SalesOrderItems
Content-Type: application/json
{
"OrderID": "SO-001",
"ItemNo": "20",
"ProductID": "MAT-1002",
"Quantity": "20.000"
}Expected: 400 Error - Only 10 units available
POST http://localhost:8080/sap/opu/odata/sap/SALES_ORDER_SRV/SalesOrderItems
Content-Type: application/json
{
"OrderID": "SO-001",
"ItemNo": "30",
"ProductID": "INVALID",
"Quantity": "1.000"
}Expected: 400 Error - Product does not exist
GET http://localhost:8080/sap/opu/odata/sap/PRODUCT_MASTER_SRV/Products('MAT-1000')GET http://localhost:8080/sap/opu/odata/sap/VALUE_HELP_SRV/Currencies
GET http://localhost:8080/sap/opu/odata/sap/VALUE_HELP_SRV/CountriesThe SalesOrderItems.js file implements validation against the product master service:
const productService = await this.base.getEntityInterface('Products', 'products');
const product = productService.fetchEntries({ ProductID: data.ProductID });After creating an item, stock is automatically decremented:
const newStock = product.StockQuantity - parseFloat(data.Quantity);
await productService.updateEntry({ ProductID: data.ProductID }, { StockQuantity: newStock });Product details are automatically populated:
- Description from ProductName
- UnitPrice from Price
- Amount calculated (Price × Quantity)
Clean service references using aliases:
sales→ /sap/opu/odata/sap/SALES_ORDER_SRVproducts→ /sap/opu/odata/sap/PRODUCT_MASTER_SRVvaluehelp→ /sap/opu/odata/sap/VALUE_HELP_SRV
- Documentation: Cross-Service Communication
- Documentation: Multi-Service Configuration
specVersion: "3.0"
metadata:
name: multi-service-app
type: application
server:
customMiddleware:
-
name: sap-fe-mockserver afterMiddleware: compression configuration: services: # Main sales service - urlPath: /sap/opu/odata/sap/SALES_ORDER_SRV metadataPath: ./webapp/localService/sales/metadata.xml mockdataPath: ./webapp/localService/sales/data alias: sales
# Product master service - urlPath: /sap/opu/odata/sap/PRODUCT_MASTER_SRV metadataPath: ./webapp/localService/products/metadata.xml mockdataPath: ./webapp/localService/products/data alias: products # Value help service - urlPath: /sap/opu/odata/sap/VALUE_HELP_SRV metadataPath: ./webapp/localService/valuehelp/metadata.xml mockdataPath: ./webapp/localService/valuehelp/data alias: valuehelp
-