0

We have been facing this strange error on some insert/update/delete calls to some of the table methods where there is some other code inside these methods which is also using ttsbegin/ttscommit in AX 2012 Feature pack.

ttsbegin and ttscommit is balanced on all levels and declared on same levels every place they are used inside code.

I find this behavior very strange as same code is working in another environment which does have same specifications.

Could it be some kernel related issue?

Same error does sometimes occur when deleting multiple lines on CustTable form for instance. Any idea what it could be?

Jan B. Kjeldsen
  • 17,817
  • 5
  • 32
  • 50
Umer Ejaz
  • 7
  • 1
  • 2
  • Are there any try/catch blocks that are also around the transaction? In certain circumstances those can call ttsabort prior to the ttscommit, causing an imbalance in TTS levels. I would also recommend running step-by-step in the debugger to identify if another method is throwing the error (keeping an eye on the TTS level on the bottom of the debug window). – kingofzeal Jan 27 '15 at 16:02
  • See also http://stackoverflow.com/q/27243714/4509 – Jan B. Kjeldsen Jan 28 '15 at 08:22
  • Try/catch is not the cause, as any throw aborts the transaction. – Jan B. Kjeldsen Jan 28 '15 at 08:23
  • 1
    Check your client/kernel version. I experienced some similar behavior where the versions did not match. Also I assume you already took care of the usual suspects (compile, full cil compile, aos restart, database sync). – FH-Inway Jan 28 '15 at 12:17

3 Answers3

2

As general information to transaction in combination with try-catch:

The general rule is that exceptions are caught in the outer most catch, where the ttslevel is 0. This means that if you put a transaction around a try/catch, your exceptions will not be caught. The following two jobs demonstrate that:

Transaction inside try/catch: try { ttsBegin; throw error("an error"); ttsCommit; } catch {
info("error caught"); }

Output:

Error an error
Info error caught

Try/catch inside transaction: ttsBegin; try { throw error("an error");
} catch {
info("error caught"); } ttsCommit;

Output:

Error an error

As you can see, the error is not caught when the transaction is around the try catch.

However, there are two exceptions to this rule. The following code demonstrates that UpdateConflict and DupplicateKeyException can be caught inside a transaction. Set set = new Set(Types::Enum); // a set containing all possible exceptions SetEnumerator se; // enumerator used to loop though the set with exception Exception exception; // used to cast the value from the set boolean caughtInside; ;

// add all exception to a set
set.add(Exception::Break);
set.add(Exception::CLRError);
set.add(Exception::CodeAccessSecurity);
set.add(Exception::DDEerror);
set.add(Exception::Deadlock);
set.add(Exception::DuplicateKeyException);
set.add(Exception::DuplicateKeyExceptionNotRecovered);
set.add(Exception::Error);
set.add(Exception::Info);
set.add(Exception::Internal);
set.add(Exception::Numeric);
set.add(Exception::PassClrObjectAcrossTiers);
set.add(Exception::Sequence);
set.add(Exception::Timeout);
set.add(Exception::UpdateConflict);
set.add(Exception::UpdateConflictNotRecovered);
set.add(Exception::Warning);

// create enumerator
se = set.getEnumerator();

// loop all exceptions
while(se.moveNext())
{
    // set flag false
    caughtInside = false;
    // begin outer try catch
    try
    {
        ttsBegin;
        // begin inner try catch
        try
        {
            // cast exception
            exception = se.current();
            // trhow exception
            throw exception;
        }
        catch
        {
            // set flag to indicate the exception was caught inside the transaction
            caughtInside = true;

            warning(strFmt("%1 can be caught inside transaction", exception));
            // throw exception again to catch it outside of transaction
            throw exception;
        }
        ttsCommit;
    }
    catch
    {
        // for once, it's ok to catch everyting :)  

        if(caughtInside)
        {
            warning(strFmt("%1 can also be caught outside of the transaction", exception));
        }
        else
        {
            info(strFmt("%1 can only be caught outside of the transaction", exception));
        }

    }
}

Output:

Info Info can only be caught outside of the transaction
Info Warning can only be caught outside of the transaction
Info Deadlock can only be caught outside of the transaction
Info Error can only be caught outside of the transaction
Info Internal can only be caught outside of the transaction
Info Break can only be caught outside of the transaction
Info DDEerror can only be caught outside of the transaction
Info Sequence can only be caught outside of the transaction
Info Numeric can only be caught outside of the transaction
Info CLRError can only be caught outside of the transaction
Info CodeAccessSecurity can only be caught outside of the transaction
Warning UpdateConflict can be caught inside transaction
Warning UpdateConflict can also be caught outside of the transaction
Info UpdateConflictNotRecovered can only be caught outside of the transaction
Warning DuplicateKeyException can be caught inside transaction
Warning DuplicateKeyException can also be caught outside of the transaction
Info DuplicateKeyExceptionNotRecovered can only be caught outside of the transaction
Info Timeout can only be caught outside of the transaction
Info PassClrObjectAcrossTiers can only be caught outside of the transaction 

It is also noteworthy that, when you enter a catch block, there has been a implicit ttsabort, so the transaction has been rolled back. However this is not true for UpdateConflict and DuplicateKeyException when they were caught inside a transaction.

Source: http://www.artofcreation.be/2011/08/10/try-catch-and-transactions/

Dark Smile
  • 65
  • 4
1

Calling return between ttsbegin and ttscommit is a no-go.

Also, the problem may be caused by any imbalance introduced in any code called by the code, fx insert or update methods.

Jan B. Kjeldsen
  • 17,817
  • 5
  • 32
  • 50
0

I have now localized the error in code. Deep down inside the code on 5th ttslevel there was a customization in an insert method of ContactPerson table in VAR layer .. I know its very strange but we have newly overtaken this customer so this was clearly sign of a poorly managed test environment. After removing one TTSCOMMIT which was one too many things have obviously started working. This was my first post in forum and I am impressed with the response you guys have given me. I am very grateful for all help you guys have given on this case. I hope to return some in future :)

Umer Ejaz
  • 7
  • 1
  • 2