tags:

views:

141

answers:

3

I was having a discussion about this with a co-worker and we couldn't come to an agreement, so I wanted to get your thoughts. I have my own opinions on this, but I won't spoil it for you.

When should I be returning a SOAP fault and when should I be returning a result object that has error information? Assume this is for a generic web service that can be consumed by various systems (.NET, Java, whatever). The result object would have an isError flag, an errorType (similar to specific exception type), and a message.

Some points to consider:

  1. Is a data validation error a fault?
  2. Should there be a combination of faults (for very exceptional cases) and the results object (for "expected" errors)?
  3. How would you group SOAP faults (critical [null reference] vs validation [zip code incorrect])?
  4. Fail-fast vs having to remember to check for error
  5. Best practices, patterns, standards, etc.

Links to articles are valid. Even though it sounds like I want your opinion, please stick to facts (x is better because of y and z...)

+3  A: 

Most SOAP clients will convert faults into a runtime exception (if that is something the client language supports). With that in mind, I think you could rephrase the question as "When do I want to throw an exception instead of returning an error value"? I'm sure you can find lots of opinions about that API design in general and that topic in particular.

That said, returning an error is usually not helpful to the client:

  1. The client needs to manually enumerate and handle your error codes vs. allowing the stub code to generate and throw an exception of the appropriate type. Using error codes prevents the client from using object-oriented techniques like handling exceptions by superclass.

  2. If you don't make your error codes part of the WSDL; the client will have no documentation on what they are or when they occur. Typed faults are part of the WSDL and therefore (to some limited extent) self-documenting.

  3. Fault messages can contain fault-specific context that the client can make use of for error reporting and recovery. For example, throwing an input validation fault containing the actual invalid input element and a reason. If you return a result with an error code and an opaque string, the client has little choice but to pass your error message on to the user, which breaks internationalization, UI consistency, etc.

To answer your specific questions:

  1. A validation error is a fault. Imagine if you invoke the web service from an AJAX client with limited error handling ability; you want the service to return a 5xx HTTP code, not a 400 success code with some unexpected response.

  2. No. APIs should provide consistent error reporting interfaces. WSDL design is API design. Forcing the client to implement two distinct error handlers does not make the client's life easier.

  3. Fault design should mirror your request/response model and display information appropriate to the abstraction of the service. Don't design a NullReference fault; design a XYZServiceRuntimeFault. If clients frequently provide invalid requests, design a InvalidRequestFault, with appropriate subclasses so that clients can quickly figure out where the invalid data is.

gibbss
I'm having a hard time deciding who to give the answer to... @gibbss was first, the references by @Richard were good. I think you brought up a good point with "forcing the client to implement two distinct error handlers". Just because there is a results object that may have error information doesn't mean SOAP faults will never occur. I'll mull this over a bit more...
Nelson
+3  A: 

A results object should only contain results. If your result object is providing a list of errors that have occurred on another system then that is an example of when you can have and "isError" flag; otherwise you can't because a result is either valid or not.

You should always be using a SOAPFault when an error occurs. Validation is an error, and it's the devils own trap to think of validation as being less severe than an inability to open a database. Both cases have the same impact - the operation cannot be completed as requested.

So you should use result objects for results and SOAP Faults for anything that prevents a valid result object; including but not limited to errors, validation failures, warnings, bus faults, etc..

In the days before exceptions there was no choice and as a result many APIs became inconsistent and most APIs differed on how to return an error. It was (and still is) horrible, confusing and often slows down development because you have to lookup how each API entry returns an error, and often how to decode or find out more about the error.

  1. To handle validation with SOAPFaults / Exceptions is more logical when you think about it, and once you've thought about it is usually easier. You do need to design the validation fault class so that it contains sufficient information to identify the offending elements in a manner not necessarily requiring the original request. This way you can start to handle validation errors more generically.

  2. If the results object contains errors they can only within the domain of the results; for example "product out of stock" because someone in the wharehouse can't count.

  3. It is not wise to make the distinction between a critical error and a validation error, this to my mind isn't a valid comparison because any assignation of severity level is very subjective. For a system providing information about chemicals to a firefighter critical probably means that the truck on fire is carrying UN 1298 & UN 1436 and not a null reference when attempting to load the warning graphic.

    Design the faults in to allow them to be identified concisely and handled accordingly. Ensure that they convey sufficient information. Abritrary categorisation is something that is unncessary when you've got sufficient information because the Fault will allow itself to be indentified.

  4. SOAPFaults turned into Exceptions are the surest way of having fail-fast.

  5. Best practices, references etc.

Richard Harrison
On point #3, I may want to display validation errors (E-mail in invalid) and not any other types of exceptions. I don't agree completely about not grouping them. That is, after all, why we have so many Exception classes in .NET (IOException, ArgumentException, etc.). Of course they are still Exceptions and not handled in a custom way, but they are grouped.
Nelson
Exceptions may, and should be identified, by type or class, e.g. ValidationFailure, SecurityFailure,RelatedKeyFailure. However these identities should not be grouped (or placed into categories) as it is this that is implying meaning when the handlers should decide on a per-instance basis. Whilst you may want to display validation failure if you are handling all exceptions then it is upto the handlers to differentiate between the exceptions based on their type.
Richard Harrison
+1  A: 

I think the short answer is use a soap fault, unless you know the client will be equipped to handle an error returned as the result. I was also thinking the analogy between exceptions and error results, as mentioned in the other answers.

There are grey areas that could both be reasonably treated as exceptions and as result errors depending upon the needs of the client. You might then provide a parameter to the service that alters how these types of error is returned. The default is to use a SOAP fault, but if the client sets the parameter to get error results, then it is indicating that it is willing to handle this as part of the result. For me, validation errors are in this grey area. For most clients they should be considered faults, but if the client wants to use the data to markup the UI with validation errors, they returning the validation errors as part of the result may be more useful.

mdma