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

What’s the reasoning behind this?

So that the returned transaction ID can be accessed within the try and the catch blocks. If you do the startTransaction in the try, the returned ID will not be readily available in the catch block.

Thanks Rob… you’re a damn genius

I am not sure if I understood this. Can you guys elaborate with an example flow please.

So, you could call this pattern the “Try, Try Again” approach. :slight_smile:

I assume you’re familiar with startTransaction and commitTransaction/rollbackTransaction services and how they are to be used.

If one structures the service this way:

SEQUENCE (exit on success)
–SEQUENCE (exit on failure)
----startTransaction (returns an ID)
----commitTransaction (accepts ID as input)
–SEQUENCE (exit on done)
----rollbackTransaction (accepts ID as input)

In this case, the ID returned by startTransaction will not be at the “root” level of the pipeline, and rollbackTransaction will not do anything.

There are two approaches that can be used to address this.

  1. If one calls getLastError, the ID can be retrieved from the pipeline var in the returned document. This is a relatively non-obvious solution but can be effective.

  2. Restructure the service this way:

startTransaction (returns an ID)
SEQUENCE (exit on success)
–SEQUENCE (exit on failure)
----commitTransaction (accepts ID as input)
–SEQUENCE (exit on done)
----rollbackTransaction (accepts ID as input)

In this case, the transaction ID will be in the “root” level of the pipeline and one does not need to get the ID out of the lastError structure.

just curious how long have u been involved with webmethods…

I started with Active Software stuff (what is now Broker Server) in '98. When wM acquired Active in 2000 I started working with B2B Server (now IS). Pretty much been doing this sort of work since then, with a 1 year hiatus when I worked an integration project that didn’t use wM products.

the catch block will be executed if any exception occurs in try block. in this case if we start the tx in try block and an exception occurs, the tx id will still be available in catch block(anyway the pipeline data will be carried to catch block).
what the use of starting the tx outside the try catch block?

Not so. In Developer it looks like the pipeline is intact in the catch block but at run-time it is not. Give it a shot with this simple example:

    1.1 SEQUENCE (exit on FAILURE)
        1.1.1 MAP (set aVar to some value)
        1.1.2 EXIT '$parent' and signal failure
    1.2 SEQUENCE (exit on DONE)
        1.2.1 BRANCH on '/aVar'
   /[^ ]/ MAP (set bVar to some value)
   $default: MAP (set cVar to some value)

When run, only cVar will be shown in the results pane.

I have two questions from this.

  1. If i am not wrong the signal failure(exit flow or exit parent) step, causes the control to return to catch block and execute the statements under catch block?!!!

  2. That means the pipeline variable values in try block are not accesseble in catch block.
    But i found assigning the variables of try block to variables in catch block!!.
    for eg: after the getLastError, to publish an Exception, the variables of try block are assigned to variables of some service in catch block that publishes the exception!.

  1. Correct. The exit step was in the example to simulate an exception such as one might get when calling a DB adapter service. Control does indeed pass to the catch block and the steps there are executed.

  2. The variables created in the try block will not be directly accessible in the catch block. One can do assignments with no problem but if those assignments use a source variable that was created in the try block, the target variable will not get a value at run-time.

Is there a specific code example that you’re wondering about?

That one way of doing it. I like the StartTransaction in my Try, since it goes to my catch, if error, and gives me nice little email or something.

I usually use a MAP step after getLastError to restore pipelines.

SEQUENCE (exit on success)
–SEQUENCE (exit on failure)
----startTransaction (returns an ID)
----commitTransaction (accepts ID as input)
–SEQUENCE (exit on done)
getLastError (map error pipeline to Doctype say “myPipeline”)
MAP (map any fields you want to restore to “myPipeline”)
----rollbackTransaction (accepts ID as input)

This should work as well…

That’s correct. This is the approach I mentioned earlier: “1) If one calls getLastError, the ID can be retrieved from the pipeline var in the returned document. This is a relatively non-obvious solution but can be effective.” . Thanks to Rocky for posting the example.

my doubt is not cleared regarding accessing the pipeline vars in catch block.

For eg:
SEQUENCE(exit on success)
–SEQUENCE(exit on failure)
-----MAP(get currentDateTime and assign that value to txId variable)
-----startTransaction(assign txId to transactionName var of startTransactionInput)
-----commitTransaction(assign transactionName var of startTransactionOutput to transactionName var of commitTransactionInput)
–SEQUENCE(exit on done)
—rollbackTransaction(assign transactionName var of startTransactionOutput to transactionName var of rollbackTranscationInput)

Now my doubt is : Even if we created a txId var and assigned it to transactionName var of startTransaction service, when an exception occurs, the transaction(transactionName assigned to rollbackTransaction) is rollbacked.In this case we are still using the var of try block in catch block assignments!!

Can you post screen shots of your getLastError and rollbackTransaction calls?

Given what you described, the transaction may appear in Developer to be rolled back but at runtime it isn’t because startTransaction (and its field, transactionName) won’t exist at the root level in the pipeline. In other words, your catch block may not be working the way you expect.

Here are the screen shots:

  1. startTransaction in try block. transactionName is the currentDateString

  2. rollbackTransaction in catch block.

You’re going to need to upload the jpg file using the attachment facilities of the forum. Click the “Go Advanced” button below and attach your screen shots.

Sorry , i was unable to send the screen shots properly in my last post.
i am sending as a zip file
hope i did better now!

The screenshots don’t show everything, so I can’t tell if the service is mapping the startTransactionOutput record from the lastError/pipeline. If it is, then the catch block will function as you are expecting. If you are not mapping startTransactionOutput from the lastError/pipeline document, then the call to rollbackTransaction is doing nothing because rollbackTransactionInput/transactionName will be null.