quantumbyte
quantumbyte

Reputation: 553

Java - Avoid passing up checked exceptions

My application architecture can roughly be represented like this:

UI --> Domain Model --> PersistenceService (Caching etc.) --> Mapping Layer

The Mapping Layer consists of interfaces that are like DAOs (just get, insert, update and delete), The Persistence Layer uses these interfaces and adds caches and checks to avoid unneccessary updates.

In theory, there are various implementations for the Mapping Layer, for example, one could map to xml files or to an SQL database; but because the mappers interact with the "outside world", they usually throw checked exceptions (IOException, SomeSQLException ...).

First problem is, how can I unify my Mapper interfaces, if the Exceptions are different for each implementation? I could create a new exception (MapperException) that can be thrown, and then I would "bubble up" the exception, through my persistence layer, through the domain layer, until the UI catches it and displays a (generic) error message.

And here is the thing I don't like; the exceptions are checked exceptions, however there is no class or layer that can actually handle them, they are just passed up until they are displayed and thats it. It seems weird to have a throws-clause on nearly every method, just because some of the low level classes throw checked exceptions that should be handled.

Can I just convert the checked exceptions to unchecked exceptions? How would I make sure that they are still catched in the UI?

Or can I somehow inject an exception handler into the lower layers that is provided by the UI layer?

Is there some kind of best practice to this? So far I have rarely dealt with exceptions because the usually do not occur and I didn't care about proper exception handling in my earlier private projects.

Upvotes: 0

Views: 351

Answers (2)

Dave Newton
Dave Newton

Reputation: 160181

IMO Lower-layer exceptions should generally be caught and wrapped in application-specific exceptions; exception chaining ensures the root cause is captured.

This protects the upper layers from changes in underlying functionality, e.g., if you have a general DataLayerException, the underlying persistence mechanism(s) can be swapped at will, and the upper layers don't need to change how they deal with persistence-related exceptions. This also allows multiple persistence mechanisms at once, like both relational and NoSQL datastores to report exceptions in a unified way to the upper layers.

Note that some frameworks already handle some of this exception aggregation already.

Converting to runtime exceptions may or may not make sense, but runtime exceptions can be caught as long as you know they're being thrown (or may be). It really depends on your specific needs.

Upvotes: 1

Jens Schauder
Jens Schauder

Reputation: 81882

Can I just convert the checked exceptions to unchecked exceptions?

Yes of course, just wrap it in a RuntimeException of your choice:

try{
    // something unsafe happens here
} catch ( SomeUglyCheckedException suce){
   throw new UncheckedExceptionOfChoice("Something went wrong", suce);
}

How would I make sure that they are still catched in the UI?

Probably yes, but it depends on the technology you use. You might register an ExceptionHandler on threads involved: http://www.javapractices.com/topic/TopicAction.do?Id=229 or the framework you use might provide a special mechanism for that.

Upvotes: 1

Related Questions