Can Java exception safety be made less ugly? - java

Given the following code: We need to lock the model, then start a transaction (which could throw an exception so we have to make sure the lock is released), then do something kind of like getting a database connection (which could throw an exception), then do some stuff which could throw an exception requiring the transaction to be reverted. This is Java 6 so we don't have Java 7 good stuff available.
SomeClass someMethod()
throws SomeException {
acquireWriteLock();
try {
startTransaction();
try {
DBConnection d = openDBConnection();
try {
doStuff(d);
commitTransaction();
} finally {
d.close();
}
} catch (SomeException e) {
handleSomeException(e);
revertTransaction();
throw e;
} catch (Throwable t) {
revertTransaction(); // Error: method must return a value of SomeClass
}
} finally {
releaseWriteLock();
}
}
Can this be rewritten to be more readable and less verbose?
Just for fun: when you see the following, what do you do about it?
DBConnection d = null;
try {
acquireWriteLock();
startTransaction();
d = openDBConnection();
try {
doStuff(d);
commitTransaction();
} catch (SomeException e) {
handleSomeException(e);
revertTransaction();
}
} finally {
d.close();
releaseWriteLock();
}

If you switch to Java 7 you can simplify it a lot. Otherwise, there's probably not much you should do about it.
You could try ideas like:
refactor the DB connection + transaction management + lock management into a general method in a common baseclass, with a subclass for each transaction type
refactor the DB connection + transaction management + lock management into a general method in a final class, with an interface for transaction types and an implementation class for each one.
However, unless this particular pattern is repeated many, many times, this kind of refactoring is probably a bad idea. (You'd be creating a local idiom, and the reader has to learn the idiom before the meaning becomes clear.)

Without upgrading to Java 7 you can combine some of this so you only need a single try-catch.
SomeClass someMethod() throws SomeException {
boolean committed = false;
DBConnection d = null;
acquireWriteLock();
try {
startTransaction();
d = openDBConnection();
doStuff(d);
commitTransaction();
committed = true;
} catch (SomeException e) {
handleSomeException(e);
throw e;
} finally {
if( d != null ) d.close();
if( !committed ) revertTransaction();
releaseWriteLock();
}
}
The trick is to make sure revertTransaction() and DBConnection.close() don't throw anything, but if you can't do that then you can put releaseWriteLock() in another finally clause. If you really wanted to improve this more you could do some of the refactorings Stephen C mentioned. Doing something like putting the acquire/release writeLock, start/rollback transaction, and open/close DBConnection are done in base class or some abstract operation class.

Related

Reduce nesting when cleaning up multiple non-Closeable resources

I have a Closeable that needs to clean up multiple resources in the close() method. Each resource is a final class that I cannot modify. None of the included resources are Closeable or AutoCloseable. I also need to call super.close(). So it appears that I cannot handle any of the resources* using try-with-resources. My current implementation looks something like this:
public void close() throws IOException {
try {
super.close();
} finally {
try {
container.shutdown();
} catch (final ShutdownException e) {
throw new IOException("ShutdownException: ", e);
} finally {
try {
client.closeConnection();
} catch (final ConnectionException e) {
throw new IOException("Handling ConnectionException: ", e);
}
}
}
}
I'd prefer a solution with less crazy nesting but I can't figure out how to take advantage of try-with-resources or any other features to do that. Code sandwiches don't seem to help here since I'm not using the resources at all, just cleaning them up. Since the resources aren't Closeable, it's unclear how I could use the recommended solutions in Java io ugly try-finally block.
* Even though the super class is Closeable, I cannot use super in a try-with-resources because super is just syntactic sugar and not a real Java Object.
This a good (albeit unorthodox) case for try-with-resources. First, you'll need to create some interfaces:
interface ContainerCleanup extends AutoCloseable {
#Override
void close() throws ShutdownException;
}
interface ClientCleanup extends AutoCloseable {
#Override
void close() throws ConnectionException;
}
If these interfaces are only used in the current class, I'd recommend making them inner interfaces. But they also work as public utility interfaces if you use them in multiple classes.
Then in your close() method you can do:
public void close() throws IOException {
final Closeable ioCleanup = new Closeable() {
#Override
public void close() throws IOException {
YourCloseable.super.close();
}
};
final ContainerCleanup containerCleanup = new ContainerCleanup() {
#Override
public void close() throws ShutdownException {
container.shutdown();
}
};
final ClientCleanup clientCleanup = new ClientCleanup() {
#Override
public void close() throws ConnectionException {
client.closeConnection();
}
};
// Resources are closed in the reverse order in which they are declared,
// so reverse the order of cleanup classes.
// For more details, see Java Langauge Specification 14.20.3 try-with-resources:
// https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.20.3
try (clientCleanup; containerCleanup; ioCleanup) {
// try-with-resources only used to ensure that all resources are cleaned up.
} catch (final ShutdownException e) {
throw new IOException("Handling ShutdownException: ", e);
} catch (final ConnectionException e) {
throw new IOException("Handling ConnectionException: ", e);
}
}
Of course this becomes even more elegant and concise with Java 8 lambdas:
public void close() throws IOException {
final Closeable ioCleanup = () -> super.close();
final ContainerCleanup containerCleanup = () -> container.shutdown();
final ClientCleanup clientCleanup = () -> client.closeConnection();
// Resources are closed in the reverse order in which they are declared,
// so reverse the order of cleanup classes.
// For more details, see Java Langauge Specification 14.20.3 try-with-resources:
// https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.20.3
try (clientCleanup; containerCleanup; ioCleanup) {
// try-with-resources only used to ensure that all resources are cleaned up.
} catch (final ShutdownException e) {
throw new IOException("Handling ShutdownException: ", e);
} catch (final ConnectionException e) {
throw new IOException("Handling ConnectionException: ", e);
}
}
This removes all the crazy nesting and it has the added benefit of saving the suppressed exceptions. In your case, if client.closeConnection() throws, we'll never know if the previous methods threw any exceptions. So the stacktrace will look something like this:
Exception in thread "main" java.io.IOException: Handling ConnectionException:
at Main$YourCloseable.close(Main.java:69)
at Main.main(Main.java:22)
Caused by: Main$ConnectionException: Failed to close connection.
at Main$Client.closeConnection(Main.java:102)
at Main$YourCloseable.close(Main.java:67)
... 1 more
By using try-with-resources, the Java compiler generates code to handle the suppressed exceptions, so we'll see them in the stacktrace and we can even handle them in the calling code if we want to:
Exception in thread "main" java.io.IOException: Failed to close super.
at Main$SuperCloseable.close(Main.java:104)
at Main$YourCloseable.access$001(Main.java:35)
at Main$YourCloseable $1.close(Main.java:49)
at Main$YourCloseable.close(Main.java:68)
at Main.main(Main.java:22)
Suppressed: Main$ShutdownException: Failed to shut down container.
at Main$Container.shutdown(Main.java:140)
at Main$YourCloseable$2.close(Main.java:55)
at Main$YourCloseable.close(Main.java:66)
... 1 more
Suppressed: Main$ConnectionException: Failed to close connection.
at Main$Client.closeConnection(Main.java:119)
at Main$YourCloseable$3.close(Main.java:61)
at Main$YourCloseable.close(Main.java:66)
... 1 more
Caveats
If the order of clean up matters, you need to declare your resource cleanup classes/lambdas in the reverse order that you want them run. I recommend adding a comment to that effect (like the one I provided).
If any exceptions are suppressed, the catch block for that exception will not execute. In those cases, it's probably better change the lambdas to handle the exception:
final Closeable containerCleanup = () -> {
try {
container.shutdown();
} catch (final ShutdownException e) {
// Handle shutdown exception
throw new IOException("Handling shutdown exception:", e);
}
}
Handling the exceptions inside the lambda does start to add some nesting, but the nesting isn't recursive like the original so it'll only ever be one level deep.
Even with those caveats, I believe the pros greatly outweigh the cons here with the automatic suppressed exception handling, conciseness, elegance, readability, and reduced nesting (especially if you have 3 or more resources to clean up).

Does Java's try-with-resources catch errors or just exceptions?

I have some junit tests which create some resources which should also be closed.
One way to implement this logic is using the #Before and #After approach.
What I did was to encapsulate the creation in some utility class to be reused. For example:
class UserCreatorTestUtil implements AutoClosable {
User create() {...}
void close() {...}
}
The whole point is for the object to close itself, rather than needing to remember to close it in #After.
The usage should be:
#Test
void test() {
try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
User user = userCreatorTestUtil.create();
// Do some stuff regarding the user's phone
Assert.assertEquals("123456789", user.getPhone());
}
}
The problem is that junit's assert keyword throws an Error - not Exception.
Will the try-with-resource "catch" the Error and invoke the close method?
* Couldn't find the answer in the try-with-resources documentation.
It does not catch anything. But it does finally close all resources.
finally blocks are run even when an Error is thrown.
The pseudo-code of a basic try-with-resources statement is (cf Java Language Specification ยง14.20.3.1):
final VariableModifiers_minus_final 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();
}
}
}
As you can see it catches Throwable not Exception which includes Error but only to get the primary exception in order to add as suppressed exceptions any exceptions that occurred while closing the resources.
You can also notice that your resources are closed in the finally block which means that they will be closed whatever happens (except in case of a System.exit of course as it terminates the currently running Java Virtual Machine) even in case an Error or any sub class of Throwable is thrown.
Try-with-resources don't catch anything in and of themselves.
However, you can attach a catch block to the end of the try-with-resources block, to catch whatever types of Throwable you like:
try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
// ... Whatever
} catch (RuntimeException e) {
// Handle e.
} catch (Exception | Throwable t) {
// Handle t.
}
The idea behind try-with-resources is to make sure that the resources should be closed.
The problem with conventional try-catch-finally statements is that let's suppose your try block throws an exception; now usually you'll handle that exception in finally block.
Now suppose an exception occurs in finally block as well. In such a case, the exception thrown by try catch is lost and the exception generated in finally block gets propagated.
try {
// use something that's using resource
// e.g., streams
} catch(IOException e) {
// handle
} finally {
stream.close();
//if any exception occurs in the above line, than that exception
//will be propagated and the original exception that occurred
//in try block is lost.
}
In try-with-resources the close() method of the resource will get automatically called, and if the close() throws any exception, the rest of the finally isn't reached, and the original exception is lost.
Contrast that with this:
try (InputStream inputStream= new FileInputStream("C://test.txt")){
// ... use stream
} catch(IOException e) {
// handle exception
}
in the above code snippet, the close() method automatically gets called and if that close() method also generated any exception, than that exception will automatically get suppressed.
See also: Java Language Specification 14.20.3
Misconception on your end: try-with-resources does not do a catch.
It does a final finally, therefore the kind of "problem" doesn't matter.
See the JLS for further information!

How to make sure resource is released, with nested object hierarchy?

I have code (simplified) like this:
class A {
B b = new B();
void close() {
b.close();
}
}
class B {
Closeable mustBeClosed = new Closeable() {
{
System.out.println("create");
}
#Override
public void close() {
System.out.println("close");
}
};
int n = 0 / 0;
void close() {
mustBeClosed.close();
}
}
//code
try (A a = new A()) {
//do something
}
How to guarantee mustBeClosed is released?
This likely happens when the object hierarchy is complex. Override finalize for B might not be a perfect solution.
Any best practice or principle against this issue?
A revised version looks like:
class B {
Closeable mustBeClosed;
B() {
try {
mustBeClosed = ...
//other initialization which might raise exceptions
} catch (throwable t) {
close();
throw t;
}
}
void close() {
if (mustBeClosed != null) {
try {
mustBeClosed.close();
} catch (Throwable t) {
}
}
//all other resources that should be closed
}
}
However this takes too much code and is far from elegant. What's more, it seems that all classes in the ownership hierarchy should follow the same style, which results lots of code.
Any advice?
Your problem is that try-with-resources won't (actually can't) call close() if the constructor throws an exception.
Any object construction that allocates a resource, and has the potential to fail during construction after the resource is allocated, must release that resource before the exception is cascaded up the call stack.
Two ways to fix that:
1) Make sure the resource allocation is the last action performed. In your case, that means move field n up before field mustBeClosed.
2) Handle the resource construction in the constructor, not in a field initializer, so you can catch any subsequent exception and release the resource again before re-throwing the exception, as your alternate solution shows.
However, you don't have to null-check in the close() method, because mustBeClosed will always be non-null if the object construction succeeds, and close() cannot be called if the object construction fails.
Use a wrapper method to close all Closeable instances gracefully.
closeGraceFully(Closeable c) { // call this guy for all instances of closeable
try{
c.close();
} catch(IOException ex) {
// nothing can be done here, frankly.
}
}
Then call this wrapper method. don't call close() directly. Don't use finalizers they are evil and will slow down your app.

How to avoid duplicate codes that is common for all methods of a class?

In our application, in DAO layer every method follows almost same sequence:
public List getSomeValue(String[] parameters) {
try {
//Get connection from pool
//Execute procedure
//Process resultset
} catch (SomeException e) {
//Error handling mechanism
} finally {
//Release connection
}
return someResult;
}
All the commented lines in the above code describes the operation we are doing.
Now, other than process result-set part, everything is almost exactly same.
My question is, can we implement some kind of design, so that we don't have to write the same code again and again in each and every method? So that, we just have to write result-set processing part.
Utility methods are already in place. But again we have to call them in each and every procedure in exactly same sequence. Can we have something so that these predefined methods will be called automatically and we have to write only the part that differs? I'm not even sure if this is at all possible or not.
Note: We can not use any ORM tool like Hibernate.
Why not pass in a mapper that knows how to convert the ResultSet into the List of elements you expect. For example:
public List<T> getSomeValue(String[] parameters, ResultSetMapper<T> mapper) {
try {
//Get connection from pool
//Execute procedure
//Process resultset
return mapper.convert(resultSet);
} catch (SomeException e) {
//Error handling mechanism
} finally {
//Release connection
}
}
interface RowMapper<T> {
List<T> convert(ResultSet resultSet);
}
You'd pass in different mapper implementations, and the getSomeValue method would stay the same, so you'd only need 1 implementation of it.
If you are using Spring in your project, you can use its ResultSetExtractor or RowMapper classes to do something similar.
Since java 8 you method could be refactored to something like;
Object doSomething(){
return doInTransaction(trans -> {
return trans.load();
});
}
Where InTrans is
public interface InTrans<T> {
T call(Transaction transaction);
}
and doInTransaction
<T> T doInTransaction(InTrans<T> callable){
try {
Connection connection = ...
return callable.call(connection));
} catch (SomeException e) {
//Error handling mechanism
} finally {
//Release connection
}
}
Alternatively you can use declarative transaction from Spring
This uses the same principle proposed by talex in his answer, except that for what you are looking for, I believe that what you want is to use the Consumer<T> functional interface (or some other similar interface) using a ResultSet as input.
So basically, all your fetching of the connection, procedure execution, looping of the resultset and the exception handling remains inside the one method without repetition. And when you invoke the method, you pass in the code that will process each row.
It will look something like this:
public void callingCode() {
List<String> someList = new ArrayList<>();
performQuery(
"SELECT * FROM ...",
new String[]{"param1", "param2"},
rs -> {
try {
// process your row here.
someList.add(rs.getString("somecolumn"));
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
}
public void performQuery(String query, String[] parameters, Consumer<ResultSet> processRow) {
try {
//Get connection from pool
//Execute procedure
ResultSet rs = null; // pretend this comes from the procedure call.
//Process resultset
while (rs.next()) {
processRow.accept(rs);
}
} catch (Exception e) {
//Error handling mechanism
} finally {
//Release resources
}
}
EDIT:
The annoying thing with the Consumer<T> functional interface is that the method signature doesn't allow for any checked exceptions, so the SQLExceptions need to be handled explicitly (in the code above, you can see that I'm forced to wrap the SQLException in a RuntimeException). To avoid this annoyance, you could choose not to use the built-in Consumer<T> functional interface, and instead, create your own that does include throws SQLException as part of the method signature.
ResultSetConsumer interface:
public interface ResultSetConsumer {
void processRow(ResultSet rs) throws SQLException;
}
Adjusted code:
public void callingCode() {
List<String> someList = new ArrayList<>();
performQuery(
"SELECT * FROM ...",
new String[]{"param1", "param2"},
rs -> {
// process your row here.
someList.add(rs.getString("somecolumn"));
});
}
public void performQuery(String query, String[] parameters, ResultSetConsumer rsConsumer) {
try {
//Get connection from pool
//Execute procedure
ResultSet rs = null; // pretend this comes from the procedure call.
//Process resultset
while (rs.next()) {
rsConsumer.processRow(rs);
}
} catch (Exception e) {
//Error handling mechanism
} finally {
//Release resources
}
}
You can create a base class having the common methods written there and then inherit the class from base class, so every child class will inherit them.
If having a super class is not an option (restricted by the framework or some other reasons), you can write a utility class having static methods for common functionality.

Proper way to handle Runtime Exceptions in Java

I'm completely new to this code and begun to questions the design choices of the original developers.
I have a multi-threaded Java application that processes a number of tasks. My job is to fix the exception handling in the code so that when a RuntimeException occurs (iBatis and/or NullPointerException) the rest of the tasks are executed instead of the thread terminating. I want to know what is the best way to deal with the exception handling below:
public List<WorkUnit> performModule(List<WorkUnit> listOfInputs)
throws ModuleException {
List<WorkUnit> listOfOutputs = new ArrayList<WorkUnit>();
for (WorkUnit mi : listOfInputs) {
WorkUnit mo=null;
try {
if (mi instanceof BulkOrder) {
mo = performModuleOperation(...);
} else if (mi instanceof Order) {
mo = performModuleOperation(...);
} else if (mi instanceof PreReleaseLoad) {
mo = performModuleOperation(...);
} else if (mi instanceof Load) {
mo = performModuleOperation(...);
}
listOfOutputs.add(mo);
} catch (OMSException e) {
if (e.shouldProcessFurther()) {
listOfOutputs.add((mo!=null) ? mo : mi);
}
//save error to database - code was removed
if ( e.getExceptionType().equals(ExceptionType.TECHNICAL)) {
if ( e instanceof ModuleException ) {
throw (ModuleException) e;
} else {
throw new ModuleException(e);
}
}
} catch (Throwable th) {
ModuleException me = new ModuleException(th);
ExceptionHandler.logException(me, (WorkUnit)mi,orderDelegate);
throw me;
}
}
return listOfOutputs ;
}
I have two major problems. 1) The catch for the Throwable object. I understand that they want to capture checked exceptions and unchecked exceptions. I guess that they want to check for Errors as well but the Sun documentation for exception handling specifically states that this is highly advised against. In the event you get a really serious error like the JVM running out of memory you may not be able to recover. This could be caught in a log file and I don't agree with it needing to be dealt with. Personally if you are tracking technical and applications exceptions errors doesn't seem like something that you would monitoring like any other exception. I could be wrong...
2) It isn't clear how the exceptions are being handled. In the code below the, which the exception throws to the code above it wraps a regular exception be it checked or unchecked into a custom exception and throws that. The code above looks for an OMSException which is the parent of every custom exception in the entire application. Is this a good design? You can see where they include a ExceptionType to the custom exception object. There already seems to be an functionality built into the existing exception handling of Java. If it is an application exception then throw a custom exception. If it is a technical exception, something is null when it isn't suppose to be or a database connection problem, then catch a unchecked exception from Java and react accordingly. This whole thing seems confusing. I just want to know what thoughts other have on the whole thing.
public Order performModuleOperation(Order order)
throws ModuleException {
try {
Map<String, Rule> rules = ...
}
catch (InductException ie) {
throw ie;
}
catch (Exception e) {
e.printStackTrace();
throw new InductException(e.toString(),e);
}
return order;
}
There are two ways to deal with a thread that exits with an unchecked exception. The first option is to run the thread from with in a try-catch block that catches all errors and exceptions:
Thread t = new MyThread();
try {
lauchThreadHere(t);
} catch (Throwable e) {
// log `e` or re-launch thread `t` or do something else.
}
Another way is to implement Thread.UncaughtExceptionHandler:
public class MyUeh implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
// log `e` or re-launch thread `t` or do something else.
}
}
Thread t = new MyThread();
t.setUncaughtExceptionHandler(new MyUeh());
lauchThreadHere(t);

Categories