How to deal with multiple exceptions thrown in .close()? - java

This is Java 7. I have a class which maintains a list of FTP clients (I call them agents) in a class which implements Closeable.
On .close() I disconnect them, but of course each of them can throw an exception. Right now the code is as follows:
#Override
public void close()
throws IOException
{
IOException toThrow = null;
final List<FtpAgent> list = new ArrayList<>();
agents.drainTo(list); // <-- agents is a BlockingQueue
for (final FtpAgent agent: list)
try {
agent.disconnect();
} catch (IOException e) {
if (toThrow == null)
toThrow = e;
}
if (toThrow != null)
throw toThrow;
}
Apart from the lack of logging of each individual exception, is this the correct way to deal with this?

Related

How to close a com.google.api.client.http.HttpResponse object properly

I am trying to close a com.google.api.client.http.HttpResponse object, but I get the Eclipse error
Unhandled exception type IOException
on the line response.disconnect();
Here's a code example:
HttpRequest request = null;
HttpResponse response = null;
try {
request = this.buildJsonApiRequest(apiUrl);
response = this.execute(request);
return response.parseAs(MyClass.class);
} catch (final IOException e) {
throw new DaoException(e);
} finally {
if (response != null) {
response.disconnect();
}
}
The code works without the finally block, but I am concerned about many response objects being opened and not closed. What is the proper way to do this?
You need to put the disconnect call within a try-catch block because according to Google API documentation that method could throw an IOException:
public void disconnect() throws IOException
Follow this link to learn more about it:
https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/http/HttpResponse#disconnect()
This is in response to Eleazar Enrique answer that the disconnect needs to be within a try block. This is an example of how to possibly write it more elegantly and make it reusable.
You could create a handler class that implements autoCloseable then use try-with-resource
public class HttpResponseHandler implements AutoCloseable {
private HttpResponse response;
public HttpResponseHandler(HttpResponse response) {
this.response = response;
}
}
public <T> T parseAs(Class<T> clazz) throws IOException {
return response.parseAs(clazz);
}
#Override
public void close() {
if (response != null) {
try {
response.disconnect();
} catch (IOException ex) {}
}
}
then in your code it would be something like this
HttpRequest request = this.buildJsonApiRequest(apiUrl);
try (HttpResponseHandler handler = new HttpResponseHandler(this.execute(request)) {
return handler.parseAs(MyClass.class);
} catch (final IOException e) {
throw new DaoException(e);
}
The AutoCloseable will close the connection for you, so you wouldn't have to handle it in the finally block.

Same exception type with different error message

Ive two method that throw the same exception throws IOException
the problem is that each method throw it from different reason, I wrap the methods
in the main with try catch, what is the recommended way to solve it ?
I need different message for each exception with the same type..
public static void main(String[] args) {
try{
….
readFile(path);
convert(file)
} catch (IOException e) {
…..
}
private static String readFile(String path) throws IOException {
//Here files requires IOException - Reason here cannot Read file
String lineSeparator = System.getProperty("line.separator");
List<String> lines = Files.readAllLines(Paths.get(path));
}
private static String convert(String file) throws IOException {
//Here reader requires also ioException- Reason here cannot parse file
ObjectMapper reader = new ObjectMapper(new YAMLFactory());
Object obj = reader.readValue(file, Object.class);
}
There are several ways you could approach this. One way, perhaps the heaviest in terms of new code you would need to write, would be throw a custom exception from each of your helper methods. Then you could catch each specific exception in a separate block.
But what I might recommend here is that you simply wrap each of the two calls to your helper methods in separate try-catch blocks:
try {
readFile(path);
} catch (IOException e) {
// handle first exception here
}
// more code
try {
convert(file)
} catch (IOException e) {
// handle second exception here
}
This is fairly clean and doesn't require a lot of refactoring. If you keep encountering this problem, then maybe consider creating custom exceptions for your application. If you have a look at many Java libraries, you will see that they often use their own custom exceptions.
If you wanted to go the route of using a custom exception, you could define one, e.g.
public class FileReadIOException extends Exception {
public FileReadIOException(String message) {
super(message);
}
}
and then use it:
private static String readFile(String path) throws FileReadIOException {
try {
String lineSeparator = System.getProperty("line.separator");
List<String> lines = Files.readAllLines(Paths.get(path));
}
catch (Exception e) {
throw new FileReadIOException(e.getMessage());
}
}
try {
readFile(path);
// more code
convert(file)
} catch (FileReadIOException e) {
// handle first exception here
} catch (SomeOtherException e) {
// handle second exception here
}
The above code showing custom exception is a bit contrived, because the reality is that all of your code is throwing IOException. Creating custom exceptions in your case does not add much value, because they are already (rightfully) throwing an IOException. I'm not sure that it doesn't make sense to handle just one type of exception. More typically, if you were working on a large enterprise application, you would use custom exceptions to handle situations which go wrong in your own custom code.
My way is usually to create your own exception and throw it like that
public class Snippet {
public static void main(String[] args) {
try {
String path = "";
readFile(path);
String file = "";
convert(file);
} catch (MyException e) {
// do whatever
}
}
private static String readFile(String path) throws MyException {
try {
String lineSeparator = System.getProperty("line.separator");
List<String> lines = Files.readAllLines(Paths.get(path));
} catch (Exception e) {
throw new MyException("Custom 'readFile' message", e);
}
}
private static String convert(String file) throws MyException {
try {
ObjectMapper reader = new ObjectMapper(new YAMLFactory());
Object obj = reader.readValue(file, Object.class);
} catch (Exception e) {
throw new MyException("Custom 'convert' message", e);
}
}
}
class MyException extends Exception {
private static final long serialVersionUID = -3166824380774329449L;
public MyException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
}
Tim's way is valid too.
#OP The best person to solve this would be you yourself.
There are quite easily multiple ways to solve that. Check which one suits you more properly.
One of the solution as per me is below. This is based on the reason IOException is superclass to many other exceptions. IOException documentation
try {
readFile(path);
} catch ( FileNotFoundException e) {
// handle first exception here
} catch ( EOFException e) {
// handle 2nd exception here
}
For the above to work you would need to know which type of IOException is being thrown.
Another solution is check individual exception messages when you know what are expected messages you may receive.
try {
readFile(path);
} catch ( IOException e) {
if(e. getMessage().contains("TXT 1...") {
//Case handle #1
} else if(e. getMessage().contains("TXT 2...") {
//Case handle #2
}
}
The best way to handle exception is not to have them. When exception is thrown, it indicates that natural lifecycle of your application has been interrupted for one reason or another. Most exceptions are self-explanatory and provide you with precise explanation of what happend, therefore creating new exceptions and re-mapping those thrown is almost always counterproductive and may result in more confusion than usefulness(especial if you work in a team).
Furthermore exceptions doesn't need to be terminal, in most cases, a scenario can be devised to retry/prompt different input etc. to ensure that lifecycle is not interrupted. Killing an application on exception can create more problems in some cases (e.g: not closing files properly, hence losing processed data).
Now to your actual problem. If you have two or more components, that throws unrelated exceptions(name is not a relation in this case), it is best not to have them in the same try/catch structure as less workaround will be necesary to scrap that one part, instead of the whole thing which can still exit on its own, or doesn't even need to be initiated.
Here is my 5 cents
public static void main(String[] args) throws Exception {
String path = "path";
String path2 = "path2";
try{
readFile(path);
} catch (IOException e) {
throw new Exception("read file exception", e);
}
try{
convert(path2);
} catch (IOException e) {
throw new Exception("convert exception", e);
}
}
private static String readFile(String path) throws IOException {
//Here files requires IOException - Reason here cannot Read file
String lineSeparator = System.getProperty("line.separator");
List<String> lines = Files.readAllLines(Paths.get(path));
}
private static String convert(String file) throws IOException {
//Here reader requires also ioException- Reason here cannot parse file
ObjectMapper reader = new ObjectMapper(new YAMLFactory());
Object obj = reader.readValue(file, Object.class);
}

How to return a 500 status code if there is an IOException while reading

Say I have the following snippet
public boolean checkListing() {
try {
// open the users.txt file
BufferedReader br = new BufferedReader(new FileReader("users.txt"));
String line = null;
while ((line = br.readLine()) != null) {
String[] values = line.split(" ");
// only interested for duplicate usernames
if (username.equals(values[0])) {
return true;
}
}
br.close();
return false;
} catch (IOException e) {
e.printStackTrace();
// what to do here
}
}
How should I handle the error if an exception occurs?
I want to know that it happened and return a 500 code back to the user.
Should I throw and exception and catch it in the other class?
Is there a more elegant way to get feedback on it?
You can return an instance of this class:
public class Result {
private boolean errorOccurs;
private boolean isValid;
private Exception exception;
public Result(boolean isValid){
this(isValid, false, null);
}
public Result(boolean isValid, boolean errorOccurs, Exception exception){
this.isValid = isValid;
this.errorOccurs = errorOccurs;
this.exception = exception;
}
public boolean isValid(){
return isValid;
}
public boolean errorOccurs(){
return errorOccurs;
}
public Exception getException(){
return exception;
}
}
In your case:
public Result checkListing() {
try {
// open the users.txt file
BufferedReader br = new BufferedReader(new FileReader("users.txt"));
String line = null;
while ((line = br.readLine()) != null) {
String[] values = line.split(" ");
// only interested for duplicate usernames
if (username.equals(values[0])) {
return new Result(true);
}
}
br.close();
return new Result(false);
} catch (IOException e) {
e.printStackTrace();
return new Result(false, true, e);
}
}
And the short form of the Result class:)
public class Result {
public boolean errorOccurs;
public boolean isValid;
public Exception exception;
}
In this case, IOException can be thrown from readLine or close.
This exception indicates that exceptional situation happened, for example the stream's source is no longer available. Your program can be recovered, or by rereading the source or reporting this problem to the user.
It's up to you to decide what to do, depending on your logic, there's no preferred way of doing that here.
Note that you should close br in a finally block.
The two most common approaches I have seen are, as noted by Sasha Salauyou, a rethrow (potentially wrapped) or a separate object providing more information.
The fundamental problem that you're trying to deal with here is that you have a method that you want to have returning more than two values with a return type that can only express two. So you either have to return a type that supports all the possible return values you need or you have to find alternate return paths (like exceptions).
In my own code, I would tend to favor a rethrow here. Writing a dedicated return object becomes difficult to maintain long term with IO because there are so many diverse ways that things can fail. However, I would diverge from the route suggested (an exception holding the original exception as cause) simply because there is usually no strong reason for the wrapping. Just declare your checkListing method to throw IOException, log your message or stacktrace in the catch block, and then throw the original exception.
Better way is to throw wrapping exception:
try (FileReader fr = new FileReader("users.txt")) {
try (BufferedReader br = new BufferedReader(fr)) {
// ... do your work
} catch (IOException e) {
throw new RuntimeException(e);
}
} catch (IOException e1) {
throw new RuntimeException(e1);
}
Notice, that here I'm opening resources in try statements thus making them to be closed automatically at the end of execution, not dependent on execution result.

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.

How to close std-streams from java.lang.Process appropriate?

This question is about java.lang.Process and its handling of stdin, stdout and stderr.
We have a class in our project that is an extension to org.apache.commons.io.IOUtils. There we have a quiet new method for closing the std-streams of a Process-Object appropriate? Or is it not appropriate?
/**
* Method closes all underlying streams from the given Process object.
* If Exit-Code is not equal to 0 then Process will be destroyed after
* closing the streams.
*
* It is guaranteed that everything possible is done to release resources
* even when Throwables are thrown in between.
*
* In case of occurances of multiple Throwables then the first occured
* Throwable will be thrown as Error, RuntimeException or (masked) IOException.
*
* The method is null-safe.
*/
public static void close(#Nullable Process process) throws IOException {
if(process == null) {
return;
}
Throwable t = null;
try {
close(process.getOutputStream());
}
catch(Throwable e) {
t = e;
}
try{
close(process.getInputStream());
}
catch(Throwable e) {
t = (t == null) ? e : t;
}
try{
close(process.getErrorStream());
}
catch (Throwable e) {
t = (t == null) ? e : t;
}
try{
try {
if(process.waitFor() != 0){
process.destroy();
}
}
catch(InterruptedException e) {
t = (t == null) ? e : t;
process.destroy();
}
}
catch (Throwable e) {
t = (t == null) ? e : t;
}
if(t != null) {
if(t instanceof Error) {
throw (Error) t;
}
if(t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw t instanceof IOException ? (IOException) t : new IOException(t);
}
}
public static void closeQuietly(#Nullable Logger log, #Nullable Process process) {
try {
close(process);
}
catch (Exception e) {
//log if Logger provided, otherwise discard
logError(log, "Fehler beim Schließen des Process-Objekts (inkl. underlying streams)!", e);
}
}
public static void close(#Nullable Closeable closeable) throws IOException {
if(closeable != null) {
closeable.close();
}
}
Methods like these are basically used in finally-blocks.
What I really want to know is if I am safe with this implementation? Considering things like: Does a process object always return the same stdin, stdout and stderr streams during its lifetime? Or may I miss closing streams previously returned by process' getInputStream(), getOutputStream() and getErrorStream() methods?
There is a related question on StackOverflow.com: java: closing subprocess std streams?
Edit
As pointed out by me and others here:
InputStreams have to be totally consumed. When not done then the subprocess may not terminate, because there is outstanding data in its output streams.
All three std-streams have to be closed. Regardless if used before or not.
When the subprocess terminates normally everything should be fine. When not then it have to be terminated forcibly.
When an exit code is returned by subprocess then we do not need to destroy() it. It has terminated. (Even when not necessarily terminated normally with Exit Code 0, but it terminated.)
We need to monitor waitFor() and interrupt when timeout exceeds to give process a chance to terminate normally but killing it when it hangs.
Unanswered parts:
Consider Pros and Cons of consuming the InputStreams in parallel. Or must they be consumed in particular order?
An attempt at simplifying your code:
public static void close(#Nullable Process process) throws IOException
{
if(process == null) { return; }
try
{
close(process.getOutputStream());
close(process.getInputStream());
close(process.getErrorStream());
if(process.waitFor() != 0)
{
process.destroy();
}
}
catch(InterruptedException e)
{
process.destroy();
}
catch (RuntimeException e)
{
throw (e instanceof IOException) ? e : new IOException(e);
}
}
By catching Throwable I assume you wish to catch all unchecked exceptions. That is either a derivative of RuntimeException or Error. However Error should never be catched, so I have replaced Throwable with RuntimeException.
(It is still not a good idea to catch all RuntimeExceptions.)
As the question you linked to states, it is better to read and discard the output and error streams. If you are using apache commons io, something like,
new Thread(new Runnable() {public void run() {IOUtils.copy(process.getInputStream(), new NullOutputStream());}}).start();
new Thread(new Runnable() {public void run() {IOUtils.copy(process.getErrorStream(), new NullOutputStream());}}).start();
You want to read and discard stdout and stderr in a separate thread to avoid problems such as the process blocking when it writes enough info to stderr or stdout to fill the buffer.
If you are worried about having two many threads, see this question
I don't think you need to worry about catching IOExceptions when copying stdout, stdin to NullOutputStream, since if there is an IOException reading from the process stdout/stdin, it is probably due to the process being dead itself, and writing to NullOutputStream will never throw an exception.
You don't need to check the return status of waitFor().
Do you want to wait for the process to complete? If so, you can do,
while(true) {
try
{
process.waitFor();
break;
} catch(InterruptedException e) {
//ignore, spurious interrupted exceptions can occur
}
}
Looking at the link you provided you do need to close the streams when the process is complete, but destroy will do that for you.
So in the end, the method becomes,
public void close(Process process) {
if(process == null) return;
new Thread(new Runnable() {public void run() {IOUtils.copy(process.getInputStream(), new NullOutputStream());}}).start();
new Thread(new Runnable() {public void run() {IOUtils.copy(process.getErrorStream(), new NullOutputStream());}}).start();
while(true) {
try
{
process.waitFor();
//this will close stdin, stdout and stderr for the process
process.destroy();
break;
} catch(InterruptedException e) {
//ignore, spurious interrupted exceptions can occur
}
}
}
Just to let you know what I have currently in our codebase:
public static void close(#Nullable Process process) throws IOException {
if (process == null) {
return;
}
Throwable t = null;
try {
flushQuietly(process.getOutputStream());
}
catch (Throwable e) {
t = mostImportantThrowable(t, e);
}
try {
close(process.getOutputStream());
}
catch (Throwable e) {
t = mostImportantThrowable(t, e);
}
try {
skipAllQuietly(null, TIMEOUT, process.getInputStream());
}
catch (Throwable e) {
t = mostImportantThrowable(t, e);
}
try {
close(process.getInputStream());
}
catch (Throwable e) {
t = mostImportantThrowable(t, e);
}
try {
skipAllQuietly(null, TIMEOUT, process.getErrorStream());
}
catch (Throwable e) {
t = mostImportantThrowable(t, e);
}
try {
close(process.getErrorStream());
}
catch (Throwable e) {
t = mostImportantThrowable(t, e);
}
try {
try {
Thread monitor = ThreadMonitor.start(TIMEOUT);
process.waitFor();
ThreadMonitor.stop(monitor);
}
catch (InterruptedException e) {
t = mostImportantThrowable(t, e);
process.destroy();
}
}
catch (Throwable e) {
t = mostImportantThrowable(t, e);
}
if (t != null) {
if (t instanceof Error) {
throw (Error) t;
}
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw t instanceof IOException ? (IOException) t : new IOException(t);
}
}
skipAllQuietly(...) consumes complete InputStreams. It uses internally an implementation similar to org.apache.commons.io.ThreadMonitor to interrupt consumption if a given timeout exceeded.
mostImportantThrowable(...) decides over what Throwable should be returned. Errors over everything. First occured higher prio than later occured. Nothing very important here since these Throwable are most probably discarded anyway later. We want to go on working here and we can only throw one, so we have to decide what we throw at the end, if ever.
close(...) are null-safe implementations to close stuff but throwing Exception when something went wrong.

Categories