views:

353

answers:

12

I found questions here http://stackoverflow.com/questions/175532/return-null-or-throw-exception and http://stackoverflow.com/questions/1626597/should-functions-return-null-or-an-empty-object, but I think my case is quite different.

I'm writing an application that consists of a webservice and a client. The webservice is responsible to access data, and return data to the client. I design my app like this:

//webservice

try
{
   DataTable data = GetSomeData(parameter);
   return data
}
catch (OopsException ex)
{
   //write some log here
   return null; 
}

//client:

   DataTable data = CallGetSomeData(parameter);
   if(data == null) 
   {
      MessageBox.Show("Oops Exception!");
      return;
   }

Well, there is a rule of not returning null. I don't think that I should just rethrow an exception and let the client catch SoapException. What's your comment? Is there better approach to solve this problem?

Thank you.

+4  A: 

In your case, an exception has already been thrown and handled in some manner in your web service.

Returning null there is a good idea because the client code can know that something errored out in your web service.

In the case of the client, I think the way you have it is good. I don't think there is a reason to throw another exception (even though you aren't in the web service anymore).

I say this, because, technically, nothing has caused an error in your client code. You are just getting bad data from the web service. This is just a matter of handling potentially bad input from an outside source.

Personally, as a rule of thumb, I shy away from throwing exceptions when I get bad data since the client code can't control that.

Just make sure you handle the data == null condition in such a way that it doesn't crash your client code.

Robert Greiner
+2  A: 

All the WebServices that I've used return objects, not simple data types. These objects usually contain a bool value named Success that lets you test very quickly whether or not to trust the data returned. In either event, I think any errors thrown should be untrappable (i.e. unintentional) and therefore signify a problem with the service itself.

Brad
A: 

The general practice in handling exception is, when the sequence of flow is expected in the normal circumstance where as the sequence could not be completed due to non-availability of resources or expected input.

In your case, you still need to decide how do you want your client side code to react for null or exception.

Gopalakrishnan Subramani
A: 

How about passing in a delegate to be invoked when anything bad happens? The delegate could throw an exception if that's what the outside could would like, or let the function return null (if the outside code will check for that), or possibly take some other action. Depending upon the information passed to the delegate, it may be able to deal with problem conditions in such a way as to allow processing to continue (e.g. the delegate might set a 'retry' flag the first few times it's called, in case flaky network connections are expected). It may also be possible for a delegate to log information that wouldn't exist by the time an exception could get caught.

PS--It's probably best to pass a custom class to the problem-detected delegate. Doing that will allow for future versions of the method to provide additional information to the delegate, without breaking any implementations that expect the simpler information.

supercat
+1  A: 

I think it all boils down to the question whether or not your client can use any info as to why no data was returned.
For example - if no data was returned because the (say sql) server that is called in GetSomeData was down, and the client can actually do something with that information (e.g. display an appropriate message) - you don't want to hide that information - throwing an error is more informative.
Another example - if parameter is null, and that causes an exception.. (although you probably should have taken care of that earlier in the code.. But you get the idea) - should have throw an appropriate (informative) exception.

If the client doesn't care at all why he didn't get any data back, you may return null, he'll ignore the error text anyhow and he's code will look the same..

Oren A
+1  A: 

If your client and service are running on different machines or different processes, it will be impossible to throw an error from the service and catch it on the client. If you insist on using exceptions, the best you can hope for is some proxy on the client to detect the error condition (either null or some other convention) and re-throw a new exception.

Mark Ransom
A: 

Exceptions are recommended in the same process space. Across processes, it is only through information that a success/failure is evaluated.

deepsat
+1  A: 

I think there may be a few factors to consider when making a decision:

  • what is the idiomatic way to do this in the language your using (if it wasn't a webservice)
  • how good your soap/webservice library is (does it propogate exceptions or no)
  • what's the easiest thing for the client to do

I tend to make the client do the easiest, idiomatic thing, within the limitations of the library. If the client lib doesn't take care of auto restoring serialized exceptions I would probably wrap it with a lib that did so I could do the following.

Client:

try:
  # Restore Serialized object, rethrow if exception
  return CallGetSomeData(parameter);
except Timeout, e:
  MessageBox.Show("timed out")
except Exception, e:
  MessageBox.Show("Unknown error")
exit(1)

WebService:

try:
  return GetSomeData(parameter) # Serialized
except Exception, e:
  return e # Serialized
dietbuddha
+3  A: 

In general i try to design my webservices in such way that they return a flag of some sort that indicates whether there was a technical/functional error or not. additionally i try to return a complex object for result not just a string, so that i can return things like:

result->Code = "MAINTENANCE" result->MaintenanceTill = "2010-10-29 14:00:00"

so for a webservice that should get me a list of dataEntities i will return something like:

<result>
    <result>
        <Code>OK</Code>
    </result>
    <functionalResult>
        <dataList>
            <dataEntity>A</dataEntity>
        </dataList>
    </functionalResult>
</result>

so every failure that can occur behind my webservice is hidden in a error result. the only exceptions that developers must care about while calling my webservice are the exceptions or errors that can occur before the webservice.

hacktick
A: 

I think returning null in this case is not bad, you can log exception in server side (async) to know what happened and return null, because you using web service throwing an exception has a lot of cost, may be its very big exception. Also if you want throw your own exception with little cost, its possible but i prefer to use as smaller as possible of my bandwidth.

SaeedAlg
+2  A: 

Your first problem is "a rule of not returning null". I would strongly suggest reconsidering that.

Returning a SoapException is a possibility, but like hacktick already mentioned, it would be better to return a complex object with a status flag {Success,Fail} with every response from the web service.

Matt H.
A: 
  • Since you are the client to your webservice, you can log the exception at the service layer and return null to the client, yet the client should still know if the CallGetSomeData returned null because a) data is not available, or b) there is a database exception as the table is locked. Hence its always good to know what has caused the error for easier reporting at client side. You should have a error code and description as part of your message.
  • If you are not consuming your webservice then you should definetly throw exception for the same reasons mentioned above, client should know what has happened and its upto them to decide to what to do with that.
anivas
How would you define "consuming your webservice"? TIA.
Hippo
"not consuming your webservice" - "not a client of your service". This is when you write a publicly used service like credid card authentication.
anivas