In Java 7 Rethrow Exception feature added.I know it's concept but I want to see the real application of it and why this feature needed?
I will take examples from here
This is the example:
static class FirstException extends Exception { }
static class SecondException extends Exception { }
public void rethrowException(String exceptionName) throws FirstException, SecondException {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (FirstException e) {
throw e;
}catch (SecondException e) {
throw e;
}
}
This compiles with both java 6 an 7.
If you want to keep checked exceptions from method signature, you have to keep cumbersome catch clauses in java 6.
In Java 7 you can do it in following way:
public void rethrowException(String exceptionName) throws FirstException, SecondException {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (Exception e) {
throw e;
}
So your benefit is that you have less cumbersome catch clause.
Use Rethrowing Exceptions with More Inclusive Type Checking feature
in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration
When you want to declare specific exceptions that can be thrown (mainly when you are catching a generic error)
For example see Precise Rethrow example:
public static void precise() throws ParseException, IOException{
try {
new SimpleDateFormat("yyyyMMdd").parse("foo");
new FileReader("file.txt").read();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
throw e;
}
}
This also make your code compliant to Sonar's Raw Exception rule.
Note you can similarly catch Throwable
Couple of use-cases:
Using rethrow, you can edit the stacktrace information to make
it more accurate. Also when needed you can hide or rid off the
unnecessary internal details in stack trace.
try { //... }
catch (Exception e) { throw (Exception) e.fillInStackTrace(); }
Real application of fillInStackTrace is very well explained here:
Why is Throwable.fillInStackTrace() method public? Why would someone use it?
Quote from the book "Thinking in Java" written by Bruce Eckel:
If you want to install new stack trace information, you can do so by
calling fillInStackTrace( ), which returns a Throwable object that it
creates by stuffing the current stack information into the old
exception object
Add custom message to the thrown exception. Add custom message to thrown exception while maintaining stack trace in Java
A simple example I can think of:
void fileOperator(String operationType) throws Exception(){ ... }
void fileReader() throws Exception {
try{
fileOperator('r');
}
catch(Exception e){
throw Exception("Failed to read the file", e);
}
}
void fileWriter() throws Exception{
try{
fileOperator('w');
}
catch(Exception e){
throw Exception("Failed to write the file", e);
}
}
Also, we can throw a more specific exception type (say FileReadException, FileWriteException) from the catch block.
Related
In Java, if I declare and caught an exception, can I handle the exception in a caller anyway? Or it needs not to be caught to handle it by caller?
class A {
void first() throws Exception {
try {
throw new Exception("my exception")
} catch (Exception e) {
log.message("Error in first()", e.getCouse)
throw e
}
}
}
class B {
Result second(A a) {
try {
a.first()
} catch (Exception e) {
log.message("Caught in B class", e.message)
return new Result(result: null, error: e.message)
}
}
second(A a)
}
You can 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.
catch (WhateverException e) {
throw e;
}
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 have below code.
The question is :
Is there a better way to handle exception for below use case other than this ?
My particular interest is using handleException method.
public void checkSomeBehaviour() throws Exception{
try{
someBusinessValidation() ;
//this method can throw BusinessValidationException which is subclass of Exception
//BusinessValidationException contains code in getMessage() method
try{
doSomething();
}catch(Exception ex1){
//throw Exception object with specific error code say 123. So this needs to be wrapped in separate try/catch
throw CustomException('123'); //CustomException is subclass of Exception
}
try{
doSomethingElse();
}catch(Exception ex2){
//throw Exception object with specific error code say 456 .So this needs to be wrapped in separate try/catch
throw CustomException('456'); //CustomException is subclass of Exception
}
}
catch(Exception ex){
//Based on Exception type , a common exception needs to be thrown as ValidationException
handleException(ex);
}
}
//this method inspects exception type and does appropriate action accordingly
private void handleException(Exception ex){
if(ex instanceof CustomException){
throw new ValidationException(ex.getCode());
}else if(ex instanceof BusinessValidationException){
throw new ValidationException(ex.getMessage());
}else{
throw new ValidationException(100); //throw code as 100 since this is generalised exception
}
}
Answer is: YES. Java gives you native syntax to do just that (cleaner and simply more appropriate than checking exception classes):
//...your try block
} catch (CustomException ex) {
throw new ValidationException(ex.getCode());
} catch (BusinessValidationException ex) {
throw new ValidationException(ex.getMessage());
} catch (Exception ex) {
throw new ValidationException(100);
}
Just note that you may need to reorder these catch blocks if they extend one another.
If you don't have any business logic between method calls then you can declare errorCode as a variable, change it after method execution and re-throw appropriate exception in catch, e.g.:
public void checkSomeBehavior() throws Exception{
int errorCode = 123;
try{
someBusinessValidation();
doSomething();
errorCode = 456;
doSomethingElse();
}catch(BusinessValidationException bve){
throw new Exception(bve.getMessage());
}catch(Exception e){
throw new Exception(String.valueOf(errorCode));
}
}
If doSomething fails, the value will be 123 and if doSomethingElse fails, the value will be 456.
Take this as example:
public class TestClass {
public static void test() throws SSLHandshakeException {
throw new SSLHandshakeException("I'm a SSL Exception");
}
public static void main(String[] args) throws SSLHandshakeException {
try {
test ();
} catch (IOException ioe) {
System.out.println("I`m handling IO exception");
}
}
}
So, I have my test method in which I'm just throwing an SSLHandshakeException which is a subtype of IOException.
The output for this is "I`m handling IO exception".
Why does this happen? I expected that my method will throw the SSLHandshakeException. Is there a rule that catch is more important than throws?
I just want to avoid using
try {
test ();
} catch (SSLHandshakeException se) {
throw se;
} catch (IOException ioe) {
System.out.println("I`m handling IO exception");
}
Because I consider it less readable
Is there a rule that catch is more important than throws?
They are two completely different things. The throws keyword is part of the method signature and is saying 'This method can throw this exception, so every caller should handle that explicitly.'
Wether or not the method actually throws that exception is irrelevant here.
As for the catch statement. SSLHandshakeException is an IOException, and so it is caught as expected.
To get the behaviour you intent you can write:
try {
test ();
} catch (SSLHandshakeException sslExc) {
throw sslExc;
} catch (IOException ioe) {
System.out.println("I`m handling IO exception that is not an SSLHandshakeException");
}
Edit: You say you find this less readable. But honestly this is just the best way. If it would behave the way you proposed than you would never be able to catch an SSLHandshakeException in a method that might also throw it? What if you want to catch it in certain conditions but throw it in others? It would just be too limiting and unintuitive.
An alternative is like so; but in my opinion this is even less readable:
try {
test ();
} catch (IOException ioe) {
if(ioe instanceof SSLHandshakeException)
throw ioe;
System.out.println("I`m handling IO exception that is not an SSLHandshakeException");
}
That's probably because you printed your custom string instead of message of exception. Try this :
public static void main(String[] args) throws SSLHandshakeException {
try {
test ();
} catch (IOException ioe) {
System.out.println("I`m handling IO exception");
System.out.println(ioe.getMessage());
}
}
SSLHandshakeException is a subclass of javax.net.ssl.SSLException wich is a subclass of java.io.IOException.
So this code :
public static void main(String[] args) throws SSLHandshakeException {
try {
test ();
} catch (IOException ioe) {
System.out.println("I`m handling IO exception");
}
}
will catch and IOException, and thus print the message "I`m handling IO exception".
I am trying to create a helper method that will eliminate the need of having code like this:
void foo() throws ExceptionA, ExceptionB, DefaultException {
try {
doSomething(); // that throws ExceptionA, ExceptionB or others
} catch (Exception e) {
if (e instanceof ExceptionA)
throw new ExceptionA("extra message", e);
if (e instanceof ExceptionB)
throw new ExceptionB("extra message", e);
throw new DefaultException("extra message", e);
}
}
The problem is that I need to maintain the throws list in the function declaration and in the body of the function at the same time. I am looking how to avoid that and to make changing the throws list sufficient and my code to looks like:
void foo() throws ExceptionA, ExceptionB, DefaultException {
try {
doSomething(); // that throws ExceptionA, ExceptionB or others
} catch (Exception e) {
rethrow(DefaultException.class, "extra message", e);
}
}
Where rethrow method will be smart enough to recognize the throws list from the method declaration.
This way when I change the list of type that my method propagates in the throws list I to not need to change the body.
The following is a function that could solve the problem. The problem is because it does not know what type of exception it will throw its throws declaration has to say Exception, but if it does this, the method that is going to use it will need to specify it as well, and the whole idea of using the throws list goes to hell.
Any suggestions how this could be solved?
#SuppressWarnings("unchecked")
public static void rethrow(Class<?> defaultException, String message, Exception e) throws Exception
{
final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
final StackTraceElement element = ste[ste.length - 1 - 1];
Method method = null;
try {
method = getMethod(element);
} catch (ClassNotFoundException ignore) {
// ignore the Class not found exception - just make sure the method is null
method = null;
}
boolean preserveType = true;
if (method != null) {
// if we obtained the method successfully - preserve the type
// only if it is in the list of the thrown exceptions
preserveType = false;
final Class<?> exceptions[] = method.getExceptionTypes();
for (Class<?> cls : exceptions) {
if (cls.isInstance(e)) {
preserveType = true;
break;
}
}
}
if (preserveType)
{
// it is throws exception - preserve the type
Constructor<Exception> constructor;
Exception newEx = null;
try {
constructor = ((Constructor<Exception>) e.getClass().getConstructor());
newEx = constructor.newInstance(message, e);
} catch (Exception ignore) {
// ignore this exception we prefer to throw the original
newEx = null;
}
if (newEx != null)
throw newEx;
}
// if we get here this means we do not want, or we cannot preserve the type
// just rethrow it with the default type
Constructor<Exception> constructor;
Exception newEx = null;
if (defaultException != null) {
try {
constructor = (Constructor<Exception>) defaultException.getConstructor();
newEx = constructor.newInstance(message, e);
} catch (Exception ignore) {
// ignore this exception we prefer to throw the original
newEx = null;
}
if (newEx != null)
throw newEx;
}
// if we get here we were unable to construct the default exception
// there lets log the message that we are going to lose and rethrow
// the original exception
log.warn("this message was not propagated as part of the exception: \"" + message + "\"");
throw e;
}
Update 1:
I can use RuntimeException to avoid the need of throws declaration, but in this case I am losing the type of the exception which is one of the most important points.
Ideas how I can resolve this?
I'm guessing that code where you're doing real work (ie. the part where you're not tinkering with exceptions) looks like this.
public void doSomeWork( ... ) throws ExceptionA, ExceptionB, DefaultException
{
try
{
// some code that could throw ExceptionA
...
// some code that could throw OtherExceptionA
...
// some code that could throw ExceptionB
...
// some code that could throw OtherExceptionB
}
catch (Exception e)
{
if( e instanceof ExceptionA )
{
throw new ExceptionA("extra message", e);
}
if( e instanceof ExceptionB )
{
throw new ExceptionB("extra message", e);
}
throw new DefaultException("extra message", e);
}
}
There are two better approaches
First Approach
public void doSomeWork( ... ) throws ExceptionA, ExceptionB, DefaultException
{
// some code that could throw ExceptionA
...
try
{
// some code that could throw OtherExceptionA
...
}
catch (Exception e)
{
throw new DefaultException("extra message", e);
}
// some code that could throw ExceptionB
...
try
{
// some code that could throw OtherExceptionB
}
catch (Exception e)
{
throw new DefaultException("extra message", e);
}
}
Second Approach
public void doSomeWork( ... ) throws ExceptionA, ExceptionB, DefaultException
{
try
{
// some code that could throw ExceptionA
...
// some code that could throw OtherExceptionA
...
// some code that could throw ExceptionB
...
// some code that could throw OtherExceptionB
}
catch (OtherExceptionA | OtherExceptionB e)
{
throw new DefaultException("extra message", e);
}
}
The first approach is good if you want to continue execution at all costs and catch and wrap RuntimeExceptions if you run into them. Generally you don't want to do this, and it's better to let them propagate up, as you probably can't handle them.
The second approach is generally the best. Here you're explicitly pointing out which exceptions you can handle, and dealing with them by wrapping them. Unexpected RuntimeExceptions propagate up, as they should unless you have some way of dealing with them.
Just a general comment: playing with StackTraceElements isn't considered to be a great idea. You may end up getting an empty array from Thread.currentThread().getStackTrace() (although you most likely will not if using a modern Oracle JVM), and the depth of the calling method isn't always length-2, it may be length-1 particularly in older versions of the Oracle JVM.
You can read more about this problem in this question.
To elaborate on what )some) people are telling you, this is MyFunctionFailedException, ofcourse it should be named something more sensible:
public class MyFunctionFailedException extends Exception {
public MyFunctionFailedException(String message, Throwable cause) {
super(message, cause);
}
}
Then your catch block becomes something like this.
try {
...
} catch (Exception e) {
throw new MyFunctionFailedException("extra message", e);
}
If you really want to rethrow a lower level exception, you should use multiple catch blocks. Be aware tho' that not all types of Exceptions necessarily has a constructor that let's you add a cause. And you really should think about why it makes sense for your method to let for instance an uncaught SQLException bubble up the call stack.
In Java, if a general exception is caught and rethrown, will outer methods still be able to catch specific exceptions?
In other words, can I do this:
try {
try {
//...
} catch (Exception e) {
//...
throw e;
}
} catch (SpecificException e) {
//...
}
re-throwing an exception does not change anything about it (it's still the same object originally thrown).
While jtahlborn answer is correct, there is one more appreciation: the compiler will see that you are throwing an exception of the generic type (even if at runtime it can be only of the specific class) and will force you to declare the generic exception in the method header.
private void test() throws FileNotFoundException {
try {
throw new FileNotFoundException("Es una exception");
} catch (IOException e) {
throw e; <-- Error because the method only throws
FileNotFoundException, not IOException
}
}
e is indeed FileNotFoundException, but as it is declared as IOException the compiler works with the broader class. What you can do is "cast" the exception.
throw (FileNotFoundException) e;
Eclipse marks the "throw e" in the inner catch as an unhandled exception, BUT it does catch the exception because when I run this it prints "It worked!". Thanks #jtahlborn. Unfortunately this means that there will still need to be an unnecessary try/catch block somewhere.
public class Tester {
public static void main(String[] args) {
try {
try {
throw new SpecificException("Test!");
} catch (Exception e) {
throw e;
}
} catch (SpecificException e) {
System.out.println("It worked!");
}
}
}