I was recently surprised to find that the finally block in this play framework controller action code only got called after an Exception, but never when the call actually succeeded.
try {
InputStream is = getInputStreamMethod();
renderBinary(is, "out.zip");
catch (Exception e) {
e.printStackTrace();
} finally {
cleanUp();
}
Perhaps the thread is terminated or something when renderBinary() is called, but to me, it was non-intuitive. I would suspect the same thing happens for other render() calls, but I didn't verify it.
I solved the problem by moving the renderBinary() to after the try/catch. Further investigation revealed that play provides an @Finally annotation to create a method that gets executed after a controller action executes. The caveat here is that this will get called after the execution of ANY action in the controller, so it may not always be a good choice.
My question is: why does the finally block not get executed after a renderBinary(), and is this documented anywhere? I can't find any reference to it in the play doc.
To clarify the sequence of events that led to this discovery:
The files that were supposed to be deleted as a result of the finally block were not deleted.
Thinking that it couldn't possibly be caused by a non-executing finally block, I changed the methodology to use the Amazon SQS Messaging Queue to send a message in the finally block -- a separate job receives the message and deletes the associated files.
The messages were not getting sent.
I set breakpoints in the code and determined that renderBinary was being called, but the finally block was not getting executed.
Just to be safe, I added log messages to the finally clause, and these also were not present.
I have repeated the debug exercise several times, and each time, the finally clause is not executed.
(Please note that the actual code doesn't really look like the above. This is a very simplified example just to illustrate the case.)