ahoffer ahoffer - 2 years ago 191
Java Question

Exception handling with Consumer functions in Java 8

This code gives me a compile error on the line

processBatch(batch, this::backupMetacard);
The process batch method wraps the consumer in a try/catch block, but Java will not compile the call.

private synchronized void drain() {

for (List<Metacard> batch : Lists.partition(metacards, BATCH_SIZE)) {
getExecutor().submit(() -> {

processBatch(batch, this::backupMetacard);
});
}
metacards.clear();
}

void processBatch(List<Metacard> metacards, Consumer<Metacard> operation) {

List<String> errors = new ArrayList<>();
for (Metacard metacard : metacards) {
try {
operation.accept(metacard);
} catch (IOException e) {
errors.add(metacard.getId());
}
}

if (!errors.isEmpty()) {
LOGGER.info("Plugin processing failed. This is allowable. Skipping to next plugin.",
pluginExceptionWith(errors));
}
}

private void backupMetacard(Metacard metacard) throws IOException {...}

Answer Source

The problem is that in the following snippet, the method backupMetacard declares to throw the checked IOException.

getExecutor().submit(() -> {
    processBatch(batch, this::backupMetacard);
                        ^^^^^^^^^^^^^^^^^^^^ // <-- this throws a checked exception
});

As such, it does not comply anymore with the contract of the functional method of Consumer, which is apply and doesn't declare to throw checked exceptions.

Wrap this into a try-catch, where you can throw an unchecked exception instead UncheckedIOException:

getExecutor().submit(() -> {
    processBatch(batch, metacard -> {
        try {
            backupMetacard(metacard);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    });
});
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download