Hi everyone! 👋
If you come from the classic Client/Server world of Uniface (or any other stateful environment), moving to the web feels like losing your memory. Suddenly, your application forgets everything between two clicks. 🤯
In Uniface DSPs and Entity Services, State Management isn’t just a nice-to-have—it’s the backbone of your architecture. Today, let’s dive into how we handle state, specifically when working with the disconnected nature of Entity Services.
Let’s go! 🚀
The Problem: “I Forgot Who You Are” 🤷♂️
In a classic Uniface form, the database connection stays open. You lock a record, go grab a coffee ☕, come back, and the lock is still there.
In the web world (Stateless), it looks like this:
- Load: User asks for data -> Service loads it…
Hi everyone! 👋
If you come from the classic Client/Server world of Uniface (or any other stateful environment), moving to the web feels like losing your memory. Suddenly, your application forgets everything between two clicks. 🤯
In Uniface DSPs and Entity Services, State Management isn’t just a nice-to-have—it’s the backbone of your architecture. Today, let’s dive into how we handle state, specifically when working with the disconnected nature of Entity Services.
Let’s go! 🚀
The Problem: “I Forgot Who You Are” 🤷♂️
In a classic Uniface form, the database connection stays open. You lock a record, go grab a coffee ☕, come back, and the lock is still there.
In the web world (Stateless), it looks like this:
- Load: User asks for data -> Service loads it -> Service dies. 💀
- Edit: User types in the browser.
- Save: User clicks save -> A NEW Service starts -> “Who are you and what is this data?” 🤔
We need a way to bridge this gap.
The Solution: The “Hot Potato” Pattern 🥔
Since the server has amnesia, the Client (DSP) must hold the memory. We treat the data state like a hot potato that we toss back and forth.
Here is the golden workflow for Entity Services:
1. The Load (Exporting State) 📤
Your Entity Service loads data from the DB, but instead of keeping it, it packs it up into a suitcase (XML, JSON, or a Struct) and ships it to the browser.
; Service: SVC_ORDER / Operation: LOAD
operation load
params
String pOrderId : IN
String pDataXml : OUT ; The Suitcase 🧳
endparams
retrieve/e "ORDERS", pOrderId
xmlsave pDataXml, "ORDERS" ; Freeze the state!
end
2. The Edit (Holding State) ✍️
The browser (DSP) receives the XML. The user edits the order. The server is currently doing nothing. Zero resources used. 🌱
3. The Save (Restoring State) 📥
This is where the magic happens. The user sends the modified XML back. The service wakes up, but it’s empty. It needs to reconnect to the previous reality.
; Service: SVC_ORDER / Operation: SAVE
operation save
params
String pDataXml : IN ; The returned Suitcase 🧳
endparams
; The magic command: RECONNECT
; This tells Uniface: "Take this data and pretend you just loaded it."
reconnect pDataXml, "ORDERS"
; Now Uniface knows what changed!
; Triggers like <validate> or <update> will fire correctly.
store
if ($status < 0)
return -1
endif
return 0
end
Wait, what about Locking? 🔒
Good catch! Since we closed the connection after Step 1, we lost our DB lock. If your colleague Bob 👷♂️ changes the record while you are editing it, standard locking won’t help.
We use Optimistic Locking here. When you run reconnect, Uniface (or your logic) checks: “Does the record in the DB look exactly like it did when I loaded it?”
If Bob changed it, the store (or reconnect) will fail with a specific error. You can then tell the user: “Hey, Bob was faster. Please reload.” 🏁
Key Takeaways 📝
- Stateless is cleaner: No hanging locks, less server memory usage.
- Reconnect is your friend: It bridges the gap between “Just XML” and “Uniface Instances”.
- Trust no one: Always validate data in the Service (save operation), never just in the browser! 🛡️
Have you worked with disconnected record sets in Uniface before? Let me know in the comments! 👇
Happy Coding! 💻✨