When using a custom Iterable/Iterator class with Database.Batchable, if the Iterator throws an exception it seems impossible to catch the exception.
Is there any way to catch the exceptions thrown in the following example code?
public class BatchableWithTryCatch implements Database.Batchable<String> {
public Iterable<String> start(Database.BatchableContext bc) {
System.debug(
'youll see this message in the same log with the exception'
);
try {
return new ErrorIterator();
} catch (Exception e) {
System.debug(
'this doesnt catch anything because there is no exception ' +
'thrown by the constructor'
);
return null;
}
}
public void execute(Database.BatchableContext bc, List<String> scope) {
System.debug(
'execute() doesnt get called because of exception in hasNext()'
);
}
public void finish(Database.BatchableContext bc) {
System.debug(
'finish() doesnt get called because of exception in hasNext()'
);
}
public class ErrorIterator implements Iterable<String>, Iterator<String> {
public Iterator<String> iterator() {
return this;
}
public Boolean hasNext() {
throw new StringException(
'Cant catch exceptions from hasNext()'
);
return true;
}
public String next() {
throw new StringException(
'Cant catch exceptions from next()'
);
return 'foo';
}
}
}
This is what the log looks like for the first 'Batch Apex' execution:
36.0 APEX_CODE,DEBUG;APEX_PROFILING,NONE;CALLOUT,NONE;DB,NONE;SYSTEM,NONE;VALIDATION,NONE;VISUALFORCE,NONE;WORKFLOW,NONE
18:29:46.0 (436218)|EXECUTION_STARTED
18:29:46.0 (475757)|CODE_UNIT_STARTED|[EXTERNAL]|01p36000006TMzQ|BatchableWithTryCatch
18:29:46.0 (17094809)|USER_DEBUG|[3]|DEBUG|youll see this message in the same log with the exception
18:29:46.0 (18531282)|FATAL_ERROR|System.StringException: Cant catch exceptions from hasNext()
Class.BatchableWithTryCatch.ErrorIterator.hasNext: line 36, column 1
It does make sense that the exceptions thrown by the Iterator class are not caught by the try/catch block in the start() method, because those methods are called by Salesforce after calling the start() method in order to set up the scope for the execute() method.
However, it is a major disadvantage not being able to catch these exceptions, so I am hoping that I am just unaware of some kind of existing error handling mechanism!
How can I catch exceptions thrown from a custom Iterable/Iterator class when used with Database.Batchable?