I have a method being called by another class that performs a number of steps on a collection of objects. Specifically, I'm copying a list of files from their original locations to a new folder. After the files have been copied, I update a database with additional data related to the group of files. It looks something like this:
public void copyFilesAndStore(File[] files, DataObject additionalData){
for (File f in files){
copyFileToDestination(f);
}
updateDatabase(additionalData);
}
The issue is, that the copyFileToDestination(File f) method can throw various IOExceptions if there's an issue with one of the files, but even if there is an exception on one of the files, I'd like to continue copying the rest of the files, and make the call to update the database. So I can do something like this:
public void copyFilesAndStore(File[] files, DataObject additionalData){
for (File f in files){
try {
copyFileToDestination(f);
} catch (IOException ex) {
log(ex);
}
}
updateDatabase(additionalData);
}
However, the class calling copyFilesAndStore() needs to know if the copy was successful or not, but if I catch all the exceptions inside this method, it won't know about them. Does it make sense at all to do something like below, or am I missing a better solution?
public void copyFilesAndStore(File[] files, DataObject additionalData){
IOException encounteredException = null;
for (File f in files){
try {
copyFileToDestination(f);
} catch (IOException ex) {
log(ex);
encounteredException = ex;
}
}
updateDatabase(additionalData);
if (encounteredException != null)
throw(encounteredException);
}
It is perfectly safe to store an exception (excluding some corner cases, like OutOfMemoryException and the like), but if you want to store possible exceptions in a loop, it is usually a good idea to store them all:
public void copyFilesAndStore(File[] files, DataObject additionalData){
List<IOException> encounteredExceptions = new LinkedList<IOException>();
for (File f in files){
try {
copyFileToDestination(f);
} catch (IOException ex) {
log(ex);
encounteredExceptions.add(ex);
}
}
updateDatabase(additionalData);
if (!encounteredExceptions.empty()) {
throw(new DelayedException(encounteredExceptions));
}
}
where DelayedException
is your own custom exception that can store a list of other exceptions (kind of like the caused-by chain in a regular exception)