Skip to main content

Adding Atomicity: introducing the Scope

Atomicity is the first line of defense for data quality, ensuring that every database change within a transaction is "all or nothing." All object changes (mutations) must succeed, or every single one must be discarded.

Example: All or nothing behavior

Suppose you have an Order-line entity that contains an amount. The Order-line entity is associated to the Order entity that stores the total order amount. The total order amount is the sum of all Order-line amounts.

Suppose you change the Order-line amount. Because the Order's total amount depends on the Order-line, the Order must also be updated. To achieve Atomicity (the "all or nothing" guarantee), both the updated Order-line and the updated Order object must succeed in being saved, or both must be completely canceled (rolled back) at the same time

1. Introducing the Scope

To manage Atomicity, we use the concept of the scope. The scope is the collection of all objects that are part of a single business transaction and must be treated as a unit.

The scope contains mutated objects (creations, changes or deletions).

Special care should be taken in situations where objects are associated with a 1:1 association, because mutating one side of the association is also changing the other side as well. In that case both objects should be placed on the scope.

2. The Atomicity Pattern for Mendix

To add reliable Atomicity to Mendix apps, you must create a clear, defined scope that contains all manipulated objects and manage its commit/rollback process rigorously. This is achieved through three basic design patterns.

2.1. Pattern 1: Creating a scope

A scope is simply a way to collect objects for a single commit. Defining the scope is generally the responsibility of the microflow that starts the transaction. The most common structures found in enterprise Mendix projects are:

  • List-based Scope: The scope consists of Microflow Variables that hold lists of changed objects. These lists are passed through the microflow hierarchy and committed together at the end of the transaction.
  • Main Object Scope: The scope is implicit. Instead of a special helper object, one of the main transaction objects itself is seen as the helper object. The scope is constructed by the final commit step by retrieving all mutated objects that are associated to the main object.
  • Helper Object Scope: This pattern uses a special Non-Persistent Entity (NPE) to act as the transactional root. This helper object links to all the other changed objects. It travels through the microflow chain, and when the final commit microflow runs, it uses the helper object to retrieve and save all the associated objects together as one unit. This scope type is used by Menditect. Details of this scope type will be part of a next publication of the Menditect Testability Framework.

Each of these scope approaches have been found in customer projects that are researched by Menditect.

2.2. Pattern 2: Adding mutated objects to the scope

Adding mutated objects to the scope is the responsibility of the microflow that induced the mutation. The two primary locations for this are:

Discipline is key: changing the scope in other microflow typologies is strongly discouraged. It breaches the Atomicity principle by scattering the transaction logic across unrelated parts of the application, leading to unpredictable results.

2.3. Pattern 3: Committing the scope

Saving or deleting the objects placed on the scope is the single responsibility of the dedicated Commit Microflow Typology (CMT). This pattern ensures the right elements on the scope are committed -or rolled back- as one unit.

This microflow pattern incorporates the following steps:

The CMT pattern must incorporate the following sequence:

  1. Retrieve Scope Objects: Gather all objects marked for mutation (this step is only used with the Main Object Scope).
  2. Validate Scope: Perform all necessary business rules checks (see Adding Consistency).
  3. Execute Database Action: Perform the Mendix Commit or Delete action on the scope objects. Critical Note: If a Commit or Delete action fails, Mendix automatically resets all modified objects in memory back to the state they held at the start of the transaction.
  4. Guarantee Rollback: If one of the validations fails, rollback all objects that are not manipulated by the touchpoint. Read the page about the List based scope how to separate touchpoint changes from non-touchpoint changes.
  5. Finalize (Optional): If successful, execute optional steps like finalizing the transaction and cleaning up the scope (e.g., deleting the Non-Persistent Helper Object).
warning

If Mendix commit actions are implemented outside of a dedicated CMT Microflow, you are bypassing the structural guarantee of Atomicity and must manually implement robust error handling around every single commit to protect data integrity.