4

I've created a request scoped bean which should call a method once the request ends. I tried to do so with a @PreDestroy annotated method, but this won't work.

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionProvider {
    @PreDestroy
    public void cleanup() {
        // DO STUFF
    }
}

How can I achieve the described behavior?

Lacuno
  • 444
  • 4
  • 13
  • Can you post your spring xml file's code snippet here? – Karthik R Sep 09 '15 at 08:32
  • 3
    PreDestroy is called just before instance of this component is destroyed, it does not have anything to requests. You can add method to this class which will handle your request, or please explain what do you mean by 'request ends' – ikos23 Sep 09 '15 at 08:34
  • @john I suppose that he tries to check if the PreConstruct works as soon as the request is complete as he has scoped it as "request" – Karthik R Sep 09 '15 at 08:38
  • PreConstruct - call a method before object is created ;)) @Christoph - check out this one: http://stackoverflow.com/questions/5638538/spring-destroy-method-request-scope-bean (OP never got it working but maybe yours is similar case). – Rafal G. Sep 09 '15 at 08:41
  • Implement `DisposableBean` or `Closeable` instead of using the annotation. – M. Deinum Sep 09 '15 at 08:51
  • This did not work at all @john Yes I want to call this method when the request is completed. – Lacuno Sep 09 '15 at 09:43

2 Answers2

2

I've solved this issue by registering an own RequestContextListener:

public class MyRequestContextListener
        extends RequestContextListener {

    @Override
    public void requestDestroyed( ServletRequestEvent requestEvent ) {

        super.requestDestroyed( requestEvent );
        applicationContext.getBean( SessionProvider.class ).cleanup();
    }
}

Hopefully this helps someone else.

Best regards, Chris

Lacuno
  • 444
  • 4
  • 13
1

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.

Prashant
  • 25
  • 5