If you are using filters or interceptors, you can avoid writing your custom request context listener and instead inject your request scoped bean in the filter and do your cleanup in there.
For example, in our rest application which uses jersey, we release the resources in our application in the following way -
public class MyResourceManager implements ContainerResponseFilter {
/* MyCustomIO class is defined to be request
scoped using proxyMode = TARGET_CLASS */
@Inject // Use @Autowired if you aren't using JSR-330 annotations
private MyCustomIO myIO;
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
// Perform your clean up here
myIO.cleanup();
}
}
Some people may argue that filters aren't meant for this, but we realized that sometimes a filter is the best place to do resource clean up at a "request" level - this is because usually our goal is to release the resources taken up during a request as soon as the request completes (or just before it completes). Relying on destroy method callback on the bean may not necessarily release the resources on completion of request as we do not have any control over garbage collection.
Also, since the only main thing which happens after filter execution is response object serialization which doesn't require any IO, it is fairly safe to clean up resources at this point without worrying about them being still in use.
But of course, this solution cannot be used for clean up at a session or application level.