[Cosmo-dev] Client Side Service Exceptions

Bobby Rullo br at osafoundation.org
Tue Feb 6 18:05:40 PST 2007


For bug 7572 - "handle CollectionLockedException in Cosmo UI" - I had  
to add some client side Exceptions. After grepping through all the  
code, it turns out we're not doing much with these exceptions (those  
that are mapped from Java ones) - which is largely a function of the  
mappings being wrong (they were still mapped from Scooby exceptions  
which obviously don't exist anymore.) Therefore I am taking this  
opportunity to talk about how to deal with service exceptions in the  
Cosmo UI.


1)  Exceptions that are thrown from RPC calls on the server can be  
mapped to JavaScript Exceptions on the client. Obviously not all  
possible Java exceptions are mapped to JavaScript exceptions - those  
just become generic JavaScript Errors. Right now the only two Java  
exceptions that are mapped are the ConcurrencyFailureException and  
CollectionLockedException. They are both mapped to  
"cosmo.service.exception.ConcurrencyException". All service code  
should be wrapped in a try catch block. To watch out for a specific  
exception you do something like the following:

Synchronous Example:
try {
     Cal.serv.saveEvent(cid, event);
}  catch (e if e instanceof  
cosmo.service.exception.ConcurrencyException) {
     showMessage("Someone else is modifying your event!");
}  catch (e) {
     //handle other errors that might happen on the server
     showMessage("Something bad happened.");
}

Asyncrhonous Example:

callback = function(returnObject, error){
     if (error){
         if (error instanceof  
cosmo.service.exception.ConcurrencyException){
            showMessage("Someone else is modifying your event!");
         } else {
             showMessage("Something bad happened");
         }
     }
}
Cal.serv.saveEvent(callback, cid, event);


Notice the use of  the "instanceof" operator to determine the  
exception type, and therefore how to handle the error. Also notice  
the conditional catch clause in the synchronous example - a neat JS  
feature I didn't know existed. If none of the conditional catches  
match the exception, the last "catch-all" catch will catch the  
exception.

2) For this specific bug (7572) I don't recommend the ui code merely  
re-trying to update the event. This would blow away any changes that  
we're just made by the other client. Not sure what a better solution  
is though short of a whole conflict resolution ui. Maybe a dialog box  
like  "Keep your changes, or get changes from the server?"

Also mde mentions the need of a "This item was deleted by someone  
else while you were trying to edit it, so it's gone now." sort of  
Exception. The problem is I don't think the server can tell whether  
an item is not around anymore because it was deleted, or because it  
never existed - it just knows that there is no such item with a UID  
of xxxxxxx. The proper thing to do would be to throw a  
"NoSuchResource" exception and catch that and have the client  
interpret it in the proper way ("The item in question no longer  
exists...Do you want to blah blah blah" or something). This is not  
implemented yet however, so you'll just get some weird error from the  
server.

3) Don't rely on the stuff inside error objects for anything. Sure, I  
didn't have to do all this wrapping - we could've just looked for  
"org.spring.dao.ConcurrencyException" whenever we called a service  
method, but then you'd have dependencies on Spring all over the place  
in your JavaScript code. And then you'd have to get rid of them all  
once we move to our GData solution.

Once we have the GData solution in place, we can still use these  
Exceptions - instead creating them by mapping Java Exceptions though  
we have our client side service layer map them to GData error codes,  
or Http error codes or however it will work. Yay.

4) Similarly, I think it's a bad idea to have the error dialog  
display error messages from the server or from the exception object  
itself in general. Better to figure out what the exception is, and  
dig up a user-friendly message from the i18n file. If it's not an  
exception that we have mapped, default to displaying a generic  
"There's been a problem with the server"

5) Let's create more exceptions! If there are others that need to be  
mapped that we need to handle specially let me know.

Right now this code is checked into my own branch (I got impatient.)  
I'll merge it tomorrow. For the moment you can look at commit r3607

Bobby





More information about the cosmo-dev mailing list