This project is read-only.

Exceptions

May 5, 2009 at 7:30 AM
Hi,

How are exceptions handled? For example I'd like to throw back an exception in my "service" to the client. I understand everything is asynchronous, but is there a way to send an exception instead of a response object?

Thanks,
/Hakan
May 7, 2009 at 1:24 AM
I think I've realized there's nothing built-in in SSB that wraps exceptions and pass them up to the calling application. What I've started to do is create a new base exception class that can be XMLSerialized and that's what I will send back, wrapping the message handlers in this code:
try
{
}
catch (Exception ex)
{
       context.Endpoint.MessageBus.Reply(new SharedMessage.ExceptionMessage(ex));
}

My question is, is there a clever way to wrap all message handlers in this wrapper so I don't have to copy/paste this to every handler? I'm looking for something similar to the IErrorHandler that we have in WCF.

Thanks!
/Hakan

May 7, 2009 at 2:01 AM
There is a way to do this now, but I like the IErrorHandler idea and will add that as an extensibility point very shortly. If you don't want to wait, you can subscribe to the IMessageBus MessageProcessingError event, and send your reply inside that message handler. 

Also keep in mind that every exception is being sent to the endpoint health monitor, if you have it configured, where they are being logged and are accesible via the website, if you end up deploying it.
May 7, 2009 at 2:06 AM
Ah, that's excellent! Yea, I was using the IErrorHandler filter in WCF and it was extremely convenient. Can you post a follow-up in here when you've implemented the IErrorHandler extension?

Yep, that's a side benefit that the monitor would get it.

May 7, 2009 at 7:51 AM
This is implemented, in the form of  IMessageProcessingErrorHandler. You can supply your own implementation by either registering an implementation of this inerface with your IoC prior to bulding you Endpoint (provided you re using an IoC to build your endpoint) or you can register an implementation using the service locator, i.e. Endpoint.LocalServices.RegisterService<IMessageProcessingErrorHandler>(new AutoReplyErrorHandler()); 

The defaut implementation, which replaces the hard-coded logic previously bult into MessageBus, is MessageRetryErrorHandler, which will make a few attempt to process a message before sending it to the poison queue You may want to extend this class when buildng your custom error handler, i.e.

 public class AutoReplyErrorHandler : MessageRetryErrorHandler
    {
        public override bool HandleMessageProcessingError(ref MessageProcessingException exception, MessageEnvelope message, IMessageBus messageBus)
        {
            messageBus.Reply(new SharedMessage.ExceptionMessage(exception));
            return base.HandleMessageProcessingError(ref exception, message, messageBus);
        }
    }

Returning true from HandleMessageProcessingError will propogate the error as usual, including sending the error to the endpoint monitor. REturning false indicates you have completely handled the message and do not want any further processing to take place.

Let me know how this works for you.