How to prevent exception catching when we need to throw custom exceptions? - java

void connectOverNetwork() throws Exception {
try {
final JSONObject response = make network call;
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new Exception("message replied with error");
}
} catch (final Exception e) {
LOG.error("---- bar message ---");
throw new SvcException("failed to connect over network");
}
}
In the code above, I am throwing an exception with a failure message.
At the same time, I am also throwing an error on failure to connect over the network.
But, if I throw an exception for !success it gets caught again, causing duplicate logging. I do not want to print bar message, if I only want to log foo message.
How to prevent it from happening?

Validate the response after the try-catch statement.
JSONObject response = null;
try {
response = /* make network call */;
} catch (final Exception e) {
LOG.error("---- bar message ---");
throw new SvcException("failed to connect over network");
}
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new Exception("message replied with error");
}
I don't recommend catching Exception - it's too general, I suggest you narrow it down to a more specific exception type.

What if you move it outside the try block.. Anyway, the reason for the first try..catch is to catch any Exception from the network call.
JSONObject response = null;
try {
response = make network call;
} catch (final Exception e) {
LOG.error("---- bar message ---");
throw new SvcException("failed to connect over network");
}
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new Exception("message replied with error");
}

First, let me point out a mistake in your code. Your method declares that it throws Exception, but it doesn't. It throws SvcException. So that's what the "throws" clause should say. (You should never say "throws Exception" anyway. You should state explicitly what kind of exception it throws.) The rest of the answer depends on whether or not your vague description "make network call" throws an exception or not.
If it doesn't, your method should look like this:
void connectOverNetwork() throws SvcException {
final JSONObject response = makeNetworkCall();
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new SvcException("message replied with error");
}
}
But that's unrealistic. Chances are, your "make network call" code throws something like IOException. In this case your code should look like this:
void connectOverNetwork() throws SvcException {
try {
final JSONObject response = makeNetworkCall(); // throws IOException
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new SvcException("message replied with error");
}
} catch (final IOException e) {
LOG.error("--- foo message ---");
throw new SvcException("failed to connect", e); // wrap e inside SvcException
}
}
Notice that I wrap the caught IOException inside the SvcException. If your SvcException doesn't do that, either rewrite it so that it can, or call its initCause() method before throwing it. You should always include the original exception when reThrowing a different exception.
Also notice that I don't bother throwing, then catching and rethrowing an IOException. When I detect failure. I just throw the exception that I need to throw. This means I need to log the foo message in two separate places. For most things, repeating a line of code should be avoided, but for logging, this is fine.
But this code is a bit messy. I would clean it up by separating the test for success from the possible IOException. So I would write it like this:
void connectOverNetwork() throws SvcException {
JSONObject response; // no need to initialize this.
try {
response = makeNetworkCall(); // throws IOException
} catch (final IOException e) {
LOG.error("--- foo message ---");
throw new SvcException("failed to connect", e); // wrap e inside SvcException
}
if (!response.getBoolean(SUCCESS)) {
LOG.error("--- foo message ---");
throw new SvcException("message replied with error");
}
}
Notice here that response is declared before the try loop. It's not initialized because there's no way it will reach the !response.getBoolean(SUCCESS) test without a value. If makeNetworkCall() throws an exception, it won't even reach that line.

Create your own exception type and don't catch it.
try {
do stuff
if (condition)
throw new MyCustomException("error")
} catch (IOException e) {
log and rethrow
}

Related

Java Exception handling for below use case

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.

Should I re-throw an exception after logging it?

I find myself coding methods that throw a specified error, but still surrounding the relevant code sections in a try catch, where I use the catch to log a localised error message and re-throw the principal one.
Here is a short example:
public void doWork(String url) throws IOException {
Object target;
try {
target = new target(url); //instantiating this object could potentially not work if the URL is malformed
} catch (MalformedURLException e) {
localErrorMessage(debug, "URL error here"); //log a local message
throw e;
} catch (IOException e) { //in some cases it can throw an IO exception if using a localised file type object.
localErrorMessage(debug, "IO error here"); //log a local message throw e;
}
}
I use this as I can turn off my localised logging (using log4j2), or use it during testing, as a debugging method.
Is this a reasonable practice, or is there a better way to do it?

How to get an exception message in a String variable in java?

I need to process an exception message when any exception is caught in Java.
I am working on a Database Connection class. When I give wrong details like username, password, host name, sid, etc, the control goes to catch block and gives an error. I would like to get this error message on the JSP side and redirect to the same page with that error message. However, when I get the error message in Java, it always takes a null value.
My code example is here.
String errorMessage = null;
try{
// CODE Where Exception occure
}catch(SQLException se){
errorMessage = se.getMessage();
}catch(Exception e){
System. out.println("In Exception block.");
errorMessage = e.getMessage();
}finally{
System.out.println(errorMessage);
}
It will go to Exception block but the errorMessage is null.
At first, the answer of #Artem Moskalev should be right in most ways. In your case, you'd said:
It will goes to Exception block but the errorMessage is null.
So, let's try two cases to debug the behavior:
First:
class Test1
{
public static void main (String[] args) throws java.lang.Exception
{
String errorMessage = null;
try{
throw(new Exception("Let's throw some exception message here"));
}catch(Exception e){
System.out.println("In Exception block.");
errorMessage = e.getMessage();
}finally{
System.out.println(errorMessage);
}
}
}
Output:
In Exception block.
Let's throw some exception message here
Seems to work like you expected.
Second:
class Test2
{
public static void main (String[] args) throws java.lang.Exception
{
// String errorMessage = null;
// To make the difference between non-initialized value
// and assigned null value clearer in this case,
// we will set the errorMessage to some standard string on initialization
String errorMessage = "Some standard error message";
try{
throw(new Exception());
}catch(Exception e){
System.out.println("In Exception block.");
errorMessage = e.getMessage();
}finally{
System.out.println(errorMessage);
}
}
}
Output:
In Exception block.
null
Why is that? Because you're accessing e.getMessage(), but if the message is emtpy e.getMessage() will return null. So the null isn't from the initialization, but from the return value of e.getMessage(), when e doesn't have any error message (for example if there is a NullPointerException thrown).
This block is always executed:
...finally{
System.out.println(errorMessage);
}
If your errorMessage has not been assigned any other value before (ie. no exception thrown in your try clause) - System.out.println will print you the errorMessage value which is null.
your catch(Exception e) block will catch all exceptions (other than SQLException which you are specifically catching above). Some exceptions e.g. NullPointerException can have null details message i.e. e.getMessage() can retun null. So it is better to print the exception details like exception type also- use e.ToString() or e.printStacktrace() for more details.

rethrow java exception with new message, preserving the exception type if it is in the method declaration list

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.

Throwing exceptions at the correct time

Just came across a rather confusing exam question, and my lecturer is away on holidays, so I come to StackOverflow begging for help!
The question is as follows :
"Joe has his own JoeConnection class for making connections between his computer and other computers. The class provides the following constructor and instance methods :
JoeConnection( String address ): Make a connection with the URL address.
void writeLn( String text ) : Write text to the JoeConnection.
String readLn( ): Read a line of text from the JoeConnection.
void clode( ) : Close the JoeConnection.
Joe's connections regularly fail and this causes errors. Using proper exception handling, demonstrate how to use Joe's JoeConnection class to
make a JoeConnection with the URL http://students.chat.box
write "Hello world" to the JoeConnection
read in a string from the JoeConnection
close the connection.
The connection handling should provide as man details as possible about the cause of failure and print the stack trace which led to the failure.
I have no idea how to tackle this, but I assume it is something similar to this :
public class Test {
try {
JoeConnection connection = new JoeConnection(http://students.chat.box);
} catch {
connectionError e; printStacktrace();}
}
}
Can anyone please help me figure this out? Thanks a lot.
Without an indication of what exceptions are thrown and why, the only proper exception handling is no handling at all. Don't catch an exception if you don't know how to fix the problem that triggered it.
But the further instructions in your assignment introduce a different notion of "proper." You're supposed to print a stack trace. So catch the exception and print a stack trace. You were on the right track, but your syntax was wrong. Refer back to your textbook and lecture notes to remind yourself what the syntax is for catching exceptions (and for passing strings to functions, for that matter).
try {
JoeConnection connection = new JoeConnection("http://students.chat.box");
connection.writeLn("Hello world");
// etc
} catch (Exception e) {
e.printStackTrace();
}
"Proper exception handling" is a little vague. I agree with #Rob Kennedy's statement that no exception handling is appropriate unless you know why the exception is thrown and what should be done with it. Otherwise, the exception should be allowed to propagate. So, for example:
void foo(String address) throws JoeException {
JoeConnection connection = new JoeConnection(address);
try {
connection.writeLn("Hello World!");
} finally {
// Ensure the connection is closed when finished.
// This happens whether an exception occurs or not.
connection.close();
}
}
If you wanted to catch the exception just to print it, you could do something like this:
void foo(String address) throws JoeException {
try {
JoeConnection connection = new JoeConnection(address);
try {
connection.writeLn("Hello World!");
} finally {
connection.close();
}
} catch (JoeException e) {
e.printStackTrace();
// Don't know what to do about this; rethrow.
throw e;
}
}
There is a subtlety here that even experience Java programmers can miss, though. If an exception occurs while creating the connection, it doesn't need to be closed. If an exception occurs while writing to the connection, it does need to be closed; thus the finally clause. However, the act of closing can also throw an exception. If closing the connection throws an exception, only that exception will be thrown by the try statement. If the finally clause was reached as a result of the writeLn operation throwing an exception, the exception of the writeLn call will be effectively ignored. This is probably not what you want.
Instead, we can try something ugly like this:
void foo(String address) throws JoeException {
try {
JoeConnection connection = new JoeConnection(address);
boolean normalCompletion = false;
try {
connection.writeLn("Hello World!");
normalCompletion = true;
} finally {
if (normalCompletion) {
// The writeLn operation completed normally.
// Propagate an exception thrown by the close operation.
connection.close();
} else {
// The writeLn operation completed abruptly.
// Ignore an exception thrown by the close operation.
try {
connection.close();
} catch (JoeException e) {
/* empty */
}
}
}
} catch (JoeException e) {
e.printStackTrace();
// Don't know what to do about this; rethrow.
throw e;
}
}
This looks (and is) syntactically hideous, but it does show "proper" exception handling of a sort. The language enhancement from Project Coin should clean this up a bit.
For starters, I can help you out with the syntax of what you wrote:
try {
JoeConnection connection = new JoeConnection("http://students.chat.box");
}
catch (JoeConnectionException e) {
e.printStacktrace();
}
I took the liberty of changing the linebreaks and renaming 'connectionError' as JoeConnectionException which looks more conventional to me.
You'll have to do something similar for the readLn, writeLn, and close method calls since it said that the connection regularly fails (i.e. not just while connecting).
Cheers, good luck.
Catching an exception should look like:
try {
JoeConnection conn = new JoeConnection(url);
} catch (YourExceptionClassNameHere e) {
e.printStackTrace();
}
Also: if you want to use a literal String, make sure you include the quotations. (It should be "http://students.chat.box".)
It's good to have a finally as well:
public class Test {
try {
JoeConnection connection = new JoeConnection(http://students.chat.box);
}
catch(Exception e) {
e.printStacktrace();
}
finally {
if(connection != null) {
connection.close();
}
}
}
Typically you handle exceptions if you know what to do with them (this involves error-recovery logic or wrapping an exception and throwing it to a higher level).
Assuming that each method throws an exception, you could do something like this for "maximum detail":
public class Test {
JoeConnection connection = null;
try {
connection = new JoeConnection("http://students.chat.box");
...
...
}
catch(OpenException e) {
System.out.println("Error while opening connection");
e.printStacktrace();
}
catch(WriteException e) {
System.out.println("Error while writing to connection");
e.printStacktrace();
}
catch(ReadException e) {
System.out.println("Error while reading from connection");
e.printStacktrace();
}
finally {
if(connection != null) {
connection.close();
}
}
}

Categories