Does it make sense to throw exception from catch block just to log the message so that we are sure that what is causing the exception?
Code
public void saveLogs(Logs logs) throws RemoteException
{
try
{
LogsOps.saveLogs(logs);
}
catch (RemoteException e)
{
log.info("RemoteException is thrown while trying to save logs ", e);
throw new RemoteException("RemoteException caused while trying to save", e);
}
}
In response to one of the comments below that this method would throw StackOverFlow Exception, here the actual implementation of log.info which just displays those errors.
/** Log the message and the exception with a level of INFO.
* #param message - The message text.
* #param t - An exception to display.
*/
public void info(Object message, Throwable t)
{
String nullSafeMessage = (message != null) ? message.toString() : t.getClass().getSimpleName();
log.info(nullSafeMessage, t);
}
So there never would be Stackoverflow exception thrown.
It depends on what's going to catch the exception higher up. If nothing else is going to log the message, then sure, it makes sense - although I'd probably rethrow the original exception instead of creating a new one:
catch (RemoteException e)
{
log.info("RemoteException is thrown while trying to save logs ", e);
throw e;
}
Ideally, though, you'd have a single catch block higher up the stack, which would log appropriately - if you're just logging the exception, that can get all the information anyway.
It may make sense to catch/log/rethrow when you want to log information which isn't present in the exception, such as parameter values.
Presuming that you will eventually handle the propagated exception, this tactic of catch-log-rethrow just clutters up the log file. Imagine that this is done the entire way up the stacktrace - you end up with reams of redundant error information that serves no useful purpose.
If you are not handling the exception you shouldn't log it either.
Besides for logging, this approach may also be used to perform necessary cleanup in case of a failure before returning control to a caller further up the stack.
For example
InputStream is = new InputStream( ... )
try {
is.read(...);
return is;
} catch ( IOException ioe ) {
is.close();
throw ioe;
}
This is, of course, a somewhat special use which can be avoided elegantly most of the time by using a finally clause - but not always, as the case above demonstrates.
Related
I am using a third party api to get user authentication in spring.
I need to catch the exceptions that occur when trying to connect to that api, like connection time out and page not found (if their server is down).
Right now I am trying to do this with below code. Is this sufficient to catch these exceptions?
public boolean userAuthentication(String userName) {
try {
if(hasAccess(userName)) {
return true;
} else {
return false;
}
} catch (IOException e) {
logger.info("exception occured "+ e);
return false;
}
}
Here hasAccess is the third party api, I cannot change that method. Whereas I need to catch these exception and give appropriate response to the user.
does hasAccess(String) define any throws statement?
Does it define that it throws IOException?
Do you have the access to the source code of this method? If you do then you can go and and check if they are handling any exceptions thrown or they are re-throwing any runtime exceptions.
To be on safer side, you should catch runtime exceptions, as the error is unpredictable for you, so you can gracefully handle errors.
It is impossible to tell whether this is sufficient without looking at the implementation of hasAccess(), since that is the function that will throw the error.
However, if you really need to catch this exception, you can always use
try {
if (hasAccess(userName)){}
} catch (Exception e) {
//caught
}
This isn't always good practice, since Exception will catch every exception, but it is a solution if you're looking for one.
I have a question about Java method introspection, specifically concerning exceptions. Say I have the following code:
private String getCustomReportResponse(HttpsURLConnection customReportConnection) {
int responseCode = 0;
try {
responseCode = customReportConnection.getResponseCode();
return httpResponseBodyExtractor.extractResponseBodyFrom(customReportConnection);
} catch (IOException e) {
translateIntoRelevantException(responseCode, e);
}
}
Let's say both statements in the try block are capable of throwing an IOException - in which case, the translateIntoRelevantException method is invoked, which looks like this:
private void translateIntoRelevantException(int responseCode, IOException e) {
if(is5xxResponseCode(responseCode)) {
throw new ServerResponseException("Could not generate report - returned response code " + responseCode, e);
}
throw new ReportException("GeminiReportException: Unable to parse response from HTTP body when requesting custom Gemini report.", e);
}
So, whatever happens, either a String is returned, or an exception is thrown. Except the getCustomReportResponse method does not compile without adding a return statement after the catch block, which is absolutely unreachable. In fact, if I put the contents of translateIntoRelevantException inside the catch block, it compiles, which seems daft to me.
I should add, the exceptions being thrown are runtime exceptions, but I've also tried making them checked exceptions, but the problem persisted.
Could someone please explain why?
This is a common problem that "rethrow" helper methods face.
The compiler does not know (and there is no way to indicate) that the method translateIntoRelevantException will never return.
As such, it thinks that there is a code-path that continues after try block. So you have to put in a "dead-code" return null (or throw new RuntimeException("should never come here").
You don't have to put it after the try block, you can put it inside the catch.
try {
responseCode = customReportConnection.getResponseCode();
return httpResponseBodyExtractor.extractResponseBodyFrom(customReportConnection);
} catch (IOException e) {
translateIntoRelevantException(responseCode, e);
throw new RuntimeException("should never come here");
}
It's probably prettier to have the helper just return the exception instead of throwing it. Then you can do
throw translateIntoRelevantException(responseCode, e);
Compilation of getCustomReportResponse should not rely on the implementation of translateIntoRelevantException for multiple reasons:
implementation of translateIntoRelevantException might not be available (it could be in a separate class, in a separate library);
otherwise any change in translateIntoRelevantException could break all of the calling methods.
As an alternative you can return an exception and then throw it in a client code:
private IOException translateIntoRelevantException(int responseCode, IOException e) {
if(is5xxResponseCode(responseCode)) {
return new ServerResponseException("Could not generate report - returned response code " + responseCode, e);
}
return new ReportException("GeminiReportException: Unable to parse response from HTTP body when requesting custom Gemini report.", e);
}
then call it like this:
throw translateIntoRelevantException(responseCode, e);
I have a method that throws an Exception, which calls a method which throws an Exception, etc etc. So several methods that "throw Exception" are daisy-chained.
The first method that calls the submethod, puts that submethod in a try-catch block that catches any Exception that gets thrown inside that call. IN THEORY. In practice, no Exception is being caught by that try-catch block. Is there a way to remedy that?
Here is the code:
try {
CSVSingleton.tryToReadBothFiles(FILE1_PATH, FILE2_PATH);
} catch (Exception e) { // THIS BLOCK NEVER GETS ENTERED BY THE PATH O EXECUTION
System.out.println("There was an exception reading from at least one of the files. Exiting.");
System.exit(0);
}
here is the method from the CSVSingleton class:
public static void tryToReadBothFiles(String filePath1, String filePath2) throws Exception {
file1 = new CSVFileForDwellTime1(filePath1);
file2 = new CSVFileForDwellTime2(filePath2);
}
And here is code from the CSVFileForDwellTime1 class:
public CSVFileForDwellTime1(String filePath) throws Exception {
super(filePath);
}
and then here is the code that actually throws an original FileNotFoundException:
public GenericCSVFile(String filePath) throws Exception{
this.filePath = filePath;
try {
fileReader = new FileReader(filePath);
csvReader = new CSVReader(
fileReader);
header = getActualHeaderNames();
} catch (FileNotFoundException e) {
System.out.println("Could not read file with name: " + filePath);
// e.printStackTrace();
}
}
My guess is that the FileNotFoundException in the last method is caught by the catch block and so doesn't "bubble up". But is there a way to force it to bubble up?
Immediate answer:
Your thought is exactly right,
try {
fileReader = new FileReader(filePath);
csvReader = new CSVReader(
fileReader);
header = getActualHeaderNames();
} catch (FileNotFoundException e) {
System.out.println("Could not read file with name: " + filePath);
// e.printStackTrace();
}
This suppresses the exception
Either remove the try-catch block (desired unless you can actually do something with the exception)or re-throw it within the catch block.
Explanation
Generally with checked exceptions like this you have 2 options
Catch the exception and do something to remedy the exception
Throw the exception to the caller
What you have done here falls into the 1st category except that you have not done anything useful in the catch block (printing to console is rarely useful in this case because the exception message itself normally has enough information to see what has gone wrong)
The 2nd category is achieved either by not using a try-catch block and thus adding throws FileNotFoundException to the method signature. Alternatively explicitly throw the exception that you caught using:
catch(FileNotFoundException e)
{
//do something
throw e;
}
however in this case if do something isn't worthwhile you have unnecessarily caught something just to throw it on.
You can think of it like this:
Alice throws a ball to Charlie
Bob intercepts the ball
Bob then looks at the ball and then throws it to Charlie
Bonus Points
When you know the exception that could occur make sure to actually catch or throw that exception and not a parent of that exception.
Take the following method signatures for example:
public String method1() throws Exception
public String method2() throws FileNotFoundException
Here method2 clearly tells the caller what could happen and can help then figure out why the exception is being called (without having to read through the code or experience the error).
Secondly other exceptions can occur and you are potentially catching the wrong exception, take the following example:
try{
fileReader = new FileReader(filePath); //could potentially throw FileNotFoundException
fileReader = null; //woops
csvReader = new CSVReader(fileReader); //throws NullPointerException but the compiler will not know this
//....other stuff....//
}
catch(Exception e){
// the compiler told me that a FileNotFoundException can occur so i assume that is the reason the catch has executed
System.err.println("You have entered an invalid filename");
//doing anything here that would fix a FileNotFoundException is pointless because that is not the exception that occured
}
Use a throw in the catch clause.
} catch (FileNotFoundException e) {
System.out.println("Could not read file with name: " + filePath);
// Continue up, Mr. Exception!
throw e;
}
Alternatively, wrap the exception as appropriate (since an IOException is checked this handy here) - this is called a Chained Exception. Then, depending on what is thrown, the throws Exception can be removed from the method signature.
throw new RuntimeException("Could not read file: " + filePath, e);
If you don't want to catch it, then don't. Alternatively, you can just throw it again with a throw-statement. You can also throw a new Exception of any class you like. You should only catch an Exception at a level where you can react to it properly. As you found out, catching it at that low level is not helpful, so do not catch it there.
You can rethrow the exception once you catch it, for callees further up the stack to handle. You can change what exception it is too if a new type of exception makes more sense at a higher level.
catch (SomeSpecificException e)
{
some code here
throw new AMoreBroadException("I really need the callee to handle this too");
}
Technically you just need to add throw e right after System.out.println("Could not read file with name: " + filePath); and the exception will propagate up to the first method.
However, this would not be a clean way to handle the exception, because in this case all you'd be doing is printing an error message at the cost of changing the location of the original FileNotFoundException. Ideally, when you need to inspect an exception stacktrace, you expect a line of code throwing an exception to be the actual line that really caused the exception.
The throws Exception in the method declaration should be considered part of the contract of the method, i.e. it describes a possible behavior of the method. You should always ask yourself: Does it make sense for a FileNotFoundException to be specified as a possible exceptional behavior for the method/constructor I'm writing? In other words, do I want to make the caller of my method aware of this exception and leave it to the caller to deal with it? If the answer is yes (and in this case I would say it makes sense), then avoid wrapping the code in a try-catch block. If no, then your catch block should be responsible for dealing with the exception itself. In this specific example IMO there is not much you can do in the catch statement, so just remove the try-catch.
As mentioned by others, you should declare the most specific exception in the method signature (throws FileNotFoundException instead of throws Exception).
I did extensive research on exceptions, but I'm still lost.
I'd like to know what is good to do or not.
And I'd also like you to give me your expert opinion on the following example :
public void myprocess(...) {
boolean error = false;
try {
// Step 1
try {
startProcess();
} catch (IOException e) {
log.error("step1", e);
throw new MyProcessException("Step1", e);
}
// Step 2
try {
...
} catch (IOException e) {
log.error("step2", e);
throw new MyProcessException("Step2", e);
} catch (DataAccessException e) {
log.error("step2", e);
throw new MyProcessException("Step2", e);
}
// Step 3
try {
...
} catch (IOException e) {
log.error("step3", e);
throw new MyProcessException("Step3", e);
} catch (ClassNotFoundException e) {
log.error("step3", e);
throw new MyProcessException("Step3", e);
}
// etc.
} catch (MyProcessException mpe) {
error = true;
} finally {
finalizeProcess(error);
if (!error) {
log.info("OK");
} else {
log.info("NOK");
}
}
}
Is it ok to throw a personnal exception (MyProcessException) in each step in order to manage a global try...catch...finally ?
Is it ok to manage each known exception for each step ?
Thank you for your help.
EDIT 1 :
Is it a good practice like this ? log directly in global catch by getting message, and try...catch(Exception) in upper level....
The purpose is to stop if a step fail, and to finalize the process (error or not).
In Controller
public void callProcess() {
try {
myprocess(...);
} catch (Exception e) {
log.error("Unknown error", e);
}
}
In Service
public void myprocess(...) {
boolean error = false;
try {
// Step 1
try {
startProcess();
log.info("ok");
} catch (IOException e) {
throw new MyProcessException("Step1", e);
}
// Step 2
try {
...
} catch (IOException e) {
throw new MyProcessException("Step2", e);
} catch (DataAccessException e) {
throw new MyProcessException("Step2", e);
}
// Step 3
try {
...
} catch (IOException e) {
throw new MyProcessException("Step3", e);
} catch (ClassNotFoundException e) {
throw new MyProcessException("Step3", e);
}
// etc.
} catch (MyProcessException mpe) {
error = true;
log.error(mpe.getMessage(), mpe);
} finally {
finalizeProcess(error);
if (!error) {
log.info("OK");
} else {
log.info("NOK");
}
}
}
Thank you.
Edit 2 :
Is it a real bad practice to catch (Exception e) in lower level and to throws a personnal exception ?
Doesn't exist a generic rule,it depends on your needs.
You can throw a personal exception, and you can manage each known exception.
But pay attention, it is important what you want.
try{
exec1();
exec2(); // if exec1 fails, it is not executed
}catch(){}
try{
exec1();
}catch(){}
try{
exec2(); // if exec1 fails, it is executed
}catch(){}
In your example above it may well be acceptable to throw your own custom exception.
Imagine I have some data access objects (DAO) which come in different flavours (SQL, reading/writing to files etc.). I don't want each DAO to throw exceptions specific to their storage mechansim (SQL-related exceptions etc.). I want them to throw a CouldNotStoreException since that's the level of abstraction that the client is working at. Throwing a SQL-related or a File-related exception would expose the internal workings, and the client isn't particular interested in that. They just want to know if the read/write operation worked.
You can create your custom exception using the originating exception as a cause. That way you don't lose the original info surrounding your problem.
In the above I probably wouldn't handle each exception in each step as you've done. If processing can't continue after an exception I would simply wrap the whole code block in an exception handling block. It improves readability and you don't have to catch an exception and then (later on) check the processing status to see if you can carry on as normal (if you don't do this you're going to generate many exceptions for one original issue and that's not helpful).
I would consider whether multiple catch {} blocks per exception add anything (are you doing something different for each one?). Note that Java 7 allows you to handle multiple exception classes in one catch{} (I realise you're on Java 6 but I note this for completeness).
Finally perhaps you want to think about checked vs unchecked exceptions.
The main point of the exception mechanism is to reduce and group together handling code. You are handling them in the style typical for a language without excptions, like C: every occurrence has a separate handling block.
In most cases the best option is to surround the entire method code with a catch-all:
try {
.... method code ...
}
catch (RuntimeException e) { throw e; }
catch (Exception e) { throw new RuntimeException(e); }
The only times where this is not appropriate is where you want to insert specific handling code, or wrap in a custom exception that will be specifically handled later.
Most exceptions, especially IOExcption in your case, represent nothing else but failure and there will be no handling beyond logging it and returning the application to a safe point, where it can process further requests. If you find yourself repeating the same handling code over and over, it's a signal that you are doing it wrong.
One very important rule: either handle or rethrow; never do both. That is what you are doing in your example: both logging and rethrowing. Most likely the rethrown exception will be caught further up in the call stack and logged again. Reading through the resulting log files is a nightmare, but unfortunately quite a familiar one.
int step = 0;
try
{
step = 1;
...
step = 2;
...
step = 3;
...
}
catch (Exception1 e)
{
log ("Exception1 at step " + step);
throw new MyException1 ("Step: " + step, e);
}
catch (Exception2 e)
{
log ("Exception2 at step " + step);
throw new MyException2 ("Step: " + step, e);
}
...
I'd say it depends on your needs...
If step2 can execute correctly even if step1 failed, you can try/catch step1 separately.
Otherwise, I would group all steps in one try/catch block and made sure that the individual steps produce a log message when they fail.
That way you don't litter your code and still know what went wrong
It's ok to catch each known exception, so you can log what exception occure, and why it did.
Here some links to exception handling patterns/anti-patterns:
Do:
http://www.javaworld.com/jw-07-1998/jw-07-techniques.html
Don't:
http://today.java.net/article/2006/04/04/exception-handling-antipatterns
http://nekulturniy.com/Writings/RebelWithoutAClause/Rebel_without_a_clause.html
About creating your own exceptions, it's certainly useful if you're creating an API, a framework or another piece of reusable code, but in a regular application, it's more debatable and I personally would suggest to stick to existing exceptions.
I have something similar to this.
void func() {
try {
//socket disconnects in middle of ..parsing packet..
} catch(Exception ex) {
if(!ex.getMessage().toString().equals("timeout") || !ex.getMessage().toString().equals("Connection reset")) {
debug("Exception (run): " + ex.getMessage());
ex.printStackTrace();
}
}
Why is it that when I get a connection reset exception or a timeout exception, it still goes inside the condition. I tried without toString and with no luck.
You shouldn't catch all exceptions and then test the error message of the exception. Instead only catch those exceptions that you intend to handle - for example SocketTimeoutException.
catch (SocketTimeoutException ex)
{
// Do something...
}
With your current code you may be catching some other type of exception that you weren't expecting. Currently you will just ignore this exception, not even logging it. This can make it very difficult to debug what is going on. If you have an exception that you can't handle you should either rethrow it or log it.
I want to catch all exceptions
If you really want to do that then you can write your code as follows:
catch (SocketTimeoutException ex)
{
// Do something specific for SocketTimeoutException.
}
catch (Exception ex)
{
// Do something for all other types of exception.
}
Regarding your specific error, you have written:
!a.equals(b) || !a.equals(c)
This expression always evaluates to true. What you meant was:
!a.equals(b) && !a.equals(c)
Or equivalently:
!(a.equals(b) || a.equals(c))
Note that by rewriting your code as I suggested above you completely avoid having to write this complicated boolean expression.
It's really not safe to rely on exceptions messages to know what is the cause of your exception.
In your case you can try to catch more specific exceptions, such as SocketTimeoutException and the classic IOException :
void func() {
try {
//socket disconnects in middle of ..parsing packet..
} catch(SocketTimeoutException ex) {
//In case of Time out
} catch(IOException ex){
//For other IOExceptions
}
}
Sources :
[Socket.connect()][3]
Even if you prefer to seek informations in exceptions messages, you shouldn't check if the message simply is equal to "timeout" but if the message contains "timeout"
[3]: http://download-llnw.oracle.com/javase/6/docs/api/java/net/Socket.html#connect(java.net.SocketAddress, int)