views:

58

answers:

4

Imagine I have a service that looks like this:

public interface MyAccountService
{
    boolean create( String user );
}

The method create performs several changes, namely (for discussion sake):

  1. adds a message into a Queue
  2. adds a row into several tables
  3. creates a LDAP account etc...

Currently I collapse all the error messages into a single boolean return value. Now internally if there is an error, I will log these for the support team.

e.g. a typical log of a failed user creation

creation of "alistair" account in the following (strict) order:

  • add to table Foo: success
  • add to table Bar: success
  • add to LDAP: failed
  • add to queue: success

This way, the tech support folks can decide how to repair the account.

What is the best practice for designing systems such that we can easily trace the success/failure of a transaction (and repair it manually) ? Is returning boolean & swallowing all exceptions a good design ? Thanks

EDIT By swallowing exceptions, I meant not throwing them up the the caller. However I do log the exceptions, and translate them to a false/true return value.

A: 

It depends on the need.

If the exception is because of the wrong information sent by the client and you want them to know so that they correct it, then you should throw the exception.

If the exception is because of internal issue but still you want the client to know then throw the exception.

Bhushan
A: 

No it is not. All available information about the exception should be logged. (including but not limited to: Exception Type, Message, Stack Trace, ...)

M. Jahedbozorgan
I clarified my question above. I do log the exceptions.
Jacques René Mesrine
+1  A: 

You have 2 options on this one in my opinion: 1. Throw a custom exception with the list of the successes, thus the client of the API can catch the exception and see what failed and then decide which action to perform. 2. Return an ENUM in which you reflect all the possible results of the outcome, thus again
the client of the API can decide which action he will perform.

Any way you must log all the problems your method encounters so it can be traced... Exception and problem swallowing is a very bad practice.

I like more the custom Exception method, for the ENUM is more C like API..

Alon
Option #1 is a reasonable option. Should I attempt to execute all the 4 operations non transactionally ? Meaning: if I encounter a problem inserting to table Foo, I remember the error and continue on to all the other tasks. Or should I short circuit and abort ? Note that except for the queue operation, all tasks are idempotent because the DB tables and LDAP server will not accept duplicate entries.
Jacques René Mesrine
This depends on your application. If you need all the task to be done under one transaction then you need to rollback all changed to subsystems if any error occurs. In this scenario just make to rollback and throw Exception with the problem. On the other hand, if it's OK just to update the DB and LDAP and indicate the client that the JMS call failed then do not run transactions just remember each error and notify the user via Exception.
Alon
+1  A: 

I like the approach described in the article presented here, there is a discussion about it here...

The idea is to consider to kind of exceptions, and to handle them differently:

One type of exception is a contingency, which means that a process was executed that cannot succeed because of a known problem (the example he uses is that of a checking account, where the account has insufficient funds, or a check has a stop payment issued.) These problems should be handled by way of a distinct mechanism, and the code should expect to manage them.

The other type of exception is a fault, such as the IOException. A fault is typically not something that is or should be expected, and therefore handling faults should probably not be part of a normal process.

pgras