Ok, I guess this thing really got to me... Couldn't stop thinking about the solution that would be more or less acceptable. Let me know what you think guys...
Service:
Code:
public class UserServiceImpl implements UserService {
private UserDao dao; // reference to the data access object used by the service
/**
* Sets the reference to the DAO implementation for this service.
* @param theDao dao instance
*/
@Required
public void setDao(UserDao theDao) {
dao = theDao;
}
/**
* Creates a new user from the given User object and returns the updated object for the new user.
* @param theDao dao instance
* @return updated user object (perhaps, with the new unique ID generated, or/and additional status info, etc.)
*/
@Transactional
public User createUser(User user) {
// any business logic (if needed)
try {
return dao.insertNewUser(user); // or, perform add'l logic and then return
} catch (Throwable t) {
String userEmailAddress = user.getEmailAddress();
if (dao.lookupExistingUser(userEmailAddress) != null) {
throw new DuplicateUserException("A user with email address " + userEmailAddress + " already exists");
} else {
// wrapping here is actually redundant; you may just re-throw the original since the svc specific exception only states the obvious.
throw new UserServiceException("Failed to create user for username/email address: " + userEmailAddress, t);
}
}
}
... other methods here
}
As you see, we are catching any exception in the createUser service method without the necessity to know anything about the data tier implementation. If something goes wrong, since we are required to inform the user of an existing duplicate, if exists, we check whether the error was caused by a duplicate indeed. If yes, throw a specific Duplicate exception. Otherwise, just re-throw the original (or wrap it inside the Service specific exception, which I think is actually redundant.) No exception handling at all on the DAO side! No exposing the data tier detail to the service. Seems simple and answers the use case. Wonder what you guys think?
Thanks,
Constantine