Why should a *startTransaction* go outside a *Try/Catch* block?

Attached are the screen shots for getLastError and rollbackTransaction.

Is this the right way to rollback a transaction in catch block if we start the Tx in try block?

The screen shots are missing.

Hi,

I am starting the Tx in try block and committing in the same block.
FYI, the currentDateString is the transcationName.
I am rollbacking the Tx after invoking the getLastError service.

I am attaching the screenshots that involves :

  1. getLastError pipeline
  2. rollbackTransaction

Can you please confirm whether i am following the right procedure in rollbacking the transaction.

Many thanks
screenshots.zip (85.5 KB)

Almost right. Instead of this:

pipeline
…transactionName

The mapping from the source var needs to be:

pipeline
…startTransactionOutput
…transactionName

Thanks Rob

ok guys ,tell me one thing lets say i write the service as below
MAIN
TRY
Start transaction ( set the transaction name = hello)
----
----

Commit transaction( set the transaction name =hello)
CATCH
getlasterror
Rollback Transaction ( set the transaction name = hello)

i guess this should work …becouse all the transaction names are set values(hardcoded).
–sri

And the best practice is alwyas put the start transaction outside the try block …its better u kick off the service with start transaction and continue…
But the above procedure should still work

-sri

I believe that would only work in a single threaded environment. If you call the service from a couple of threads, your transactions will become confused.

I don’t know if this qualifies as “best practice.” Either approach, startTransaction outside or inside the try block, is workable.

Correct me if I am wrong…I think startTransaction inside try block should be a better option as this gives us the ability to start the transaction at a later stage so as to keep the transaction time minimum with the DB instead of opening it up before Try block and having the transaction open for longer time…Keeping it inside TRY block will help us achieve transaction with DB in a least time.

Thanks,
Puneet Verma

Are you saying that this structure:

startTransaction
SEQUENCE (exit on success)
…SEQUENCE (exit on failure)
…(call an adapter service)
…(call an adapter service)
…endTransaction (commit)
…SEQUENCE (exit on done)
…getLastError
…endTransaction (rollback)

is slower than this structure?

SEQUENCE (exit on success)
…SEQUENCE (exit on failure)
…startTransaction
…(call an adapter service)
…endTransaction (commit)
…SEQUENCE (exit on done)
…getLastError
…endTransaction (rollback)

What makes you say that? I agree that steps within the start and end should be minimized, but I don’t believe the SEQUENCE blocks add any execution time. However, I’ve never measured so I’m not 100% certain.

No…In the structure you mentioned there might not be comparable difference.But consider these structures…

Case 1:
startTransaction
SEQUENCE (exit on success)
…SEQUENCE (exit on failure)
…(map data)
…(some other logic step)
…(call an adapter service)
…endTransaction (commit)
…SEQUENCE (exit on done)
…getLastError
…endTransaction (rollback)

Case 2:

SEQUENCE (exit on success)
…SEQUENCE (exit on failure)
…(map data)
…(some other logic step)
…startTransaction
…(call an adapter service)
…endTransaction (commit)
…SEQUENCE (exit on done)
…getLastError
…endTransaction (rollback)

In this scenario , Case 2 would be a better approach to have the startTransaction just before we do any DB operation instead of Case 1 where the startTransaction is before Try block and we keep the Transaction with DB open for unnecessarily longer time when the same can be achieved using Case 2 in a better and more efficient way.

Thanks,
Puneet Verma

Thanks for the clarification. Your first post implied that simply moving the startTransaction step outside of the try/catch block would improve things. It didn’t mention any non-adapter service steps between the start and end.

I agree that between startTransaction and endTransaction, the number of steps should be kept to a minimum. Ideally, the only step(s) would be adapter services.

When an exception occurs, the pipeline rolls back to the state it was in before the “try” block (This can be pesky to debug). Putting the startTransaction before the try block ensures that if there is an exception, the transaction information isn’t wiped out of the pipeline.

I missed something here… which situation will only work in a single threaded environment?

Thanks!

This can be considered as best practice to all this discussion of where to put the startTransaction and how to retrieve the “transactionName” value in the catch block!!

write a generic svc which returns “unique_id” as the output… search on wmusers to get an idea on how to implement it… call this “generateRefID” svc

-----generateRefID (assign the value to transactionRefID variable)
SEQUENCE(exit on success)
–SEQUENCE(exit on failure)
-----startTransaction(assign transactionRefID to transactionName var of startTransactionInput)
-----commitTransaction(assign transactionRefID var to transactionName var of commitTransactionInput)
–SEQUENCE(exit on done)
—getLatError
—rollbackTransaction(assign transactionRefID var to transactionName var of rollbackTranscationInput)

I hope this should end most of the discussion on this topic!!

when you hard code the transactionName to something static like “hello” !!

Hi Saurab,
What you suggest will work just fine. We follow a transaction management best practice as below which does not require to create a unigueID. This is already handled by the stratTransaction service. WM BIS guide says this with respect to startTransactionInput / transactionName- “Specifies the name of the transaction to be started. If you leave this parameter blank, Integration Server will generate a name for you. In most implementations it is not necessary to provide your own transaction name”

  1. Always use “startTransaction” service outside TRY/CATCH block, “commitTransaction” service inside TRY block and “rollbackTransaction” in the CATCH block.
    2. Do not explicitly set “transactionName” property for start transaction service. It is an optional parameter. Instead use the “startTransactionOutput/transactionName” variable returned by “startTransaction” service. Use this transactionName to commit/rollback the transaction.
    3. You may explicitly set transactionName when the service is serialized but it is not required.
    4. When dealing with nested transactions involving distributed transaction support, give additional care while developing your integration logic. In this case do not explicitly set the transaction name property. Instead use the “startTransactionOutput/transactionName” variable returned by “startTransaction” service for the appropriate levels of transaction and allow system to handle it.
    By calling the startTransaction inside TRY sequence we have to explicitly map it back from the pipeline and pass it to tollbackTransaction service. As IS rollsback the pipeline to the beign of TRY sequence in case of a failure it gives the CATCH sequence to access the transactionName straightaway.
    cheers,
    Sampath

I dunno if this qualifies as “best practice.” It’s just one way to do things. (I’m not a big fan of “best practice”–it has become an overloaded term that seems to have lost meaning, much the way “canonical” is meaninglessly bandied about.)

This is unnecessary. A call to startTransaction with a null transactionName will generate one for you. No need to reinvent a way to create an ID.

I had thought the discussion was pretty much over when the two approaches had been posted by the 6th post in this thread! But now we’re on the 4th page of posts. Perhaps there is enough info now.

Thread closed. Topic beat to death (and then some).