I am developing a very small test to simulate a 3 layered system so I can understand how Exceptions work. At the same time I would like to come up with a reasonable approach so I can use this design as further reference for similar operations in other applications.
I have been reading through different articles on the topic and it seems that there is a huge controversy over using checked or unchecked exceptions which is making me doubt about my final design.
I won’t go through the arguments used to criticize or support checked/unchecked exceptions because probably they are all well known but rather I will present my design looking for some advices in how to improve it and make it (as long as possible) similar to a real application.
The system is in charge to perform basic CRUD operations in a relational DB (lets say MySQL) using JDBC. I have the following: a presentation layer, a service layer and a persistence layer.
Based on this answer Handling Dao exceptions in service layer it makes sense for me not to expose specific layer implemantation and decouple the layers. So I decided to create my custom exceptions and wrap them into a Base Exception per layer so I can translate specific layer exceptions (i.e SQLException) into general layer exceptions (i.e PersistentException, BusinessException). And if later on the implementation changes I can simply wrap the new one into the base exception expected by the higher layer. So I have the following exceptions:
com.user.persistent.exceptions
    |_ PersistentException
    |_ ExistingUserException
    |_ Some more..
com.user.business.exceptions
    |_ BusinessException
    |_ somemore....
From Josh Bloch’s book Effective Java: “Use checked exceptions for conditions from which the caller can reasonably be expected to recover.” I am also not that sure but I believe a user can recover from a SQLExeption (i.e A user by mistake provides an existing ID, he can re-type the right one ) so I decided to make the previous exceptions checked exceptions. Here is an overview of how the classes look like:
Persistence Layer.
public interface UserDAO 
{
    public void create(User team) throws PersistentException;
}
//Implementation in DefaultUserDAO.java
@Override
    public void create(User team) throws PersistentException 
    {       
        try
        {
            System.out.println("Attempting to create an user - yikes the user already exists!");
            throw new SQLIntegrityConstraintViolationException();           
        }
        catch(SQLIntegrityConstraintViolationException e)
        {
            throw new ExistingUserException(e);
        }
        catch (SQLException e) 
        {
            throw new PersistentException(e);
        } 
        finally 
        {
            //close connection
        }
    }
Service Layer:
public interface UserService 
{
    void create(User user) throws BusinessException;
}
//Implementation of UserService
@Override
public void create(User user) throws BusinessException 
{
    System.out.println("Doing some business logic before persisting the user..");
    try 
    {
        userDao.create(user);
    } 
    catch (PersistentException e) 
    {
        throw new BusinessException(e);
    }
}
Presentation
    try 
    {
        userService.create(user);
    } catch (BusinessException e) 
    {   
        e.printStackTrace();
    }
Now the following points make me feel unsure about this design.
- I like the idea of having the compiler verifying if clients of the method catch/throw the declared exceptions when using checked exceptions. However, at the same time I think this approach leads to clutter code to handle all the exceptions. Not sure if it is because I am not making proper usage of exceptions or because checked exceptions really lead to clutter code.
 - I also like the idea of decoupling layers by wrapping specific layer exceptions into General ones. But, I can see a lot of new classes being created for every possible exception instead of just throwing an existing java exception.
 - I can also see that a lot the existing code on this application is devoted to handle exceptions and a small portion of it is devoted to the actual objective of the system.
 
These are actually my main concerns and make me wonder if this is really a good design. I would like to hear your opinions about it (and perhaps some small snippets of sample code). Can you guys give me some hints on how can I possibly improve it? In a way I can achieve decoupling between layers and avoid leaking layer specific concerns..