JoobObjectLockedException

A JoobObjectLockedException is thrown when a lock request cannot be granted within the specified lock timeout interval, due to incompatible locks held by other JADE sessions.

The JoobObjectLockedException object properties that indicate details about the lock request and the JADE session that had the object locked at the time are listed in the following table.

Property Type Description
LockTarget ObjectId The object requested to be locked
LockType LockType The requested lock type
LockDuration LockDuration The requested lock duration - Transaction or Session
LockTimeout TimeSpan The requested lock timeout period
TargetLockedBy ObjectId The JADE session that had the object locked

If required, you can repeat an explicit lock request, by using a catch block and a loop. This provides a way to extend the lock timeout period in certain circumstances; for example:

bool locked = false;
int  retries = 0;
while ( !locked )
{
    try
    {
        context.Lock(obj1, LockType.Update, LockDuration.Transaction,
                           TimeSpan.FromSeconds(4) );
        locked = true;
    }
    catch (JoobObjectLockedException ex)
    {
        if ( ++retries > 5 )
             throw ex;
        Console.WriteLine("Object{0} locked by {1} – retrying", obj1.ToString(),
                          ex.TargetLockedBy.ToString());
    }
}

The exception can be avoided, by using the JoobContext TryLock method. This method returns true or false, to indicate the outcome of the lock request, instead of throwing an exception if the request times out; for example:

if ( !context.TryLock(obj1, LockType.Exclusive, LockDuration.Transaction,
                      TimeSpan.FromSeconds(4)) )
{
    Console.WriteLine("Could not lock {0}", obj1.ToString());
}

Although the TryLock method does not result in a JoobObjectLockedException being thrown, a JoobDeadlockException can still occur.

A JoobObjectLockedException can be thrown as a result of an implicit lock request made by JADE. Implicit lock requests happen when JADE collections are accessed, or objects get implicitly locked for updating, including during inverse maintenance to automatically update collections. For implicit lock requests, the default lock timeout period is specified in the ServerTimeout parameter in the [JadeServer] section of the JADE initialization file.

For straightforward implicit lock requests, it may be appropriate to catch the exception and retry the operation that resulted in the implicit lock request, if a longer timeout period was wanted. However, when a JoobObjectLockedException is thrown during inverse maintenance (for example, when changing the collection parent reference), the transaction is automatically rolled back, so the operation cannot be retried without reprocessing the whole transaction. The transaction is rolled back in order to maintain referential integrity, which can be compromised if inverse maintenance is not completed.

A catch block can check if the transaction has been rolled back by checking the JoobConnection IsTransactionActive property; for example:

try
{
    Member member = new Member();
    member.Id = 99;
    member.MyOwner = owner;
    // ...
}
catch
{
    if ( !context.Connection.IsTransactionActive )
    {
        Console.WriteLine("Transaction was automatically rolled back");
    }
    else
        tran.Rollback();
}

As an alternative, the code can avoid lock exceptions on implicit locks by instead explicitly locking collections before the operation involving inverse maintenance.

When update locks are being used, a lock exception can be thrown when committing a JADE transaction. This happens if an update lock cannot be upgraded to an exclusive lock. In this circumstance, the transaction will have been rolled back. A catch block can be used to detect this, for example:

using (System.Data.IDbTransaction tran = context.BeginTransaction())
{
    // ...
    try
    {
        tran.Commit();
    }
    catch
    {
        Console.WriteLine("Could not commit transaction due to an exception");
    }
}