RESTEasy JAX-RS application not calling @PreDestroy

999 Views Asked by At

I'm using RESTEasy 3.1.0.CR3 with its servlet initializer in Tomcat 8.5, via annotations (no web.xml):

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jaxrs</artifactId>
        <version>3.1.0.CR3</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-servlet-initializer</artifactId>
        <version>3.1.0.CR3</version>
    </dependency>

I have a JAX-RS application that I need to know before it is destroyed/uninstalled from the container, so that I can release some resources (stop a thread):

@ApplicationPath("/")
public class MyRESTApplication extends Application {

  …

  @Override
  public Set<Class<?>> getClasses() {
    …
  }

  @Override
  public Set<Object> getSingletons() {
    …
  }

  @PreDestroy
  public void end() {
    //TODO release resources
  }

But my end() method doesn't seem to be called. Am I doing this wrong? Is there a better way to detect when a JAX-RS application is taken down?

2

There are 2 best solutions below

4
On

I'm not sure if this is supported. For @PreDestory the same rule applies like for @PostConstruct:

This annotation MUST be supported on all classes that support dependency injection.

Is dependency injection in an Application class supported? A JAX-RS implementation may integrate Managed Beans, EJBs or CDI but this is optional. JAX-RS itself provides dependency injection via @Context but explicitly not in an Application class (ch. 9.2.1 of the specification).

So @PreDestory may work in some environments but there's no guarantee.

In your environment I would implement a custom ServletContextListener and release resources in #contextDestroyed. Your Application class should be accessible via the ServletContext:

Map<String, ResteasyDeployment> deployments = (Map<String, ResteasyDeployment>)
    request.getServletContext().getAttribute("resteasy.deployments");
ResteasyDeployment deployment = deployments.get("/application/path");
Application application = deployment.getApplication();

You could also handle everything in a custom ServletContextListener without the Application class and store references as ServletContext Attributes.

0
On

This seems to be quite a big oversight in the JAX-RS specification. See the following discussion:

[jax-rs-spec users] Fwd: Lifecycle management in Application subclasses

Some reasonable workaround would be appreciated.