i'm struggling to figure out how to use the Closer utility from the guava library. Please see the code below.
IOException
on both object initialization and close()
. Therefore, the code in the finally and rethrow blocks is underlined. Throwable
instead of other exception types and do i have to rethrow the errors (i would prefer to log those at the spot)`
int getDocumentsCount() {
Closer closer = Closer.create();
try {
IndexWriter iwriter = closer.register(openIndexWriter());
return iwriter.numDocs();
} catch (Throwable e) {
logger.error(e, e);
return -1;
} finally {
closer.close();
}
}
IndexWriter openIndexWriter() throws IOException {
return new IndexWriter(directory, analyzer, false,
IndexWriter.MaxFieldLength.UNLIMITED);
}
`
Thanks a lot
(stuck with Java 6)
From Guava's own explanation, you have to use Throwable
, yes.
Here's their example snippet:
public void foo() throws IOException {
Closer closer = Closer.create();
try {
InputStream in = closer.register(openInputStream());
OutputStream out = closer.register(openOutputStream());
// do stuff with in and out
} catch (Throwable e) { // must catch Throwable
throw closer.rethrow(e);
} finally {
closer.close();
}
}
Note that they catch Throwable
and rethrow it directly from the Closer
instance.
As to why it is Throwable
and not, let's say IOException
or RuntimeException
, it's because the Closer
must know that an error occurred so that it can close the resources properly. All is only a matter of doing things proper. So it can work if you don't do it properly, but it's not guaranteed.
Not that if your method can throw MyOwnCheckedException
, for instance, you have to declare them:
} catch (Throwable t) {
throw closer.rethrow(e, MyOwnCheckedException.class);
} finally {
closer.close();
}
Java 7 example, for comparison:
public void foo() throws IOException {
try (InputStream in = openInputStream();
OutputStream out = openOutputStream();
// do stuff with in and out
}
}
If you compare the Closer
example with the Java 7 example, you can see that I still have to declare the IOException
in the method signature.
For your case, this is what you have to do:
int getDocumentsCount() {
try {
Closer closer = Closer.create();
try {
IndexWriter iwriter = closer.register(openIndexWriter());
return iwriter.numDocs();
} catch (Throwable e) {
closer.rethrow(e);
} finally {
closer.close();
}
} catch (IOException e) {
logger.error(e, e);
return -1;
}
}
To avoid try-pyramids, I'd do the following:
int getDocumentsCount() {
try {
return doGetDocumentsCount();
} catch (IOException e) {
logger.error(e, e);
return -1;
}
}
int doGetDocumentsCount() throws IOException {
Closer closer = Closer.create();
try {
IndexWriter iwriter = closer.register(openIndexWriter());
return iwriter.numDocs();
} catch (Throwable e) {
closer.rethrow(e);
} finally {
closer.close();
}
}