This is a discussion on Windows Communication Foundation within the Technology BUZZzzzzz forums, part of the Discussweb Technology Box category; Hi guys, I am writing WCF services which are utilizing COM+ application, now I am unable to decide on exception ...
| |||||||
| Register | FAQ | Members List | Calendar | Mark Forums Read |
| |||
| Hi guys, I am writing WCF services which are utilizing COM+ application, now I am unable to decide on exception management i.e. whether to use error codes or exception for business errors. Let me give you an example: public Document GetDocument(int docId) Now there can be following outputs when you call this method - throws exception if database is down Can be easily handled via exception management - Returns null if document not found - Returns null if document is not in active state (Business case) Now the above cases, they return the same output but the reasons are different and I want to show the reason to the client, what can be the best practice? One of the options I were thinking of public Document GetDocument(int docId, out enum returnErrorCode) so enum can have values DocumentNotFound, DocumentNotInActiveState etc First of all I don’t like this approach and secondly caller will have to do lot of if checks after the method call which is weird. The other option i am thinking to have two type of base exceptions derived from WCF FaultException, one to handle all unknown/technical exceptions and one to handle pure business errors with ErrorCode in it. The only benefit we'll be getting with this approach that WCF clients will be handling just these exceptions instead of writing various if checks. But still not sure it’s correct to handle business errors via exceptions. Please advice. Regards |
| Sponsored Links |
| |||
| First of all if you are developing using a service orientated paradigm why are you passing simple types to an end point surely you want to be submitting a 'request' message and receiving a 'response' message back, also naming a method 'GetXXX' seems like a bad idea to me. e.g. RetrieveDocumentResponse RetrieveDocument(RetrieveDocumentRequest) The advantage of this is that the response message 'RetrieveDocumentResponse' can contain a status field indicating success, the document and a error message field etc... Personally I prefer not to use exceptions to convey errors in business logic across a service boundary, I prefer the above approach. I only expect exceptions from infrastructure\message (versioning)\hosting problems, e.g. the end point of the web service is not available (404 error) etc Hope this helps ![]() |
| |||
| Well agree with you but based on circumstances you cannot follow the full practice some time, can you? So it's a kind of SOA but not 100% of course, but anyway the question remains same Error Code or Exception? Regards |
| |||
| You raise the more generic question of how to handle multiple (and multiple kinds of) responses - one of WSDL's shortcomings. Consider moving to a generic signature like: IMessage[ ] Execute(IMessage[ ] input); Then consider moving to a publish/subscribe model. Finally, you'll find that (as this post shows) you don't need any request/response semantics for getting information . Give it a try. It's more scalable than the synchronous request/response the tools auto-magically spit out. |
| |||
| You could try a more simplistic approach: GetDocumentResponse GetDocument(GetDocumentRequest request) GetDocumentRequest would have everything you need to call the service (input parameters, service/application parameters, etc.) GetDocumentResponse would have the data you want to retrieve and the execution status. You should leave SOAP as transport only. That way you can easily consume/expose services using other "protocols" (like REST, RSS, etc.). This suggestion doesn't invalidate anything Udi said about the publisher/subscribe model. It's just a simplier and not so generic service contract. |
| |||
| My point is that SOAP is transport and SOAP faults should be only for transport errors. Some error might not be a business error from the producer's standpoint, it certainly is one form the consumer's standpoint. You don't expect to receive a FileNotFoundException because the products file is missing when you call GetProducts. Instead you should get some sort of internal error. |
| |||
| I'd have to agree with that, you wouldn't expect an infrastructure file to be missing that would be ideal for an exception. However I'm still unclear as to what this thread is suggesting as the answer. The quote from Ron Jacobs is interesting... According to the .NET FrameworkClass Library Design Guidelines “Exceptions are the standardmechanism for reporting errors. Applications and libraries should not use return codes to communicate errors. The use of exceptions adds to a consistentframework design and allows error reporting from members, such as constructors,that cannot have a return type. Exceptions also allow programs to handle theerror or terminate as appropriate. The default behavior is to terminate anapplication if it does not handle a thrown exception.” Or have I missed something?
__________________ H2O Without us, no one can survive.. |
| |||
| I think service invocations should be treated as low level invocations and exceptions should be a high level mechanism. A SOAP fault should be a transport error when using SOAP. When using REST, HTTP status codes and messages should be used. When using SOAP faults you can get a FaultException or a SoapException depending whether you are using WCF or ASMX. Should you build your service consumers be aware of the API over the transport either? And you can also be accessing a database or a file (on a local drive or via FTP). You should shield all this from the business invocation code and throw transport or communication exceptions. As for business rules, a business exception should be thrown. With this pattern, everyone will be happy: 1. No FaultExceptions or SoapException 2. Exceptions thrown when an error occurs. |
| |||
| IMO fault\error\exception (which ever you like to call it) is never nice to look at in the 'real' world of application development, whether it be a exception handling strategy like the enterprise library exception handling block, detailed error messages\codes or multiple 'catch' statements. Just as long as you decide on a strategy you can justify and use it every where then it should be ok. As I & others have stated above I believe you shouldn't throw exceptions from a service - detailed error codes\messages should be returned in the response message, only the communication infrastructure (e.g. SOAP via HTTP) should throw exceptions. |
| |||
| Sorry guys for coming so late on it, anyway i think you guys are thinking totally from WCF perspective and whatever comments you all have given are totally correct in WCF world. Ok lets say if i remove SOA all together and you have COM+ services in place of it, what you will do than? or if i keep service layer either as WCF or COM+ or webservices but there's a business layer written in custom .net classes what they'll return then? like lets say WCF ProductManagerService calls CreateProduct and internally it calls Create of Product BLL class then how this BLL would handle the errors? via exception or error codes? Regards |
| |||
| Visit the following link. Ron Jacobs : Exceptions vs. Error codes with Services Keep in mind that the goals are still the same whether or not you are involving services The goals are: 1. Easy to understand, code and use 2. Consistent with the intent of the language/technology designers and common practice With that said, I believe that exceptions are still the best way to go in either case. Some people have noted that exceptions may introduce a performance problem, however this is only in rare cases where the number of exceptions thrown are really excessive (like hundreds of thousands). If that is your concern, I would test the performance to know for sure. |
| |||
| I have never done any real work with COM+ but I've done some mixed REST/ASMX/WCF clients and I think I would do the same for COM+ an abstraction layer for comunication and business errors would be on the message (or data transfer object). As I said before, that doesn't prevent you from throwing a business exception from the client service calling code to the code calling the code that calls the service.
__________________ H2O Without us, no one can survive.. |
| |||
| Let me just code what I mean. This would be the service consuming code: Code: // ...
IProductsService productsService = ServiceContainer.GetService();
try
{
Product[] productsService.GetProducts(category);
}
catch (InvalidProductCategoryException bex)
{
// ...
}
catch (ProductSystemException exe)
{
// ...
}
// ... Code: public class WcfProductsServiceAdapter : IProductsService
{
public Product[] GetProducts(string category)
{
GetProductsRequestMessage request Translators.Get(category);
Adapters.BeforeSendMessage(request);
GetProductsResponseMessage response;
using (ProductsServiceClient client new ProductsServiceClient())
{
try
{
response = client.GetProducts(request);
}
catch(Exception ex)
{
throw new ProductSystemException(ex.Message, ex);
}
}
Adapters.AfterReceiveMessage(response); // throws business exceptions
// based on error information
// on the respone message.
return Translators.GetList<Product>(response);
}
} Using this pattern, you can implement your service adapter using WCF with MessageVersion.None, ASMX, COM+, database, XML file, etc. I hope I understood correctly the question: WCF, FaultException and business errors, right?
__________________ H2O Without us, no one can survive.. |
| |||
| re: the performance argument. I concede that normally you'd put maintenance ahead of squeezing out performance but I'm not so sure it's as small as you suggest, especially in a distributed world. If that exception has to be serialized back a few hops then it is going to start looking slow. Given that we should ideally be designing code that works on a PDA and a 1000 unit farm it is difficult to implement an exception to the exception rule! But how many people really design like that I wonder? On this note I'm sure I read that Microsoft were looking to change how exception handling worked and it promised to alleviate some of the stack walking, did I dream this or does anyone else know about it? |
| |||
| re: H2O But why spit the two out? Obviously the general catch (Exception) is for the example but why wouldn't you catch transport exceptions along with business exceptions. I don't really understand what you're gaining from the approach . If you wanted to be clear couldn't you nest it like try Call Biz Component try Make WCF call catch(transportException1) catch(transportExeption2) catch (BizException1) ... where the nested try would be another function? |
| |||
| My example wasn't that simple. The code using a particular IProductsService isn't aware of any particular implementation nor transport. So, it would be very wrong to catch a FaultException if you are retrieving products from an XML file. Maybe I've been CABing too much latelly. ![]()
__________________ H2O Without us, no one can survive.. |
| |||
| One major problem with writing RPC style methods like this is that you have no way of returning out-of-band information. In this particular example, you are asking about how to propogate error codes and other information from the service to the consumer. Using a design like this, you must use transport-level mechanisms (soap faults, etc) to propagate out-of-band information. What several people are trying to point out is that by bringing your abstraction up a level, you gain the ability to convey the out-of-band data without using some behind-the-scenes magic (ie..soap faults). Generally, this is done by moving away from RPC methods (as seen above) into a more messaging friendly api, such as this one: public GetDocumentResponse GetDocument(GetDocumentRequest request); Now you can encapsulate the details of the request into a single "object". Code: public class GetDocumentRequest
{
private string _docId;
public string DocId
{
get { return _docId; }
set { _docId = value; }
}
} Code: public class GetDocumentResponse
{
private Document _document;
public Document Document
{
get { return _document; }
set { _document = value; }
}
} Code: public abstract class Request
{
private string _requestId;
public string RequestId
{
get { return _requestId; }
set { _requestId = value; }
}
} Code: public abstract class Response<T>
{
private string _correlationId;
private T _request;
private bool _success;
private string[] _errors;
public string CorrelationId
{
get { return _correlationId; }
set { _correlationId = value; }
}
public T Request
{
get { return _request; }
set { _request = value; }
}
public bool Success
{
get { return _success; }
set { _success = value; }
}
public string[] Errors
{
get { return _errors; }
set { _errors = value; }
}
} After defining our base types, we can simply use them with our messages: public class GetDocumentRequest : Request public class GetDocumentResponse : Response<GetDocumentRequest> By using the RPC style method and returning the entity directly, you back yourself into a corner. You will need the flexibility down the road (if not now). I would also recommend not using a string[] for the errors, introduce another object just to convey error information (ie.. something that has an Id and Message property). If you ever have to support multilingual exception handling across a service boundary, you will understand why (trust me, I'm there now). And if you are looking for some sample code, you can check out my blog: A Unit of Work Implementation for Webservices Refactoring the Design If you can follow me this far, I show you in my blog how to bundle multiple "Requests", send them across the wire, unbundle them, process them, bundlle the "responses", and then send them back to the consumer. All while using only a single network traversal. You could never do that with an RPC style interface. Also, take a look at the Notification Pattern. It makes the exception handling (at least for checking preconditions) much simpler to write. You place it into some goo between the metal (WCF/ASMX/etc) and your application logic. Hope Helpful.
__________________ Raja. Myblog |
| |||
| Re-reading your example I think we're almost saying the same thing, except I'm talking about something like... You have... Code: Adapters.AfterReceiveMessage(response); Code: Adapters.AfterReceiveMessage(exception); |
| |||
| re: Raja... What concerns me with that approach is it seems that you're changing your implementation to fit the technology rather than representing the actual problem. In the example the client wants a Document from a service not a DocumentResponse. Perhaps you've just skipped over something and I've missed the point? |
![]() |
| Thread Tools | |
| Display Modes | |
| |
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| How u do Bluetooth Communication between PC and mobile in J2ME | itbarota | J2ME | 9 | 09-11-2008 02:08 AM |
| Can any one explain about the features of window workflow foundation ? | oxygen | C# Programming | 1 | 07-30-2007 04:51 AM |
| Difference betw | ||||