Blog › ICP guides
Omnis Studio developer on retainer: DAM transaction not rolled back on endmethod, Omnis 8 developer, Omnis Studio financial services developer on monthly retainer
October 9, 2026 · ~15 min read
An Omnis Studio developer was maintaining a financial services client portfolio management system at a wealth management firm running Omnis Studio 8.1 on a Windows Server 2019 application server, with a SQL Server 2019 backend database. The Omnis application served 20 concurrent client services staff who managed client account portfolios, ran compliance checks, and processed account status updates. A sequence method named oClientAccount.$updateAccountStatus in the ClientAccount task class handled the workflow of placing a client account under compliance review: it called $ctask.$DAMsession.$startTransaction() to begin an explicit transaction on the SQL Server DAM (Data Access Module) connection, issued a SQL UPDATE statement via $sqlexec to mark the account — UPDATE ClientAccounts SET Status = 'Under Review' WHERE AccountId = iAccountId — which acquired an exclusive row lock on the ClientAccounts row for that account, and then called a regulatory compliance check method to verify that the account update met current compliance requirements before committing. When the compliance check returned a failure code (indicating the account had incomplete regulatory documentation), the validation check at line 14 of the method called $endmethod(kComplianceFailed) to return the failure code to the calling window method, which would then display an appropriate error dialog to the client services staff member. The developer who wrote oClientAccount.$updateAccountStatus understood that the calling window method would handle the compliance failure display and that the overall workflow would be terminated. What the developer did not account for was that $endmethod() in an Omnis Studio sequence method terminates the method and returns control to the caller — but it does not commit or roll back any open DAM transaction that the method had initiated. The $startTransaction() called at line 3 remained open after $endmethod(kComplianceFailed) at line 14, and the exclusive row lock on the ClientAccounts row for iAccountId remained held by the DAM connection for its lifetime. Other Omnis tasks connecting through the same connection pool and attempting to update the same account received SQL Server error 1222 “Lock request time out period exceeded.” Lock timeout errors per afternoon: 2–4 at peak compliance review hours; 0 after $rollback() was added before every $endmethod() on all validation failure paths in oClientAccount.$updateAccountStatus.
The root cause was the relationship between Omnis Studio’s sequence method execution model and the lifecycle of the underlying DAM database connection’s transaction state. An Omnis Studio DAM session object ($DAMsession) maintains a persistent connection to the backend SQL database. When $startTransaction() is called on the DAM session, Omnis sends a BEGIN TRANSACTION (or equivalent for the configured backend — PostgreSQL, Oracle, MySQL) to the backend database server. The DAM session’s transaction state is now “open”: subsequent SQL statements executed via $sqlexec or $dowork on this DAM session operate within the open transaction, acquiring row-level or page-level locks according to the backend database’s normal locking rules. SQL Server, in its default READ COMMITTED isolation level, acquires exclusive row locks for the duration of any transaction that modifies a row via UPDATE. These locks are held by the backend connection until the transaction is explicitly committed ($commit()) or rolled back ($rollback()). The $endmethod() command in Omnis Studio terminates the current sequence method, releases any local Omnis variables, and returns the specified return code to the calling method. It has no effect on the state of any DAM session or its open transactions. After $endmethod(kComplianceFailed) executes, the oClientAccount task’s $DAMsession object continues to exist, still connected to SQL Server, still holding the open transaction that was started with $startTransaction() at line 3, with the exclusive row lock on ClientAccounts row iAccountId still held. The connection’s transaction state is fully transparent to the Omnis application’s window-level event model: the client services staff member sees the compliance failure dialog, dismisses it, and returns to their workflow — with no indication that the underlying DAM connection is holding an uncommitted transaction and a live SQL Server row lock.
The single-developer test invisibility follows the standard concurrent lock bug pattern but has an additional layer of invisibility specific to Omnis Studio’s connection pool architecture. The developer who wrote oClientAccount.$updateAccountStatus tested the compliance failure path on a development Omnis instance with a single task running. They called the method with a test account that had incomplete documentation, confirmed that the compliance check returned kComplianceFailed, and verified that the calling window method displayed the appropriate error dialog. The SQL Server connection used by the development task held the open transaction, but since only one Omnis task was running in the development instance, no other task attempted to UPDATE the same ClientAccounts row. SQL Server’s default lock timeout in the development environment may have been set to −1 (wait indefinitely), meaning that even if a second connection had tried to lock the same row, it would have waited forever rather than returning error 1222 within a visible test window. In production with 20 concurrent client services tasks sharing a pool of SQL Server connections, the collision became visible when two staff members ran compliance review workflows on accounts whose underlying data shared relational dependencies — the same account being reviewed from two workstations, or the compliance check’s underlying query joining to a table row that another task had locked in its own open transaction. The lock timeout error appeared on the second task with no Omnis-level diagnostic information about which task held the blocking connection.
Omnis Studio: from Blyth Software’s 1982 Macintosh tool to a modern cross-platform RAD platform
Omnis was created by Blyth Software in the United Kingdom in 1982, initially as one of the first commercial database application development tools for the Apple II and TRS-80 microcomputers. Blyth’s Omnis 3 (released in 1984 for the Apple Macintosh) became one of the most popular Mac database tools of the late 1980s, particularly in the UK, France, the Netherlands, and Australia, competing directly with 4th Dimension and FileMaker Pro in the Mac database market. Omnis 3’s strength was its client-server architecture: it could connect multiple Macintosh workstations to a central Omnis server, sharing a single database file with robust multi-user record locking, while maintaining a rich graphical application interface on each client workstation. Blyth Inc., the US subsidiary, marketed Omnis in North America through the late 1980s and 1990s.
Omnis 7 (released in the early 1990s) was the major cross-platform release: Mac and Windows clients connecting to a shared Omnis server on either platform. Omnis 7 introduced the DAM (Data Access Module) architecture that became the foundation of all subsequent Omnis database connectivity: instead of using Omnis’s own embedded database, a DAM allowed Omnis to connect to external SQL databases (SQL Server, Oracle, Sybase, Informix, and later PostgreSQL and MySQL) via native database APIs or ODBC, executing SQL statements and managing transactions through the DAM session object while the Omnis application logic handled form presentation and business rules. This architecture was particularly well-suited to financial services, insurance, and professional services firms that already had substantial SQL Server or Oracle infrastructure and wanted to build a rich Omnis client application on top of it without replicating all their existing stored procedure logic.
Blyth Inc. was acquired by Raining Data Corporation in 2001, and Raining Data renamed the product Omnis Studio and the company to TigerLogic Corporation in 2008. TigerLogic sold the Omnis Studio product line to Omnis Software Ltd (a UK-based company) in 2014. Omnis Software Ltd has continued active development: Omnis Studio 8.x and 9.x added REST service server capabilities, a JavaScript-based omnis web client for browser-based deployment, and enhanced mobile support. Omnis Studio 10.x (current, 2024) adds further web client improvements, enhanced REST API server features, and continued platform maintenance for the installed base of financial services, insurance, not-for-profit, and professional services organizations that have run core business applications on Omnis since the 1990s. The Omnis developer community is relatively small and geographically concentrated in the UK, the Netherlands, Australia, and the United States, which means that retainer developers with deep Omnis Studio expertise — particularly for complex financial services or insurance applications with multi-user concurrency requirements — are rare and command premium retainer rates.
The DAM transaction model in Omnis Studio is the correct abstraction for managing SQL backend transactions from Omnis sequence methods, but it requires explicit transaction management by the developer for every method that initiates a transaction. Omnis Studio does not provide an equivalent of SQL Server’s SET XACT_ABORT ON or a transaction auto-rollback on method exit. The developer is responsible for ensuring that every $startTransaction() is matched by either a $commit() (on success) or a $rollback() (on every failure path and every error path) before control returns from the sequence method. This responsibility mirrors the explicit transaction management requirement in stored procedures in Sybase ASE, SQL Anywhere, InterSystems Caché, and other database environments where the platform does not automatically clean up an open transaction on error: the developer must pair every transaction open with every transaction close.
Omnis Studio DAM session transaction model: $startTransaction, $commit, $rollback, and connection lifetime locks
Omnis Studio’s DAM (Data Access Module) session object provides the interface between Omnis application logic and the underlying SQL database connection. The transaction management methods on the DAM session are: $startTransaction() sends a BEGIN TRANSACTION (or equivalent for the configured backend) to the SQL server, placing the DAM session’s connection in an explicit transaction context; $commit() sends COMMIT TRANSACTION, committing all pending changes and releasing all row-level locks acquired since $startTransaction(); $rollback() sends ROLLBACK TRANSACTION, discarding all pending changes and releasing all row-level locks. All three methods operate on the underlying backend SQL connection managed by the DAM session — the backend database’s locking behavior is governed entirely by the backend’s rules, not by Omnis Studio’s runtime. SQL Server holds exclusive row locks (acquired by UPDATE statements) for the full duration of the open transaction. PostgreSQL holds row-level exclusive locks from the UPDATE through the COMMIT or ROLLBACK. Oracle uses undo segments to manage lock state similarly.
The $endmethod() command in Omnis Studio sequence methods terminates the method execution and passes a return value back to the calling method or task. It is the standard way to return from a sequence method, analogous to RETURN in stored procedure languages. $endmethod() has no interaction with the DAM session: it does not issue any SQL statement, does not commit or roll back any open transaction, and does not modify the DAM session’s connection state in any way. After $endmethod(), the DAM session continues to exist in whatever state it was in when the method exited — including any open transaction that was started with $startTransaction(). The correct pattern for a sequence method that calls $startTransaction() is to call $rollback() on every $endmethod() exit that does not call $commit() first. For methods with multiple validation checks and multiple failure paths, the safe pattern is: at the top of the method, set a flag variable (e.g., lTransactionOpen := kTrue) immediately after $startTransaction(); at the end of every failure path, check the flag and call $rollback() before $endmethod(); use Omnis Studio’s ON condition error routing to ensure that unexpected errors also trigger a $rollback() before the error propagates to the caller.
Diagnosing an Omnis Studio DAM session transaction hold requires querying the backend SQL database’s lock diagnostic views, since Omnis Studio itself does not expose live transaction state information at the application layer. For SQL Server backends: SELECT l.session_id, l.resource_type, l.resource_description, l.request_mode, s.login_name, s.host_name, s.program_name, r.blocking_session_id FROM sys.dm_tran_locks l JOIN sys.dm_exec_sessions s ON l.session_id = s.session_id LEFT JOIN sys.dm_exec_requests r ON l.session_id = r.session_id WHERE l.request_mode = 'X' AND l.resource_type = 'RID' — this query returns all exclusive row locks, with the session ID of the holding connection, the login name (will show the Omnis application server’s SQL Server login, e.g., OMNIS_APP), the host name (the Omnis application server machine name), and the blocking session ID for any connection waiting on the same resource. Cross-reference the session ID with the Omnis application server’s connection pool configuration and log to identify which Omnis task class instance used that connection. In the oClientAccount.$updateAccountStatus incident, the diagnostic shows: SQL Server session 58, login OMNIS_APP, host APP-SERVER-01, program Omnis Studio 8.1, exclusive row lock on ClientAccounts page 1, slot 3, row ID 3. SQL Server sessions 61 and 63 are blocked on the same row with request status WAIT. The Omnis application server log (if verbose logging is enabled) may show the last method and task that used connection session 58. The fix: $rollback() added before $endmethod(kComplianceFailed) at line 14 of oClientAccount.$updateAccountStatus, and the full method audited for any other $endmethod() calls that exit without either $commit() or $rollback().
Typical Omnis Studio developer retainer work and what it looks like in a work log
DAM transaction not rolled back on $endmethod() validation failure is the canonical Omnis Studio invisible production lock bug for sequence methods that use $startTransaction() with multi-path validation logic. It appears in the work logs of Omnis retainer engagements for financial services portfolio management, insurance claims processing, professional services matter management, and not-for-profit fund management systems built on Omnis Studio 6.x through 10.x. The work log entry that makes this diagnosable: “Omnis Studio 8.1, library ClientPortfolio.lbs; sequence method oClientAccount.$updateAccountStatus; backend SQL Server 2019, database PortfolioDB; DAM session $ctask.$DAMsession; $startTransaction() at line 3; $sqlexec UPDATE ClientAccounts SET Status = 'Under Review' WHERE AccountId = iAccountId at line 6 (exclusive row lock on ClientAccounts row iAccountId); compliance check failure at line 14: If (compliance_result = kFailed) $endmethod(kComplianceFailed) End if — $endmethod() without $rollback(); SQL Server lock diagnostic (sys.dm_tran_locks + sys.dm_exec_sessions): session 58, login OMNIS_APP, host APP-SERVER-01, program Omnis Studio 8.1, exclusive row lock on ClientAccounts page 1 slot 3; blocked sessions: 61 and 63, request status WAIT on same row; lock timeout errors per afternoon before fix: 2–4 (each resolved by the system administrator killing SQL Server session 58); fix: $rollback() added before $endmethod(kComplianceFailed) at line 14; full method audited for additional $endmethod() paths without $rollback() — 3 additional paths found and fixed (risk limit check at line 21, account age check at line 28, KYC documentation check at line 35); lock timeout errors per afternoon after fix: 0; 3h.”
Omnis Studio window and form development is the routine day-to-day Omnis retainer task for financial services and insurance clients who have grown their Omnis application incrementally over many years and now need new windows, report views, and data entry screens to support new business workflows. A common engagement for a UK-based insurance broker: the underwriting team needs a new risk exposure summary window that shows a client’s aggregate insured value across all active policies, segmented by risk category, with a drill-down to individual policy detail. The retainer developer creates a new Omnis Studio window class, adds a scrolling list pane component to display the risk category summary rows, writes the data population method that queries the SQL Server backend ($sqlexec SELECT RiskCategory, SUM(InsuredValue) FROM Policies WHERE ClientId = iClientId AND Status = 'Active' GROUP BY RiskCategory ORDER BY RiskCategory), and wires the double-click event on the summary row to open the existing policy detail window for the selected risk category. Work log: “Omnis Studio 8.1; library InsuranceBroker.lbs; new window class wRiskExposureSummary; scrolling list pane for risk category / insured value summary; $populate method with $sqlexec GROUP BY query; drill-down to existing wPolicyDetail on double-click; tested with 12-client data set; delivered to UAT; 5h.”
Omnis Studio version migration is the highest-investment Omnis retainer engagement for clients running Omnis Studio 4.x or 6.x who need to move to a supported version for continued operating system compatibility, security patches, and omnis web client access for remote worker deployments. The migration assessment begins with a library inventory: enumerate all task classes, window classes, report classes, server task classes, and remote task classes; identify deprecated Omnis Studio 6.x syntax that Omnis Studio 8.x or 10.x’s compiler rejects or behaves differently under; audit all sequence methods containing $startTransaction() for missing $rollback() on failure paths (the migration is the correct moment for the transaction rollback audit); review DAM session configuration for any backend-specific connection string parameters that have changed between Omnis Studio versions (particularly for Oracle and PostgreSQL DAM modules, which have undergone API updates between major versions). Work log: “Omnis Studio 6.1 → 8.1 migration; library ClientPortfolio.lbs; class inventory: 84 task classes, 156 window classes, 23 report classes, 12 server task classes; deprecated syntax audit: 7 methods using deprecated $listitem() syntax replaced with $getColVal(); 3 methods using deprecated file I/O commands replaced with $openfile(); DAM session transaction rollback audit: 34 sequence methods containing $startTransaction(); 8 methods missing $rollback() on at least one $endmethod() failure path identified and fixed (including oClientAccount.$updateAccountStatus from the prior production incident); DAM session configuration: SQL Server connection string updated for SQL Server 2019 TLS 1.2 requirement; Omnis 8.1 compatibility test: all 84 task classes executed against production data snapshot; 2 report class pagination differences corrected; migration completed; 31h across 5 sessions.”
Track Omnis Studio developer retainer hours without the status emails
When a 3-hour investigation traces 2–4 afternoon SQL Server lock timeout errors in a portfolio management system to an oClientAccount.$updateAccountStatus sequence method that calls $startTransaction() and $sqlexec UPDATE ClientAccounts then exits via $endmethod(kComplianceFailed) on the compliance check failure without calling $rollback() — leaving the SQL Server DAM transaction open with an exclusive row lock on the ClientAccounts row for the connection lifetime, blocking concurrent client services tasks with error 1222 — the work log must name the method, the UPDATE table, the $endmethod() path that lacked $rollback(), the SQL Server lock diagnostic evidence, and the timeout rate before and after the fix. HourTab gives your Omnis Studio retainer client a public dashboard URL they can bookmark: hours used, hours remaining, and a work log naming the missing $rollback() on the failure branch. No client login. No status emails. CSV in, URL out.
How HourTab tracks Omnis Studio developer retainer hours
Omnis Studio DAM transaction hold bugs caused by $rollback() missing on $endmethod() validation failure paths are invisible in single-task development testing by the same mechanism that makes all multi-user backend lock bugs invisible when only one database connection is exercised at a time. The developer who writes oClientAccount.$updateAccountStatus tests the compliance failure path by running the method with a test account that has incomplete documentation. The method reaches the compliance check at line 14, the check returns kComplianceFailed, and the method exits via $endmethod(kComplianceFailed). The calling window method displays the compliance failure dialog correctly. The developer sees no error and considers the path correctly handled. The SQL Server DAM connection used by the development task holds the open transaction from $startTransaction(), but since there is only one Omnis task running in the development instance, no other task attempts to UPDATE ClientAccounts row iAccountId, and no lock timeout occurs. The SQL Server connection’s sys.dm_tran_locks view would show the exclusive lock if queried, but the developer never queries it during the test — there is no visible symptom to prompt a diagnostic query. In production with 20 concurrent client services tasks sharing a SQL Server connection pool, the collision is visible only when two tasks exercise the same locked row within the lock hold window: one task holding the lock after a compliance failure exit, and another task attempting a concurrent UPDATE or SELECT with UPDLOCK on the same account.
The work log entry that makes Omnis Studio lock work auditable must name every element of the causal chain: the Omnis Studio version, the library name, the sequence method name, the DAM session object, the $startTransaction() call site, the $sqlexec UPDATE table and WHERE clause, the validation failure path that lacked $rollback(), the SQL Server session and lock diagnostic evidence (sys.dm_tran_locks: session ID, resource type, resource description, lock mode; sys.dm_exec_sessions: login name, host name, program name), the blocked sessions, the lock timeout frequency before and after the fix, and the audit result for additional unprotected $endmethod() paths. A log that says “fixed Omnis locking issue, 3h” is not auditable to a portfolio management director, a compliance officer, or an IT manager reviewing change control records for a regulated financial services system. A log that names the method, the SQL Server diagnostic evidence, the specific $endmethod() call that lacked $rollback(), and the before/after timeout rate is auditable, defensible, and builds the trust that sustains a long-term Omnis retainer relationship in regulated environments. HourTab gives Omnis Studio developers a public retainer-hours URL they send to clients — wealth management firms, insurance brokers, professional services organizations, not-for-profit funds, and government departments that run core business operations on Omnis Studio applications backed by SQL Server, PostgreSQL, or Oracle and maintain them with an Omnis specialist on monthly retainer.
The broader context for Omnis Studio retainer billing is that the $endmethod() without $rollback() pattern is the Omnis Studio instantiation of the universal principle that every platform requiring explicit transaction management demands that the developer pair every $startTransaction() with $rollback() on every failure path. Progress OpenEdge ABL developer retainers cover the equivalent in Progress: FIND FIRST EXCLUSIVE-LOCK without RELEASE leaving a record lock on the validation failure branch, and DO TRANSACTION blocks where the failure path exits without rolling back — same invisible single-user test, same multi-user production lock collision. Uniface developer retainers cover the equivalent in Uniface: implicit transaction commit behavior in Uniface TCC (Transaction Coordinator Component) where the developer’s custom code path exits without the expected explicit commit or rollback, leaving backend SQL locks held by the Uniface server connection. Natural developer retainers cover the equivalent in Software AG Natural with Adabas: a Natural subroutine that holds an Adabas record in a “hold” queue without issuing an END TRANSACTION or BACKOUT TRANSACTION on the failure path — same class of invisible enterprise client-server transaction management bug, same pattern of a developer who tests in single-user mode and never observes the multi-user hold queue collision that their missing rollback creates in production.
FAQ: Omnis Studio developer retainers
What does an Omnis Studio developer on retainer typically do?
An Omnis Studio developer on monthly retainer covers DAM transaction rollback audits (reviewing all sequence methods containing $startTransaction() to confirm $rollback() is present on every $endmethod() failure path and every error handler); backend lock timeout diagnosis (querying SQL Server sys.dm_tran_locks, PostgreSQL pg_locks, or Oracle v$lock to identify the DAM connection holding the lock, then tracing it to the sequence method that exited without $rollback()); Omnis Studio window, task, and method development (window classes, task classes, report classes, server task classes, sequence methods, data entry forms); Omnis Studio version migration (4.x/6.x to 8.x/10.x, deprecated syntax replacement, DAM API updates, web client migration); and financial services, insurance, not-for-profit, and government application maintenance for Omnis applications backed by SQL Server, PostgreSQL, or Oracle.
What Omnis Studio DAM transaction debugging work is most commonly underlogged?
Open backend SQL transaction lock hold bugs caused by $rollback() missing on $endmethod() validation failure paths are the most systematically underlogged Omnis Studio retainer work. The pattern: sequence method calls $startTransaction() + $sqlexec UPDATE (acquiring exclusive row lock); developer tests with single task in development; production validation failure causes $endmethod() without $rollback(); SQL Server / PostgreSQL / Oracle DAM transaction remains open with row lock held for connection lifetime; other Omnis tasks receive lock timeout (SQL Server error 1222, PostgreSQL lock_timeout). The work log must name the sequence method, the UPDATE table, the $endmethod() path lacking $rollback(), the backend lock diagnostic evidence, and the timeout rate before and after the fix.
What are typical Omnis Studio developer retainer rates?
Entry-level Omnis Studio developers with experience in basic Omnis scripting, window class development, and DAM session connection configuration typically bill at $65 to $115 per hour. Mid-level Omnis Studio developers with experience in DAM transaction management ($startTransaction, $commit, $rollback), server task class development, Omnis Studio error handling, and backend SQL query optimization typically bill at $95 to $170 per hour. Senior Omnis Studio developers with deep knowledge of Omnis Studio multi-user architecture, connection pool management, web client (Omnis Studio 10+), version migration from 4.x/6.x to 8.x/10.x, REST service development, and vertical-market financial services application architecture typically bill at $145 to $255 per hour. Monthly retainer ranges: $2,500 to $4,500/month for advisory and DAM transaction audits; $4,000 to $8,000/month for active Omnis Studio maintenance and application server administration.
What should an Omnis Studio developer retainer agreement include?
An Omnis Studio developer retainer agreement should specify: Omnis Studio version (4.x, 5.x, 6.x, 8.x, or 10.x); the backend SQL database (SQL Server, PostgreSQL, Oracle, MySQL, or Sybase — lock diagnostic tooling and DAM transaction behavior differ); whether the retainer developer has access to both the Omnis Studio library source and the backend database for running lock diagnostic queries (sys.dm_tran_locks, pg_locks, v$lock); whether the retainer covers a DAM transaction rollback audit (reviewing all sequence methods with $startTransaction() for missing $rollback() on every $endmethod() failure path); whether the retainer covers Omnis application server administration (connection pool configuration, application server log review, connection kill for lock resolution); and whether the retainer includes Omnis Studio version migration scoping for clients on unsupported older versions.
How should Omnis Studio developer retainer hours be logged?
Log each Omnis Studio retainer session with the version, library name, sequence method name, backend database, specific issue, and before/after metric. For DAM transaction not rolled back on $endmethod(): Omnis Studio version (8.1), library (ClientPortfolio.lbs), method (oClientAccount.$updateAccountStatus), backend (SQL Server 2019 PortfolioDB), DAM session ($ctask.$DAMsession), $startTransaction() call site (line 3), $sqlexec UPDATE table and WHERE clause (UPDATE ClientAccounts SET Status = 'Under Review' WHERE AccountId = iAccountId), validation failure path lacking $rollback() (compliance check at line 14: If (compliance_result = kFailed) $endmethod(kComplianceFailed) End if without $rollback()), SQL Server lock diagnostic (session 58, login OMNIS_APP, host APP-SERVER-01, exclusive row lock ClientAccounts page 1 slot 3; blocked sessions 61 and 63), lock timeout errors per afternoon before fix (2–4), fix ($rollback() added before $endmethod(kComplianceFailed) at line 14; 3 additional unprotected $endmethod() paths fixed at lines 21, 28, 35), lock timeout errors per afternoon after fix (0), hours (3h). For Omnis version migration: source/target version, library class count, deprecated syntax replaced, transaction audit count and fixes, DAM configuration updates, hours.