The 6.1 release has added two services namely pub.flow:throwExceptionForRetry and pub.flow:getRetryCount to help overcome the transient errors in triggered services automatically. I tried to test these so as to make sure they work as suggested.
First of all I did not get any examples in WmSamples illustrating their usage.
So I created the following flow to test :
1 INVOKE savePipelineToFile
2 INVOKE debugLog
3 INVOKE getRetryCount (copied the result to myretrycount)
4.11 BRANCH on ‘/myretrycount’
4.111 0: SEQUENCE
4.1111 INVOKE debugLog
4.1112 INVOKE addInts
4.1113 INVOKE debugLog
4.112 1: SEQUENCE
4.1121 INVOKE debugLog
4.113 2: SEQUENCE
4.1131 INVOKE debugLog
4.21 INVOKE getRetryCount
4.22 BRANCH on
4.221 %retryCount%==0: SEQUENCE
4.2211 INVOKE debugLog
4.2212 INVOKE throwExceptionForRetry
4.222 %retryCount%>0: SEQUENCE
4.2221 INVOKE debugLog
The service was made to be triggered by some document. And the step 4.1112 was deliberately made to fail. So actually I should have got it successful the second time round when IS was supposed to have re-tried the service. BUT it did not retry after first failure.
Has anybody tried this?
Please let me know what is going wrong here? My code or webMethods?
The document says that trigger retries are not applicable for service exception, it is only for ISRuntimeExceptions.
BUT the question is: How do we simulate and test this feature?
And of course: How do we code our triggered services to distinguish between the error types and hence use the throwExceptionForRetry Service effectively?
We coded our own service for this.
- Create a java service, no imports needed.
- Put this line in it:
throw new com.wm.app.b2b.server.ISRuntimexception();
IMPORTANT: This cannot be in the catch block. If an error occurs in a flow service, then set a flag and then put a branch statement OUTSIDE of the catch block (outside of all of the sequences in fact) that triggers a call to your new java service in the case of an error. This will move the document back to the broker for redelivery.
WARNING: This should be used for transient conditions like database not available, etc. For bad code issues, it will create an infinite loop on error, so be careful in the use of it.
Why is it required to have this outside the catch block?
Because it won’t work. This was a very specific piece of instruction from webMethods.
The best thing to do is put together a small pub/sub test and watch the fireworks.
But I am still not clear as to how can we DETECT the transient errors in first place to set the flag which can then be used to call the java service that throw com.wm.app.b2b.server.ISRuntimexception(). And I am not sure why would you not use the pub.flow:throwExceptionForRetry directly which is supposed to achieve the same.
If you do not mind, can you share the code that you used to test this.
With developer, you have typically three sequences; one outer sequence and two child inner sequences.
- Outer sequence is set to SUCCESS
- First inner sequence is set to FAILURE (Try Block)
- Second inner sequence is set to DONE. (Catch Block)
What occurs is that the outer sequence is happy if the first inner sequence completes without any failures. But, if any flow steps throw an error, then the flow code jumps down to the second inner child which is set to DONE. With the SEQUENCE set to DONE, it will execute every single flow step whether or not there is an error. While in the catch block, set your flag. When you exit the sequences then place the branch with your call to the java service I mentioned in the other message.
You should read the developer’s guide and download the GEAR best practices guides to help you.
That is right Ray.
That is what I tried in first place. In the code above the step 4 is outer sequence set to exit on success and 4.1 and 4.2 are inner sequences set to exit on failure and done respectively.
Now the question remains that when in catch sequence, what exactly we need to do to check if the exception, that had caused the code to jump in there, is ISRuntimeException or normal program error exception.
In other words: what do we need to check in order to set that FLAG which we will check outside the sequence to throw the retry exception.
The idea is not to check to see if there is an exception, but the understand that by the very nature that you are in the catch block that an error has occurred. If you are concerned about the type of error, and wish to trap, perhaps database errors, then you can filter by error type thrown.
pub.flow:getLastError will extract the very last error from that occurred by the user running the service. Make sure it is the FIRST flow service in the catch block. Otherwise, if something else throws an error in the catch block, it will return that particular error. And since the catch block is set to done, it will continue.
Once you filter and determine that you have a transient error, then you set your flag value that the outside branch executes against.
The main thing that you accomplish with this is to resend the document to the flow.
Of course, if you have db calls and other things running, then you need to use start/commit/rollback or you will not be happy. The rollback should be in the catch block.
This is about the best explanation I can give you. I am using this in 6.01, although it was designed for 6.1.
I think I get it now. Basically I have to judge from the lastError and decide if I can solve it by resending the document. If so then set the flag, otherwise, let it fall thru and log as error.
Thanks once again for taking so much effort for my sake.
I made a test as what what you said above, and I set Deliver Util=Successful in the properties tag of the trigger, but when publish the document and make some runtime exception, the trigger will occur the following error with not retrying the trigger service:
2004-06-23 16:52:17 GMT+08:00 [ISS.0098.0049C] Exception:com.wm.app.b2b.server.I
SRuntimeException: retry while executing trigger. Rejecting Document for Trigger
could you tell me what’s wrong with my test?
I am trying to use the throwExceptionForRetry service but the flow service is not getting triggered again.I created a flow service in where I am calling a divideInts service which throws an error and I am catching that error in CATCH Sequence.After that I am Branching on the flag and in there I am calling the above mentioned Java serice by Ray(I also tried the throwExceptionForRetry service).What it should ideally do is to resubmit the document but this is not happening.It just executes the service once.In the Trigger service I am subscribing to a Publishible Document and from there my Flow service is being called.Can anyone tell me where I am going wrong.Do we need any other settings?Any help is appreciated.
It will definitely work as long as you have the try/catch block set up correctly. Keep in mind that you have to invoke the java service AFTER the try catch block (outside of the block, not within.)
The call to com.wm.app.b2b.server.ISRuntimexception() requeues the document and resets the pointers. The broker does not discard the document until it receives an ack.
I am calling the java service after the Try-Catch block(outside allthe Sequences).This is what I am doing.I have a Publishable Doc generated from a InsertNotification on a table.This document is being subscribed by a Trigger which in turn calls the Flow Service.In my Flow Service, I have Try-Catch set up with sequences.In the 2nd seq(the 1st inside the main seq), I am calling divideInts which I am causing to fail.This error is being caught by 3rd Seq(2nd inside the main seq) where I am setting a retryFlag parameter to say ‘Y’.After these sequences(outside all the seq),I am using a Branch step where if a get a retryFlag=‘Y’, I am calling the java service which throws ISRuntimeException().After doing all these steps I publish the document, but its not getting republished when the error occurs.All this I am doing on IS 6.1.
Today I tried using this with IS 6.0.1. I noticed that if I make a call to any java service which throws a ISRuntimeException() in its code then the trigger works fine(even this thing is not working in IS 6.1).But if I try to use the same set up as discussed in 1st para then it does not work.If if wrap the java service inside a flow service then it is working only if the java service which throws the error is the last step in the flow,i.e outside all seq,branches etc.This thing is not working even if its inside a Branch(again this is working in IS6.0.1 only).I dont know where I am going wrong or what thing I am missing out here.
It sounds like you are doing everything right. Tech Services gave us this workaround in 6.01 for another client - although there is no documentation on it. It is supposedly a feature of 6.1.
I am unable to come up with an explanation for you or a solution. Are you able to submit a service request to webMethods? Then you can share your new found knowledge!
Thanks for spending your time on it.I will raise a SR with webMethods and will take it up from there.But what baffles me is its not working at all in 6.1(even though its released in this version) and tha java code part is working in 6.0.1.
I am working on IS 6.0, and have implemented the retry logic as suggested by Ray.
Its working fine. But in the Monitor there are a lot of entries for a single request.
I need to retry 5 times.
Every time I throw an ISRuntimeException, it adds an entry in the audit log and shows up in the monitor.
So for every request when the backend is down, I get 6 entries in the monitor.5 for ISRuntimeException to retry from the trigger, and 1 more when the retry count has exceeded what is set in the trigger.
So I cant do a resubmit all from the monitor, because if I do that, 6 requests will be sent to the backend instead of 1.
Can you please help me out with this.