Mule documentation states that catch-exception-strategy is similar to java catch block. But unfortunately, the payload is consumed (message is consumed); from the catch block the payload is lost (unlike a java method where you can access the method input parameters from a catch/finally block).
The problem with this design is that at any instance, (from the catch strategy flow) it is impossible to know the error and last known enriched payload which was used (which caused the error?). This complicates auditing of data which caused the error.
Suppose if there is a flow with 10 message processors, it becomes tedious to identify the message processor which threw error.
I can see 2 workarounds regarding the payload:
1) After the inbound endpoint, push the payload to a flow variable before every message processor (again another disadvantage is what happens to the Inbound properties and attachments?)
2) Use Rollback exception strategy with zero attempts (the transaction will be rolled back), and original input message may be available. (drawback: it is difficult to introspect on why the error happend and on which message processor - example: I may have 5 or 6 DB processors)
The reason why this becomes important is supporting an ESB application in production becomes easier.
For example, from the catch-block if we are able to pipe the payload and exception details (linked to a single UID), then you can run a log monitor tool, push it to a real time dashboard for monitoring purpose/raise Alerts. The same approach can be uniformly applied to all the applications/flows and java components, etc.
MMC is weak in this area - for example, if you want to supress Alerts from a batch job after 5 occurrences, MMC cannot do it.
My questions are:
1) Is there any reason on why the payload is made unavailable?
Possible workaround is to push (last known data) to another variable as part of message called originalPayload or originalInboundProperties?
2) Any other straight forward way of piping the exception and payload to an appender (instead of workarounds)?
Ananth Krishnan (WHISHWORKS.com)
Related
I'm creating a Forge application which needs to get version information from a BIM 360 hub. Sometimes it works, but sometimes (usually after the code has already been run once this session) I get the following error:
Exception thrown: 'Autodesk.Forge.Client.ApiException' in mscorlib.dll
Additional information: Error calling GetItem: {
"fault":{
"faultstring":"Unexpected EOF at target",
"detail": {
"errorcode":"messaging.adaptors.http.flow.UnexpectedEOFAtTarget"
}
}
}
The above error will be thrown from a call to an api, such as one of these:
dynamic item = await itemApi.GetItemAsync(projectId, itemId);
dynamic folder = await folderApi.GetFolderAsync(projectId, folderId);
var folders = await projectApi.GetProjectTopFoldersAsync(hubId, projectId);
Where the apis are initialized as follows:
ItemsApi itemApi = new ItemsApi();
itemApi.Configuration.AccessToken = Credentials.TokenInternal;
The Ids (such as 'projectId', 'itemId', etc.) don't seem to be any different when this error is thrown and when it isn't, so I'm not sure what is causing the error.
I based my application on the .Net version of this tutorial: http://learnforge.autodesk.io/#/datamanagement/hubs/net
But I adapted it so I can retrieve multiple nodes asynchronously (for example, all of the nodes a user has access to) without changing the jstree. I did this to allow extracting information in the background without disrupting the user's workflow. The main change I made was to add another Route on the server side that calls "GetTreeNodeAsync" (from the tutorial) asynchronously on the root of the tree and then calls it on each of the returned children, then each of their children, and so on. The function waits until all of the nodes are processed using Task.WhenAll, then returns data from each of the nodes to the client;
This means that there could be many api calls running asynchronously, and there might be duplicate api calls if a node was already opened in the jstree and then it's information is requested for the background extraction, or if the background extraction happens more than once. This seems to be when the error is most likely to happen.
I was wondering if anyone else has encountered this error, and if you know what I can do to avoid it, or how to recover when it is caught. Currently, after this error occurs, it seems that every other api call will throw this error as well, and the only way I've found to fix it is to rerun the code (I use Visual Studio so I just rerun the server and client, and my browser launches automatically)
Those are sporadic errors from our apigee router due to latency issues in the authorization process that we are currently looking into internally.
When they occur please cease all your upcoming requests, wait for a few minutes and retry again. Take a look at stuff like this or this to help you out.
And our existing reports calling out similar errors seem to point to concurrency as one of the factors leading up to the issue so you might also want to limit your concurrent requests and see if that mitigate the issue.
Thinking of 'production' usage of Orion Context Broker, I wonder what kind of guarantees are provided by the Orion Context Broker in terms of delivery of messages -- both from producer and consumer perspective? In particular, keeping in mind various possible failure scenarios (CB failure/restart, network transient failure, consumer failure/restart, etc), as well as possibility of resource congestion in the CB. Few examples:
1) if a context update operation succeeds, is it guaranteed that consequent queries will return the latest data (e.g., even if CB failed right after acknowledging the update request, and then restarted)?
2) if a consumer subscribed for certain context information, is it guaranteed that it will receive all the relevant updates -- exactly once, at least once, or even at all? (e.g., in case of transient network failure between CB and the consumer)
3) if a consumer updated its subscription, is it guaranteed that the consequent updates will accurately reflect it? (e.g., if CB failed right after acknowledging the subscription request, and then restarted)
4) if a consumer is subscribed for context changes ('onchange', no throttling), and there are multiple consequent updates from the producer affecting the same attribute, is it guaranteed that each of the changes will be sent (or some might be skipped -- e.g., due to too many notifications that CB needs to send during a certain period of time), in any particular order?
etc...
Thanks!
Answering bullet by bullet:
In general, if the client receives a 2xx response (inside of the response payload in the case of NGSIv1, HTTP response code in the case of NGSIv2) it can assume that the update has been persisted in context database, so subsequent queries will return that data (except in the case of running CB with -writeConcern 0 if the DB fails before the update can be persisted from DB memory to disk).
In order to keep things simpler, CB uses a "fire and forget" notification policy. However, CB can be combined with HTTP relaying software (e.g. Rush, event buses, etc.) in order to implement retries, etc.
Similar to case 1, if the client receives a 2xx response (inside of the response payload in the case of NGSIv1, HTTP response code in the case of NGSIv2) it can assume that the update has been persisted in context database (except in the case of running CB with -writeConcern 0 if the DB fails before the update can be persisted from DB memory to disk), so notifications of such data (due to either existing subscriptions or new ones) will use the new value.
All notifications will be sent as long as thread saturation (in the case of -notificationMode transient) or queue saturation (-notification threadpool:q:n) don't occur. You can find more information about notification modes in Orion documentation.
I have a sequential workflow, which is hosted in IIS as a Workflow Service.
My workflow starts with a ReceiveActivity, and inside the ReceiveActivity a call is made to a WCF service with a SendActivity. If this call receives an exception, there is a FaultHandlerActivity on my ReceiveActivity which is meant to handle the call, and send a default value back to the client.
What is happening in my client is that an exception on the SendActivity is bubbling back to the client as a FaultException, even though my FaultHandlerActivity is running (I verified this by logging the beginning and end of the single CodeActivity in my fault handler)
My question is: How can I swallow exceptions ocurring in the SendActivity, without a FaultException being returned to the client?
OK, I figured it out.
My receiveActivity had a fault handler directly on it. What happens then is that if any child activity raises an exception, the fault handler on the receive activity is invoked, and it is also set to a Faulted state, and the exception received is returned to the client application - whether I wanted that or not.
The solution was to add a sequence activity inside the receiveActivity, do all of the processing inside the sequence activity, and add a faultHandlerActivity to the Sequence, which sets up my default return value.
The receive activity is never faulted, and the exception is not returned to my client, but the default value set up in the Sequence's FaultHandler is returned.
Hopefully this will help someone else with the same issue
I have an orchestration that receives an XML with some email properties(like: to, from, cc, subject, etc..).
Then I want to send the emailmessage with a dynamic port (and I assigned some of the values according the input xml). After the email has been sent, I want to do some further processing but that processing may only execute when the mail has been delivered succesfully on the SMTP server.
In the functional design they want to have a retry per hour and maximum of one day, after that periode a message must be in the EventLog when it cannot be delivered successfully.
Therefore I set the dynamic port with the context properties BTS.RetryCount to 23 and BTS.RetryInterval to 60.
I have set the dynamic SMTP port delivery notification to "Transmitted" and I have a catch exception block to catch the DeliveryFailureException.
Is this enough ?
It is a litte bit confusing for me reading several blogs if I should mark the scope Synchronized...
Patrick,
You're right, the documentation on this aspect of BizTalk delivery notification is scarce and confusing. After extensive testing, I have not been able to identify a difference wether the Scope is set to Synchronized = true; or not.
The official documentation for the Synchronized setting only applies to shared variables when used in both branches of a Parallel execution.
As for the Delivery Notification itself, I'm currently facing a problem in production where the FILE adapter produces its ACK event before the entire contents of the file is written to the output folder - it renders this part of the solutiong useless!
Where should I be logging exceptions? At the data service tier(ExecuteDataSet, etc.) and/or at the data access layer and/or at the business layer?
At a physical tier boundary.
Also in the top-level exception handler in the client.
I.e. if your business tier is running on a server, log exceptions before propagating to the client. This is easy if you're exposing your business tier as WCF web services, you can implement an error handler that does the logging before propagating a SOAP fault to the client.
If you are throwing the exception you should log it when it occurs and then bubble it up. Otherwise only the end user should log an exception (you may have lots of tracing on of course in which case it may get logged quite a bit).
The end user may be a UI component or a Service or something...
If you handle an exception in you code somewhere - then that is the end user and you should log it there. In most apps and in most cases it should be logged by the UI when it displays the error message to the user.
I usually allow exceptions to propagate up and log them when they reach the very top level. For example
main {
try {
application code
} catch {
preform logging
}
}
But that only makes sense for fatal exceptions. Other exceptions I usually log them in the block that handles the recover from said exception.