Reputation: 13833
I have an interface
public interface DataDAO {
public void doSomething() throws Exception;
}
Lets say that there are two implementations, one that uses Database to get the data and another one that uses a Webservice.
public class DataDAOJdbc implements DataDAO {
public void doSomething() throws Exception {
//Implement
}
}
public class DataDAOWebService implements DataDAO {
public void doSomething() throws Exception {
//Implement
}
}
As you can already see, the problem is the super generic exception launched. As both implementations need to raise the same kind of exception.
The Jdbc implementation really only raises lets say SQLException while the Webservice implementation only rises the IOException.
Question is, how can I make the interface more elegant, so I capture a proper exception?
The first thing that I though was creating my own exception, and declare it on the interface level
public interface DataDAO {
public void doSomething() throws MyCoolException;
}
And then, of course implement accordinly.
Question is, does this make sense? I have never created my own exceptions, so I am not really sure if this makes much sense or not. Also, what should I take into account when creating MyCoolException?
Upvotes: 6
Views: 196
Reputation: 55223
does this make sense?
Yes, it does. By declaring that doSomething
throws a specific checked exception, you're signaling to callers of the method that they only need to catch and deal with that specific exception. By declaring plain throws Exception
, callers would be encouraged to catch and deal with all Exception
s, which even include runtime exceptions like NullPointerException
.
what should I take into account when creating MyCoolException?
It could be as simple as the following:
public final class MyCoolException extends Exception {
public MyCoolException(Throwable cause) {
super(cause);
}
}
So your custom exception would simply act as a wrapper for the cause exception, whatever it may be. If possible you could add a message with additional information that might be helpful for debugging. When MyCoolException
is caught you can unwrap it by calling getCause()
, or else pass it into a call to a logging framework (its stacktrace will include the cause exception).
Upvotes: 1
Reputation: 85789
The first thing that I though was creating my own exception, and declare it on the interface level (...) does this make sense?
Yes, it does makes sense and I would think it is the best way to handle these situations.
I'll provide a kickoff example for this (based on your current code):
public class MyCoolException extends Exception {
public MyCoolException() {
}
public MyCoolException(String message) {
this.message = message;
}
}
public interface DataDAO {
public void doSomething() throws MyCoolException;
}
public class DataDAOJdbc implements DataDAO {
public void doSomething() throws MyCoolException {
//Implement
try {
} catch (SQLException e) {
//handle the exception
logger.error("Error!", e);
//throw your custom exception
throw new MyCoolException(e.getMessage());
}
}
}
public class DataDAOWebService implements DataDAO {
public void doSomething() throws MyCoolException {
//Implement
try {
} catch (IOException e) {
//handle the exception
logger.error("Error!", e);
//throw your custom exception
throw new MyCoolException(e.getMessage());
}
}
}
Upvotes: 4
Reputation: 308141
You can use a generic type to define the interface thrown:
public interface DataDAO<E extends Throwable> {
public void doSomething() throws E;
}
Then your Implementations would look like this:
public class DataDAOJdbc implements DataDAO<JDBCException> {
public void doSomething() throws JDBCException {
//Implement
}
}
public class DataDAOWebService implements DataDAO<WebServiceException> {
public void doSomething() throws WebServiceException {
//Implement
}
}
However, this has the drawback that you can no longer handle all the exceptions the same way, unless you just catch Exception
(which pretty much negates the entire point).
Upvotes: 2