Question

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:

  1. The files that were supposed to be deleted as a result of the finally block were not deleted.

  2. 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.

  3. The messages were not getting sent.

  4. I set breakpoints in the code and determined that renderBinary was being called, but the finally block was not getting executed.

  5. Just to be safe, I added log messages to the finally clause, and these also were not present.

  6. 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.)

Was it helpful?

Solution

It's true. I just found out about this today, since my company uses the play framework and someone ran into it.

As I understand it, this likely only occurs in play versions prior to 2.0, but when you catch all Exceptions following a render call, play apparently rewrites the code to skip the finally block...

I don't understand why or exactly how this is done, but it is apparently the case.

If you catch a specific exception, I don't think this will happen.

But yes, you're not crazy or a bad programmer. This really is just a weird, undocumented play gotcha.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top