Throw UnhandledEventException if the event is filtered - masstransit

I've a scenario where a certain filter has to be matched before we can transition into a new state. So i've setup a filter, and registerd OnUnhandledEvent to throw exceptions if the event isn't handled. Unfortunately, it doesn't throw any errors. Automatonymous seems to mark this as handled because we are in the right state to handle the event.
Is there an option to manually throw an UnhandledException?
During(
this.ToBeReviewed,
When(this.Approve, IsCreatedByOtherUserAccountId())
.TransitionTo(this.Approved)
.Then(AddUserAcceptedEvent));
OnUnhandledEvent(x => x.Throw()); // Not working because the event is filtered above

You could throw the exception yourself. The state machine isn't going to throw if you're in a state that handles the event.
.Then(_ => throw new UnhandledEventException);

Related

PushStreamContent and exceptions in the middle of streaming/serializing

We're using PushStreamContent to stream some large lumps with Content-Disposition headers set and the like. As a number of people have discovered, the drawback is what happens when something goes wrong in the streaming?
At the very least, we were trying to get the error logged on our side so someone could follow up.
Recently, I ran into a weird situation. Putting a try/catch around the streaming function worked well enough for errors encountered before you actually started streaming (i.e. errors in sql queries and the like), but if the error occurred later (like in the serialization), the catch block doesn't fire.
Would anyone have any idea why that is?
e.g.
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
try
{
response.Content = new PushStreamContent((stream, content, context) =>
{
using (XmlWriter rWriter = PrepForXmlOutput(stream))
{
rpt.GenerateXmlReport(rWriter, reportParams, true);
}
}, "EventReport", extension);
}
catch (Exception e)
{
// The first step of GenerateXmlReport() is to run the sql;
// if the error happens there, this fires and will log the exception
// if the error happens later, during the result serialization, this does NOT fire
Log.Error(e);
}
return response;
Hate it when I see the answer just after I hit Post.
Try/catch around the outside only covers until I return the HttpResponseMessage. When/where I get the exception depends on how far the inner method gets before that return happens.
The try/catch needed to be on the inner call (the one where all the work happens) to cover the whole lifecycle.

Ms BotBuilder : firstRun dialog prevents triggering of other dialogs based on LUIS intents

I have a firstRun dialog defined in the bot like this :
// First run dialog
bot.dialog('firstRun', [
function (session, next) {
session.userData.token = _.get(session, 'message.user.token', null) || _.get(session, 'userData.token', null)
}
]).triggerAction({
onFindAction: function (context, callback) {
var score = 0;
if (session.userData.token doesn't exist or new token recieved in `session.user.message.token`){
score = 1.1;
}
callback(null, score);
}
});
And there's a LUIS model integrated with a dialog that triggers on an intent, let's say Help :
bot.dialog('help', [
(session, args) => {
let entities = _.get(args, 'intent.entities', null);
let topic = _.get(builder.EntityRecognizer.findEntity(entities, 'topic'), 'entity', null) || _.get(args, 'option', null);
session.replaceDialog(topic);
}
])
.triggerAction({
matches: 'Help'
});
The onFindAction triggers on every message. And it triggers firstRun only on the first message when session.userData.token is not set.
Problem is, if the first message is matched to Help intent, it does not get triggered. It works from the second time, when firstRun is not triggered.
How can I ensure any matching intent triggers the corresponding dialog, irrespective of firstRun?
If there's a different way possible to achieve the same thing, please suggest.
Addition
What I am trying to accomplish is this - I have a web service auth token that I want to keep in session.userData.token that refreshes every hour. So right now I trigger onFindAction on every utterance which checks if either session.userData.token doesn't exist (which means its the first utterance) OR a new token has been sent. In both cases I trigger firstRun to update session.userData.token and proceed to trigger any dialog that matched with the LUIS intent of the utterance. But whenever firstRun is triggered, none of the other dialogs are triggered. It would be ideal to have a simpler mechanism to do this i suppose.
Thanks
It sounds like you're trying to have a pass-through intent handler that would trigger before the message is routed to the actual handlers. Middleware would be the best place to handle your token refresh logic, but working with session in your middleware isn't easy. This blog post of mine explains why - http://www.pveller.com/smarter-conversations-part-4-transcript/.
Your best bet is the routing event, I believe. It's synchronous via events and you are given the session object. You should be able to validate and refresh your token as needed before the message reaches the proper intent handler destination.
bot.on('routing', function (session) {
if (!session.userData.token) {
// receive new token
}
});
Unlike middleware though, you are not given the next callback to continue the chain, so you will have to make sure you fetch the token synchronously. The blog post I mentioned previously explains this part as well.

How to safely ignore an error in a Dynamics CRM plugin?

I have a CRM plugin registered on Create (synchronous, post-operation) of a custom entity that performs some actions, and I want the Create operation to succeed in spite of errors in the plugin. For performance reasons, I also want the plugin to fire immediately when a record is created, so making the plugin asynchronous is undesirable. I've implemented this by doing something like the following:
public class FooPlugin : IPlugin
{
public FooPlugin(string unsecureInfo, string secureInfo) { }
public void Execute(IServiceProvider serviceProvider)
{
try
{
// Boilerplate
var context = (IPluginExecutionContext) serviceProvider.GetService(typeof (IPluginExecutionContext));
var serviceFactory = (IOrganizationServiceFactory) serviceProvider.GetService(typeof (IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
// Additional validation omitted
var targetEntity = (Entity) context.InputParameters["Target"];
UpdateFrobber(service, (EntityReference)targetEntity["new_frobberid"]);
CreateFollowUpFlibber(service, targetEntity);
CloseTheEntity(service, targetEntity);
}
catch (Exception ex)
{
// Send an email but do not re-throw the exception
// because we don't want a failure to roll-back the transaction.
try
{
SendEmailForException(ex, context);
}
catch { }
}
}
}
However, when an error occurs (e.g. in UpdateFrobber(...)), the service client receives this exception:
System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]:
There is no active transaction. This error is usually caused by custom plug-ins
that ignore errors from service calls and continue processing.
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ref ProxyRpc rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref MessageData msgData, Int32 type)
at Microsoft.Xrm.Sdk.IOrganizationService.Create(Entity entity)
at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.CreateCore(Entity entity)
at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.Create(Entity entity)
at Microsoft.Xrm.Client.Services.OrganizationService.<>c__DisplayClassd.<Create>b__c(IOrganizationService s)
at Microsoft.Xrm.Client.Services.OrganizationService.InnerOrganizationService.UsingService(Func`2 action)
at Microsoft.Xrm.Client.Services.OrganizationService.Create(Entity entity)
at MyClientCode() in MyClientCode.cs: line 100
My guess is that this happens because UpdateFrobber(...) uses the IOrganizationService instance derived from the plugin, so any CRM service calls that it makes participate in the same transaction as the plugin, and if those "child" operations fail, it causes the entire transaction to rollback. Is this correct? Is there a "safe" way to ignore an error from a "child" operation in a synchronous plugin? Perhaps a way of instantiating an IOrganizationService instance that doesn't re-use the plugin's context?
In case it's relevant, we're running CRM 2013, on-premises.
You cannot ignore unhandled exceptions from child plugins when your plugin is participating in a database transaction.
However, when your plugin is operating On Premise in partial trusted mode, you can actually create a OrganizationServiceProxy instance of your own and use that to access CRM. Be sure you reference the server your plugin is executing on to avoid "double hop" problems.
If really needed, I would create an ExecuteMultipleRequest with ContinueOnError = true, for your email you could just check the ExecuteMultipleResponse...
But it looks a bit overkill.
You can catch exceptions if running in async mode. Be sure to verify your mode when catching the exception.
Sample Code:
try
{
ExecuteTransactionResponse response =
(ExecuteTransactionResponse)service.Execute(exMultReq);
}
catch (Exception ex)
{
errored = true;
if (context.Mode == 0) //0 sync, 1 Async.
throw new InvalidPluginExecutionException(
$"Execute Multiple Transaction
Failed.\n{ex.Message}\n{innermessage}", ex);
}
if(errored == true)
{
//Do more stuff to handle it, such as Log the failure.
}
It is not possible to do so for a synchronous plugin.
A more detailed summary, explaining the execution mode and use case can be found on my blog: https://helpfulbit.com/handling-exceptions-in-plugins/
Cheers.

How can I tread OpenDolphin client send HttpHostConnectException?

Is there way to handle situation when message is not delivered to server? Dolphin log infors about situation clearly, but I'would like to catch it from code. I was looking for some method like: onError to override like onFinished:
clientDolphin.send(message, new OnFinishedHandlerAdapter() {
#Override
public void onFinished(List<ClientPresentationModel> presentationModels) {
// Do something useful
}
}
});
, but there is nothing like that. Also wrapping send call in try/catch does not work(not suprising since send is not blocking its caller code).
I thing there is definitely some easy way to get informed about undelivered message, but I cant see it.
Thaks, in advace, for answers!
You can assign an onException handler to the ClientConnector - and you are actually supposed to do so. The exception handler will get the exception object passed in that happened in the asynchronous send action.
Below is the default handler that even tells you, what you should do ;-)
Closure onException = { Throwable up ->
def out = new StringWriter()
up.printStackTrace(new PrintWriter(out))
log.severe("onException reached, rethrowing in UI Thread, consider setting ClientConnector.onException\n${out.buffer}")
uiThreadHandler.executeInsideUiThread { throw up } // not sure whether this is a good default
}

Spring Portal MVC Clear Action Exception going to Render Phase

I would like to know whether or not it is possible to clear an exception out of the request when trying to hit the Render Phase after the Action Phase has thrown the exception.
If you look at this code snippet from the doRenderService method of DispatchPortlet.class (a Spring provided class):
PortletSession session = request.getPortletSession(false);
if (session != null) {
if (request.getParameter(ACTION_EXCEPTION_RENDER_PARAMETER) != null) {
Exception ex = (Exception)
session.getAttribute(ACTION_EXCEPTION_SESSION_ATTRIBUTE);
if (ex != null) {
logger.debug("Render phase found exception caught during action phase - rethrowing it");
throw ex;
}
}
else {
session.removeAttribute(ACTION_EXCEPTION_SESSION_ATTRIBUTE);
}
}
You can see here that an exception gets put into the parameter map and there doesn't seem to be any way to clear it out.
What I would like to do is originally catch the Exception (what I am successfully doing), display an "Error Page" (what I am successfully doing), then display a button on that Error Page that allows the user to bring up the "Render Phase" page again so that he/she may be able to try their Action, again.
I've tried to create a filter, interceptor, new controller to clear the parameter, but it seems that the ParameterMap is an UnmodifiableCollection.
Any thoughts?
I actually was able to figure this out by doing the following in a render-phase filter:
session.setAttribute(ACTION_EXCEPTION_SESSION_ATTRIBUTE, null)
You can configure your org.springframework.web.portlet.DispatcherPortlet with setForwardActionException(false). This prevents spring from adding the Exception details in render parameters, or session.

Resources