Pessimistic Locking

Pessimistic locking can be used when there is a high probability of simultaneous editing of a single entity instance. In such cases the optimistic locking, based on entity versioning, usually creates too many collisions.

Pessimistic locking explicitly locks an entity instance when it is opened in the UI detail view. As a result, only one user can edit this particular entity instance in a given moment.

The Jmix pessimistic locking mechanism can also be used to manage simultaneous execution of arbitrary processes. The locks are distributed, since they are replicated in the cluster.

Installation

For automatic installation through Jmix Marketplace, follow instructions in the Add-ons section.

For manual installation, add the following dependencies to your build.gradle:

implementation 'io.jmix.pessimisticlock:jmix-pessimisticlock-starter'
implementation 'io.jmix.pessimisticlock:jmix-pessimisticlock-flowui-starter'

Important Note for Single Menu Mode Applications

If your application uses Single menu mode, you should manually add menu items after installing an add-on.

  1. Open the Menu Designer in Jmix Studio.

  2. Navigate to the Structure tab.

  3. Available menu items are displayed in the left panel.

    add menu items
  4. To add items:

    • Select the desired items and click the > (Add Selected) button.

    • Or, drag-and-drop them from the left panel into the current menu structure on the right.

This step is required because applications in Single menu mode do not automatically merge add-on menus with the existing structure.

Usage

To enable pessimistic locking for any entity, add the @PessimisticLock annotation to the entity class, for example:

@PessimisticLock(timeoutSec = 120)
@JmixEntity
@Table(name = "DOCUMENT")
@Entity
public class Document {
// ...

The standard entity detail view automatically handles pessimistic locking by switching to read-only mode if the entity is locked by someone else.

You can also lock an entity in your own code using the LockManager bean. For example:

@Autowired
private LockManager lockManager;

public void lockAndProcessDocument(Document document) {
    LockInfo lockInfo = lockManager.lock(document);
    if (lockInfo != null) {
        throw new IllegalStateException("Document is already locked by " +
                lockInfo.getUsername());
    }
    try {
        processDocument(document);
    } finally {
        lockManager.unlock(document);
    }
}

See the Javadocs of the LockManager interface for more information.

Lock Expiration

The timeoutSec annotation attribute defines the lock expiration timeout in seconds. It is 300 sec by default.

The automatic lock expiration requires the Quartz job scheduler. You can provide it by including the Quartz add-on in your project.

The following application properties control the expiration mechanism:

  • Set jmix.pslock.use-default-quartz-configuration to false if you want to disable the default expiration mechanism. This property is true by default.

  • Use jmix.pslock.expiration-cron to set a Cron expression for expiration schedule. This property has 0 * * * * ? value by default, which means "every minute".

Locks Admin UI

Current state of locks can be tracked through the Pessimistic Locking → Locks view. This view also enables unlocking of any object.