I have the following code which is java 1.7 compatible, however, I need it to be compatible with java 1.6. currently I get the following error for this code: try-with-resources is not supported in -source 1.6
the code looks like this:
try (QueryExecution qexec = QueryExecutionFactory.create(query, input.getModel())) {
// Some other code
while (results.hasNext()) {
// do something
}
return something;
}
what do I need to change in order to make it work with java 1.6?
The real answer:
The real answer here is use Java 7 or 8. Java 6 is very old. Java 7 came out four years ago; Java 8, almost a year and a half.
Only keep reading if there's a very, very good reason you can't do that. :-)
TL;DR
That specific example can be simply:
QueryExecution qexec = QueryExecutionFactory.create(query, input.getModel());
Throwable thrown = null;
try {
// Some other code
while (results.hasNext()) {
// do something
}
return something;
}
catch (Throwable t) {
thrown = t; // Remember we're handling an exception
throw t;
}
finally {
try {
qexec.close();
}
catch (Throwable t) {
if (thrown == null) {
// Not handling an exception, we can rethrow
throw t;
}
else {
// Log it or something, you can't allow it to
// throw because there's *already* an exception
// being thrown and you'll hide it. This is why
// Java 7 added Throwable#addSuppressed.
}
}
}
But that's because it's a very simple case. If there were any other resources that needed closing (results
, for instance?) or you were handling some exceptions in the code itself, it would be more complicated.
The more general form is;
SomeResource r1 = null;
Throwable thrown = null;
try {
r1 = new SomeResource();
SomeOtherResource r2 = null;
try {
r2 = new SomeOtherResource();
// use them
return something;
}
catch (Throwable t) {
thrown = t; // Remember we're handling an exception
throw t;
}
finally {
try {
r2.close();
}
catch (Throwable t) {
if (thrown == null) {
// Not handling an exception, we can rethrow
throw t;
}
else {
// Log it or something, you can't allow it to
// throw because there's *already* an exception
// being thrown and you'll hide it. This is why
// Java 7 added Throwable#addSuppressed.
}
}
}
}
catch (Throwable t) {
thrown = t; // Remember we're handling an exception
throw t;
}
finally {
try {
r1.close();
}
catch (Throwable t) {
if (thrown == null) {
// Not handling an exception, we can rethrow
throw t;
}
else {
// Log it or something
}
}
}
You'll probably want some utility library functions to help with this, it's a lot of boilerplate otherwise. I used to have things that did "silent" closes for the case where I knew an exception was already happening.
Details: This is covered by §14.20.3 of the JLS and its subsections:
A simple try-with-resources
:
try ({VariableModifier} R Identifier = Expression ...)
Block
translates to:
{
final {VariableModifierNoFinal} R Identifier = Expression;
Throwable #primaryExc = null;
try ResourceSpecification_tail
Block
catch (Throwable #t) {
#primaryExc = #t;
throw #t;
} finally {
if (Identifier != null) {
if (#primaryExc != null) {
try {
Identifier.close();
} catch (Throwable #suppressedExc) {
#primaryExc.addSuppressed(#suppressedExc);
}
} else {
Identifier.close();
}
}
}
}
You'll have to remove the addSuppressed
part as Throwable
didn't have that in JDK6.
An extended try-with-resources
:
try ResourceSpecification
Block
[Catches]
[Finally]
translates to:
try {
try ResourceSpecification
Block
}
[Catches]
[Finally]
...where that
try ResourceSpecification
Block
...is replaced by the big thing that the simple try-with-resources
turns into, so the whole thing turns into:
try {
{
final {VariableModifierNoFinal} R Identifier = Expression;
Throwable #primaryExc = null;
try ResourceSpecification_tail
Block
catch (Throwable #t) {
#primaryExc = #t;
throw #t;
} finally {
if (Identifier != null) {
if (#primaryExc != null) {
try {
Identifier.close();
} catch (Throwable #suppressedExc) {
#primaryExc.addSuppressed(#suppressedExc);
}
} else {
Identifier.close();
}
}
}
}
}
[Catches]
[Finally]
...which is why we love the try-with-resources
statement so much.