In C#, I can use the throw; statement to rethrow an exception while preserving the stack trace:
try
{
...
}
catch (Exception e)
{
if (e is FooException)
throw;
}
Is there something like this in Java (that doesn't lose the original stack trace)?
catch (WhateverException e) {
throw e;
}
will simply rethrow the exception you've caught (obviously the surrounding method has to permit this via its signature etc.). The exception will maintain the original stack trace.
You can also wrap the exception in another one AND keep the original stack trace by passing in the Exception as a Throwable as the cause parameter:
try
{
...
}
catch (Exception e)
{
throw new YourOwnException(e);
}
I would prefer:
try
{
...
}
catch (FooException fe){
throw fe;
}
catch (Exception e)
{
// Note: don't catch all exceptions like this unless you know what you
// are doing.
...
}
In Java is almost the same:
try
{
...
}
catch (Exception e)
{
if (e instanceof FooException)
throw e;
}
In Java, you just throw the exception you caught, so throw e rather than just throw. Java maintains the stack trace.
Stack trace is prserved if you wrap the catched excetion into an other exception (to provide more info) or if you just rethrow the catched excetion.
try{
...
}catch (FooException e){
throw new BarException("Some usefull info", e);
}
something like this
try
{
...
}
catch (FooException e)
{
throw e;
}
catch (Exception e)
{
...
}
public int read(byte[] a) throws IOException {
try {
return in.read(a);
} catch (final Throwable t) {
/* can do something here, like in=null; */
throw t;
}
}
This is a concrete example where the method throws an IOException. The final means t can only hold an exception thrown from the try block. Additional reading material can be found here and here.
I was just having a similar situation in which my code potentially throws a number of different exceptions that I just wanted to rethrow. The solution described above was not working for me, because Eclipse told me that throw e; leads to an unhandeled exception, so I just did this:
try
{
...
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
throw new RuntimeException(e.getClass().getName() + ": " + e.getMessage() + "\n" + e.getStackTrace().toString());
}
Worked for me....:)
Related
I have a function that throws several different types of custom Exceptions. I wish to catch these exceptions from that function, add some important information, and then throw the exception as their original type to pass up the caller chain (exception chaining). I would like this to be compact in a single catch if possible.
I know Java 7+ has the functionality to handle multiple Exception types and throw them while maintaining their type. However, when exception chaining I cannot catch and throw multiple Exception types in the same catch block without losing the type. Is it possible to throw an exception maintaining its original type in a single catch block that accepts multiple Exception types? Or do I have to split it into 3 nearly-equivalent (essentially redundant) catch blocks?
Example:
void thisWorks() {
try {
someFunction(); // throws ExceptionA, ExceptionB, ExceptionC
} catch (ExceptionA | ExceptionB | ExceptionC exception) {
throw exception; // still has the original ExceptionA/ExceptionB/ExceptionC type
}
}
void whatIWant() {
try {
someFunction();
} catch (ExceptionA | ExceptionB | ExceptionC exception) {
// This throws an Exception, not the original ExceptionA/ExceptionB/ExceptionC type.
// Is it possible to fit this in a single block like the thisWorks() function?
// Or do I have to split into 3 catch blocks just for the throw type?
throw new Exception("Important information here", exception);
}
}
i don't think there simple approach if you don't like multiple catch my approach would be something like this but to me one way or the other you still have some redundance either mutiple catch or do multiple instanceof your exception.
try {
someFunction()
} catch (Exception ex) {
if (ex instanceof ExceptionA) {
throw new ExceptionA("Important information here", ex);
} else if(ex instanceof ExceptionB){
throw new ExceptionB("Important information here", ex);
} else {
throw new ExceptionC("Important information here", ex);
}
}
public class MyThrowClass {
public static void main(String[] args) throws Exception {
try {
someFuntion(1);
} catch (Throwable t) {
throw new Exception("Important information here", t);
}
}
public static void someFuntion(int value) throws ExceptionA, ExceptionB {
if (value == 1) {
throw new ExceptionA("Exception A");
}
throw new ExceptionB("Exception B");
}
}
I am able to catch RuntimeException or subclass of it with below code:
try {
//code that throws subclass of RuntimeException
throw new ChildRuntimeException("try");
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
But I am getting error with below code and not able to catch RuntimeException in Exception catch block.
try {
// code that throws subclass of Exception
throw new ChildExceptionClass("try");
} catch (ChildExceptionClass ex) {
throw new RuntimeException(ex.getMessage());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
I searched for the same type of questions but did not find a suitable answer. Can
anyone explain why the behaviour is different?
In the second example you are throwing a childRuntimeException, which is caught, but then a new runtimeException is thrown. This block has no "catch" clause, so the exception is thrown and not caught.
The second catch is relevant for the "try" block, not for the "catch" block.
What I guess you probably want to do is:
try { // code that throws subclass of Exception
throw new ChildExceptionClass("try");
} catch (ChildExceptionClass ex) {
try {
throw new RuntimeException(ex.getMessage());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
Do you understand the difference?
I have a code that invokes an external API via EJB and that API occasionally leaks an exception that is not part of the client kit, therefore resulting in ClassNotFoundException.
I have a try-catch block surrounding the call:
try {
thirdPartyLibrary.finalInvokeMethod();
} catch (SomeException exception) {
//Do something
} catch(
..
} catch (Exception exception) {
if (exception instanceof ClassNotFoundException) {
log.error("....");
}
}
I want to avoid using instanceof in catch, but if I add a separate catch clause for ClassNotFoundException, the compiler produces an error "Unreachable catch block", since thirdPartyLibrary.finalInvokeMethod(); doesn't throw ClassNotFoundException.
Is there a better way to address the issue?
I've found a workaround. I've wrapped the thirdPartyLibrary.finalInvokeMethod(); in another method that throws the checked exception. So I got a dedicated catch clause without a compiler error.
private someMethod() {
try {
callExternalAPI();
} catch (SomeException exception) {
//Do something
} catch(
..
} catch (ClassNotFoundException exception) {
log.error("....");
//Do something
} catch (Exception exception) {
//Do something
}
}
private void callExternalAPI() throws ClassNotFoundException {
thirdPartyLibrary.finalInvokeMethod();
}
I have been trying to find out answer to this question but did not get any satisfactory explanation. Here is some background:
Java 7 allows us to catch multiple exceptions in a single catch block provided those exceptions are from diffrent hierarchy. Eg:
try {
// some code
} catch(SQLException | FileNotFoundException e) {
e.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
But if exceptions are from the same hierarchy we must use multiple catch blocks like:
try {
// some code
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
But if I try to write code like below compiler complains that "The exception FileNotFoundException is already caught by the alternative IOException"
try {
// some code
} catch(FileNotFoundException | IOException e) { // compiler error
e.printStackTrace();
}
Now my question is: Why compiler reports an error in last case, can't it figure out that FileNotFoundException is special case of IOException? This would save code duplication when my exception handling logic is same.
Why compiler reports an error in last case, can't it figure out that FileNotFoundException is special case of IOException?
Because FileNotFoundException is a subclass of IOException. In other words, the "FileNotFoundException |" part is redundant.
The reason why the code below is ok...
} catch(FileNotFoundException e) {
...
} catch(IOException e) {
...
}
...is because here the IOException clause matters: If a SocketException is thrown for instance, it will pass the by the FileNotFoundException part, and get caught in the IOException clause.
When catching an exception you have order your catch clauses from the most specific to the most general.
Consider the following hierachy:
class MyException extends Exception {}
class MySubException extends MyException {}
If a part of your code throws MyException an an other part throws MySubException you have to catch MySubException first.
catch(MySubException e){
} catch(MyException e){
}
Its the same thing like using the instanceof operator.
If you test if an instance of MySubException is an instanceof MyException the result will be true.
mse = new MySubException();
if(mse instanceof MyException){
println("MyException");
} else if(mse instanceof MySubException){
println("MySubException");
}
This piece of code will never print "MySubException".
mse = new MySubException();
if(mse instanceof MySubException){
println("MySubException");
} else if(mse instanceof MyException){
println("MyException");
}
This would be the correct order.
Its because FileNotFoundException extends IOException, as you said its of same hierarchy, you cannot add them to same catch block.
Sonar gives a major violation error ("Preserve Stack Trace") for the following code. Following method is used to throw an exception. What are the steps should I take to overcome this violation?
public void exceptionHandler(String exception) throws PhDashException {
String exceptionMsg = exception.replaceAll("-", "_");
ExceptionPhDash pHDashExceptionMapper = new ExceptionPhDash();
try {
pHDashExceptionMapper = new ObjectMapper().readValue(exceptionMsg, ExceptionPhDash.class);
} catch (JsonParseException e) {
LOGGER.info(e.getMessage());
} catch (JsonMappingException e) {
LOGGER.info(e.getMessage());
} catch (IOException e) {
LOGGER.info(e.getMessage());
}
throw new PhDashException(pHDashExceptionMapper.getMessage());
}
You've logged each exception; that should be enough as far as preserving information is concerned like below,
LOGGER.info("Unexpected Exception has occurred", e);
Or You should re throw the PhDashException if you can, because, you should be enough as far as preserving information is concerned
throw new PhDashException(pHDashExceptionMapper);