1
\$\begingroup\$

I have a program which basically manages batch runs of some underlying Fortran programs, and at the end, I want to move all the related files into a different directory.

At the moment, there is something along the lines of this:

private void finalClean() throws Exception{
  Script.move(file1, calcDir);
  Script.move(file2, calcDir);
  Script.move(file3, calcDir);
  ...
}

Now, the nature of these jobs is that they do not always run to completion, but the finalClean method is in the finally clause, so it is always run. The problem is, that depending on where the run fails, not all of the files are present, which means that if one of those files isn't present, it throws an exception, causing none of the remaining files to be moved. The files are not always created in the same order either, which means I can't just order them as they would be created and then not have to worry about remaining files, as they're not created.

My current solution to this is:

ArrayList<String> files_to_move = new ArrayList<String>();
files_to_move.add("file_name_1");
files_to_move.add("file_name_1");
files_to_move.add("file_name_1");
...    

for(String file_name : files_to_move){
  try {
    Script.move(QNFiles.getProject(), file_name, calcDir);
  } catch (Exception ex) {
    Logger...blah.blah.blah;
  }
}

But I'm not overly pleased with how it looks. Is there a way to have a some kind of construct around the whole loop which just grabs all the exceptions, ignores them, and then throws an exception containing info on all of the others afterwards? Maybe a way I can temporarily ignore a subset of exceptions and deal with them all later, without having the try catch in the loop?

I don't use Java as much as Python anymore, so I suspect my wanting to neaten this up is a symptom of becoming used to that, but still: is there a better way to do this?

\$\endgroup\$
1
\$\begingroup\$

If what worries you is readability use a function that takes care of the exception:

boolean error = false;
for(String file_name : files_to_move){
    error |= moveTheFile(...);
}
if (error) {
    // throw your exception here
}

The function would be something like:

private boolean moveTheFile(...) {
    try {
         Script.move(QNFiles.getProject(), file_name, calcDir);
    } catch (Exception ex) {
        Logger...blah.blah.blah;
        return true;
    }
    return false;
}
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

From The Java Language Specification (section 11.3)

When an exception is thrown (§14.18), control is transferred from the code that caused the exception to the nearest dynamically enclosing catch clause, if any, of a try statement (§14.20) that can handle the exception

So, there is no way to surround your for loop with a unique try-catch ignoring inner exceptions because when the first exception occurs the control will be transferred to the catch block.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

As antonio said, there is no way to achieve it without a try-catch. You need that try-catch in the loop so that another loop iteration is possible. If you want to throw an exception containing information about all failures, you can use "suppressed exceptions":

List<Exception> exceptions = new ArrayList<>();

for(String file_name : files_to_move){
    try {
        Script.move(QNFiles.getProject(), file_name, calcDir);
    } catch (Exception ex) {
        exceptions.add(ex);
    }
}

if (!exceptions.isEmpty()) {
    RuntimeException exception = new RuntimeException("Couldn't move all files");
    for (Exception suppressedException : exceptions) {
        exception.addSuppressed(suppressedException);
    }
    throw exception;
}

You will see in the console RuntimeException (consider creating your own with more meaningful meaning) and all suppressed exceptions.

However, should this method really thrown an exception? Exceptions are used in exceptional circumstances to indicate that some part of program failed. However in your case some scripts failing is normal. If you need to display what files were not moved consider handling this via return statement, e.g. return a list of files that have been moved or files that didn't exist.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ The whole "Exceptions are used in exceptional circumstances" blarb is exactly my thinking. I can't change the underlying "script.move" code, as it's used all over the place and in some places used to determine program flow :/. I guess i could create an alternative method which does not through the exception and use that instead. \$\endgroup\$ – will Feb 27 '15 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.