Are you a Uniface developer or simply maintaining a legacy system and wondering, “What exactly does this headless component do?” 🤔
In this post, I’ll break down the Session Service in Uniface, explain why it’s crucial for clean architecture, and how it helps you separate concerns effectively. Let’s dive in! 🚀
What is a Session Service? 🧐
A Session Service (SSV) in Uniface is a specialized component designed to encapsulate complex business logic without any user interface (UI). Think of it as the “engine room” or “Controller” of a specific business process. ⚙️
Unlike simple Entity Services (which typically manage CRUD operations for a single database entity), a Session Service acts as a coordinator. It manages logic that spans multiple entities, handl…
Are you a Uniface developer or simply maintaining a legacy system and wondering, “What exactly does this headless component do?” 🤔
In this post, I’ll break down the Session Service in Uniface, explain why it’s crucial for clean architecture, and how it helps you separate concerns effectively. Let’s dive in! 🚀
What is a Session Service? 🧐
A Session Service (SSV) in Uniface is a specialized component designed to encapsulate complex business logic without any user interface (UI). Think of it as the “engine room” or “Controller” of a specific business process. ⚙️
Unlike simple Entity Services (which typically manage CRUD operations for a single database entity), a Session Service acts as a coordinator. It manages logic that spans multiple entities, handles transaction boundaries, and executes specific tasks.
Key Characteristics:
- Headless: It has no forms, windows, or widgets. It runs entirely in the background. 👻
- Task-Oriented: It is built to handle specific operations like “Process Order” or “Calculate End-of-Month Report”.
- Stateless (mostly): In modern web contexts (like using the Uniface Web Application Server), Session Services are often designed to be instantiated for a single request and then destroyed. 💨
- Transaction Controller: It often takes responsibility for the
commitandrollbackcommands to ensure data integrity across multiple tables. 🛡️
The Problem: Logic in the UI Layer 🍝❌
Imagine you have a “Buy Now” button in a DSP (Dynamic Server Page) or a Form. A common mistake is to put all the processing logic directly into the button’s detail trigger:
- Check stock availability 📦
- Create a header record in the
ORDERSentity 📝 - Loop through a list to create
ORDER_LINES🔄 - Update the
CUSTOMERcredit limit 💳 - Send a confirmation email 📧
Why is this problematic?
- Lack of Reusability: If you need to trigger the same process from a different part of the system (e.g., a batch job or a REST API), you have to duplicate the code. 😱
- Testing Difficulties: Logic embedded in UI triggers is hard to test independently.
- Maintenance Headaches: Your form code becomes bloated, making it difficult to read and maintain.
The Solution: Encapsulate with Session Services ✅
By moving that logic into a dedicated Session Service component (e.g., SVC_ORDER_PROCESS), you clean up your architecture significantly. Your UI trigger becomes a simple call:
; Button "Buy Now" Trigger
activate "SVC_ORDER_PROCESS".createOrder(in_CustomerID, in_CartID, out_Status)
This approach decouples the process from the presentation. ✨
Code Example: The “Create Order” Operation 🛒
Here is a simplified example of what the ProcScript inside a Session Service operation might look like.
Component: SVC_ORDER_PROCESS
Operation: createOrder
entry createOrder
params
string pCustomerID : IN
string pItemList : IN
numeric pStatus : OUT
endparams
variables
numeric vTotalAmount
string vItem
endvariables
; 1. Validate Customer
activate "SVC_CUSTOMER".checkCredit(pCustomerID, pStatus)
if (pStatus < 0) return -1
; 2. Create Order Header
clear/e "ORDERS"
ORDERS.CUST_ID = pCustomerID
ORDERS.DATE = $date
; 3. Process Items (Iterating through the list)
getitem/id vItem, pItemList, 1
while ($status > 0)
creocc "ORDER_LINES"
ORDER_LINES.ITEM_ID = vItem
; ... logic to calculate price and discounts ...
getitem/id vItem, pItemList, $loopcounter + 1
endwhile
; 4. Transaction Management
commit
if ($status < 0)
rollback
pStatus = -99
return -99
endif
pStatus = 1 ; Success! 🎉
return 0
end
Common Pitfalls to Avoid ⚠️
- Assuming State Persistence: In a web environment, don’t assume the service remembers variables from a previous call. Always pass all necessary context (like Session IDs or current status) as parameters! 🔄
- Interactive Commands: Never use
askmessor other interactive commands inside a Session Service. Since it runs on the server (often headless), the process will hang indefinitely waiting for user input that can never happen! 🛑 - Locking Issues: Be mindful of record locking. If your service locks data and takes a long time to complete without committing, it can block other users. ⏳
Conclusion 🎯
Session Services are essential for building scalable and maintainable Uniface applications. They keep your code DRY (Don’t Repeat Yourself), allow for better separation of concerns, and make your application logic testable.
Whether you are modernizing an old system or building a new service-oriented architecture, mastering the Session Service is key to professional Uniface development.
Happy Coding! 💻✨