Compare these two methods:
void foo() throws SomeSuperException {
try {
//...
} catch (SomeSuperException e) {
if (e instanceof SomeSubException) {
throw e;
}
}
}
void bar() throws SomeSubException {
try {
//...
} catch (SomeSuperException e) {
if (e instanceof SomeSubException) {
throw (SomeSubException) e;
}
}
}
Aside from the method signatures (bar can declare throws SomeSubException instead of throws SomeSuperException), is there any practical difference between the two methods?
To be clear: I'm aware that this is a horrible approach to exception handling, and should not be done!
The difference is that in the first case, externally the caller doesn't know about your specific SomeSubException, so some detail is lost in translation.
No there's no (big) difference.
From the ordinary it's the best choice to throw the most specific exception,
no the super or broader one. This allows you to handle more cases in the overlaying catchBlock.
Related
I have two APIs (say create and update) that calls the same serviceA. serviceA has a conditional block that will only be called in case of update. serviceA throws a number of different exceptions but some of them will only be thrown within the conditional block called by update I am looking for suggestions for exception handling in my APIs (create and update). What is a recommended practice here? I don't want to have duplicate exception handling logic but if I extract the error handling logic, I might have to catch exceptions that are only applicable to update for create as well.
public class ServiceA {
void upsert(Request request) {
//some common operations for create and update
if (request.action == "UPDATE") {
//update
if (someUpdateErrorCondition) {
throw new ExceptionA();
} elseif (someOtherUpdateErrorCondition) {
throw new ExceptionB();
}
...
}
if (someErrorCondition) {
throw new ExceptionC();
} elseif (someOtherErrorCondition) {
throw new ExceptionD();
}
...
}
Appreciate your help!
Not sure if I correctly understood the problem, but if you have common exceptions to handle as well as specific exceptions then you could use a lambda for common error handling.
There's various flavors of the same approach which is to control the execution with a shared component, whether you use function composition, the decorator pattern, etc.
E.g. (non-java pseudo-code)
function process1() {
withCommonErrorHandling(() => {
try {
//could throw CommonError or Process1Error
} catch (Process1Error e) {
//handle
}
});
}
function process2() {
withCommonErrorHandling(() => {
try {
//could throw CommonError or Process2Error
} catch (Process2Error e) {
//handle
}
});
}
function withCommonErrorHandling(fn) {
try { fn() }
catch (CommonError e) {
//handle
}
}
Given a function that might throw:
public static int f() throws Exception {
// do something
}
Is there any way this code:
public static int catchF() throws Exception {
try {
return f();
} catch (Exception ex) {
throw ex;
}
}
is any different to calling f directly? I.e. could the caller detect the difference by inspecting the exception? Is there any discernible overhead in using catchF instead of f?
If there is no difference, can compilers, or the JVM, optimise a call to catchF into a direct call to f?
While this might seem like a strange thing to do, the use case would be to re-introduce an exception at the type level after earlier hiding it:
class Test {
// Hide the exception.
public static <X extends Exception, T> T throwUnchecked(Exception ex) throws X {
throw (X) ex;
}
// Interface for functions which throw.
interface Throws<T, R, X extends Exception> {
R apply(T t) throws X;
}
// Convert a function which throws a visible exception into one that throws a hidden exception.
public static <T, R, X extends Exception> Function<T, R> wrap(Throws<T, R, X> thrower) {
return t -> {
try {
return thrower.apply(t);
} catch(Exception ex) {
return throwUnchecked(ex);
}
};
}
// Unhide an exception.
public static <R, X extends Exception> R unwrap(Supplier<R> supp) throws X {
try {
return supp.get();
} catch (Exception ex) {
throw (X)ex;
}
}
public static Stream<Integer> test(Stream<String> ss) throws NumberFormatException {
return Test.<Stream<Integer>, NumberFormatException>unwrap(
() -> ss.map(wrap(Integer::parseInt))
);
}
public static void main(String[] args) throws NumberFormatException {
final List<Integer> li = test(Arrays.stream(new String[]{"1", "2", "3"})).collect(toList());
System.out.println(li);
}
}
The intent is to wrap functions that throw exception into ones where the exception is hidden at the type level. This makes the exceptions usable for example with streams.
is any different to calling f directly?
No.
I.e. could the caller detect the difference by inspecting the exception?
No, because you're not constructing a new exception at this point. The stack trace was constructed at the point where the new WhateverException(...) was invoked (not where the throw was, although they are often in the same place).
Typically, you rethrow a caught exception if you need to do some cleanup as a result of the exception:
try {
// ...
} catch (SomeException e) {
// Clean up resources.
throw e;
}
The fact that something happened as the call stack was unwound is neither visible nor relevant to the caller.
A quick demo can show that the stack traces are identical whether the exception is caught and rethrown or simply allowed to propagate.
Is there any discernible overhead in using catchF instead of f?
The overhead of constructing the exception will far outweight any overhead of this redundant construct.
An exception handler that simply rethrows and does not affect the known types of the exceptions has absolutely no semantic effect.
In theory, then, compilers or the JVM could optimize the try-catch out. In practice, I doubt that they do, because such code should be rare and not on hot paths (exceptions should never be); it's probably not worth the effort to implement such an optimization.
I tend to throw as many checked Exceptions up as possible: it declutters the code (and I regard checked Exceptions as a dubious aspect of Java). I tend to use them when "refining" code.. i.e. when it makes sense for the particular context.
This approach gets slightly complicated when overriding superclass/interface methods which don't throw the requisite Exception, and therefore I tend to do this:
#Override
public void close() {
try {
_close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
where _close is a private method which does all the business.
The problem when it comes to JUnit, if you actually want to test something where an exception is thrown by _close() is that the resulting RuntimeException seems to be handled by JUnit in an "unconditional" way: it seems always to stop the test with a failure message... even if you actually catch and deal with it in a try .. catch!
There is a sort of "workaround" for this which I've found (the CUT class closes all its closeableComponents when it is closed):
#Test (expected = RuntimeException.class)
public void errorFlagShouldBeSetIfAnyCloseablesThrowExceptionWhenCUTCloses() throws Exception {
Closeable spyCloseable = spy( new Closeable(){
#Override
public void close() throws IOException {
throw new IOException( "dummy" );
}});
spyCUT.addCloseableComponent( spyCloseable );
Exception blob = null;
try{
spyCUT.close();
}catch( Exception e ){
blob = e;
}
assertThat( spyCUT.getErrorFlag() ).isTrue();
if( blob != null ){
throw blob;
}
I.e. if you don't have this expected setting you always get a test failure (because of the RuntimeException "ignoring" the try .. catch). But in order to satisfy the expected you then have to rethrow the RuntimeException at the end of the test...
... is there any way of varying JUnit's handling of RuntimeExceptions?
Something must be wrong in your setup. JUnit does not have any such special handling for runtime exceptions.
I put together this MCVE; and it passes.
static class CUT {
void close(Closeable _close) {
try {
_close.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
#Test
public void test() throws Exception {
Closeable spyCloseable = Mockito.spy(new Closeable() {
#Override
public void close() throws IOException {
throw new IOException("dummy");
}
});
Exception blob = null;
try {
new CUT().close(spyCloseable);
fail("should have thrown");
} catch (Exception e) {
blob = e;
}
assertThat(blob.getMessage(), is("java.io.IOException: dummy"));
}
It is not exactly what you have up there; but "close enough" in my mind.
Long story short: your answer is coming from some other place. I suggest: do the same as I did: create a true mcve; and work your way from there!
I am coding a Java Library that will be used to access a DB.
I am throwing the exceptions to the end-programmer who uses the JAR library to handle it the way he/she wants.
I wrote a custom Exception (provided below) to wrap connection specific exceptions together so the end-programmer will not have to catch all these exceptions in his code. (to make it easy for him)
is this a good practice when it comes to coding Java libraries?
By using this the user will only have to catch NConnectionException in his code.
public class NConnectionException extends Exception {
private static final Logger logger = LoggerFactory.getLogger(NConnectionException.class);
public NConnectionException(Exception e) {
if (e instanceof NullPointerException) {
logger.error("ERROR IN READING DF");
e.printStackTrace();
}
else if (e instanceof FileNotFoundException) {
logger.error("FILE NOT FOUND");
e.printStackTrace();
} else if (e instanceof ParserConfigurationException)
{
logger.error("PARSE CONF ERR");
e.printStackTrace();
}
else if (e instanceof org.xml.sax.SAXException)
{
logger.error("SAX ERR");
e.printStackTrace();
}
else if (e instanceof IOException)
{
logger.error("IO ERR");
e.printStackTrace();
}
}
}
You can pass a cause (Throwable) to a custom exception. Look at the Exception javadoc for more Information.
Edit:
public class CustomException extends Exception {
public CustomException(Throwable t) {
super(t);
}
}
public void testMethod(String s) throws CustomException {
try {
int integer = Integer.parseInt(s);
} catch (NumberFormatException e) {
throw new CustomException(e);
}
}
try {
testMethod("not a number");
} catch (CustomException ce) {
ce.printStackTrace(); // this will print that a CustomException
// with the cause NumberFormatException has occured.
ce.getCause(); // this will return the cause that
// we set in the catch clause in the method testMethod
}
According to this post, wrapping all the exceptions in a single is not good.
If you want to wrap them then
As your program will throw only one exception at a time then no need to store list of exceptions in NConnectionException.
And you can create a single object of exception in NConnectionException class. You can refer this structure.
And store the thrown exception in that object and throw back newly created object of NConnectionException class. Let the calling program catch NConnectionException exception and take out the stored object and act accordingly.
Note : Generally we don't handle unchecked exception (like NullPointerException), calling program will take care of it.
I have the following scenario.
public void foo() throws BadFooException, IOException{
try{
..........
} catch(ArrayIndexOutOfBoundException e) {
throw new BadFooException(e);
} catch(ArithmeticException e) {
throw new BadFooException(e);
}
}
Here BadFooException is a class that extends Exception. But to my desire BadFooException shall only catch
ArrayIndexOutOfBoundException
and
ArithmeticException
not the other exceptions. I am always catching those two exception and throwing my desired exception. But is there any way, so that my desired exception will be thrown automatically in case of only these two exceptions but other exceptions will be thrown separately?
Thanks in advance.
It's quite clear what you ask... However if you want to combine several exceptions, to save some typing work, you could use:
public void foo() throws CustomException1, OtherException {
try {
// stuff (that can throw Exception1, Exception2 and OtherException)
} catch (Exception1 | Exception2 ex) {
throw new CustomException1(ex);
}
}
Thus with a vertical bar in between.
As far as I know, there is no more elegant way to do this.