Register the response-close filter at the highest precedence
The filter only has to run before Grails' grailsWebRequestFilter
(HIGHEST_PRECEDENCE + 30), which builds the GrailsWebRequest from the
response it receives. Ordering it relative to the Sentry filter was
arbitrary; registering it at the highest precedence keeps it in front
of any filter added later.
Address review: explain filter ordering, packaging and close semantics
Comment-only: say why the filter is ordered right after the Sentry filter,
that the class is neither component-scanned nor packaged, who calls close()
on the writer and the stream and who closes the container's own stream, and
walk through the spec step by step.
Fix flaky API specs racing transactional controller commits
The Grails JSON converter closes the response writer at the end of render(),
which makes the container finish the response while a class-level
@Transactional controller action has not yet committed. The API specs fire
their next request as soon as the previous response is complete, so that
request can reach the database before the commit. This is the source of the
intermittent "foreign key constraint fails" and "unsaved transient instance"
failures in run-backend-tests.
Add DeferResponseCloseFilter to the integration test source set and register
it for every integration spec from IntegrationSpecConfig. It turns close() on
the response writer and output stream into a flush (discarding further
output, as the container does after a real close) so that a response finished
by closing the writer or stream is completed when the request finishes, after
the action has returned and its transaction has completed. No production
sources change and the filter is not packaged into the application.
Add an integration spec that blocks a category save's commit from Hibernate's
post-insert event and asserts the client is still waiting.