Skip to content
Ryan Heaton edited this page Sep 17, 2015 · 1 revision

JAX-RS Endpoint Lifecycle Explained

Default JAX-RS Bean Lifecycle

The JAX-RS specification dictates that the default lifecycle of an endpoint class is once-per-request. Take the following endpoint class, for example:

@Path ("/mypath")
public class MyEndpoint  {
 @GET
 @Path("/hello")
 public String helloWorld() {
   return "hello world!";
 }
}

According to the JAX-RS specification, there will be one instance of MyEndpoint for every request to /mypath/hello.

There are advantages to this approach. For example, the JAX-RS can manage the entire lifecycle of the endpoint bean and do things like inject request-specific parameters and context into fields on the endpoint bean. For example:

@Path ("/mypath")
public class MyEndpoint  {

 @Context
 HttpServletRequest request;

 @GET
 @Path("/hello")
 public String helloWorld() {
   return "hello world!";
 }
}

Since the JAX-RS implementation is managing the lifecycle of this bean, it can safely inject the HttpServletRequest into the request field without having to worry about disrupting the state of the endpoint bean.

JAX-RS Bean Lifecycle and Other Containers

The problem with the one-bean-per-request lifecycle strategy comes when you try to integrate with other DI containers. Spring, for example, defaults the lifecycle of its beans to be one-per-application (a.k.a. "singleton"). Developers who want to leverage the features of Spring to manage the lifecycle of their endpoint beans have to somehow reconcile the difference between the default JAX-RS behavior (one-per-request) and the behavior of Spring (one-per-application).

To account for this reconciliation, the JAX-RS specification relaxed its restriction to allow different JAX-RS implementations to define their own lifecycle management capabilities. Jersey, for example, tends to hold to the one-per-request lifecycle mapping, but provides some support for Spring integration by allowing developers to have fields on the endpoint bean whose instances are provided by Spring (see the com.sun.jersey.spi.inject.Inject annotation). CXF, on the other hand, uses the one-per-request lifecycle only when there is no endpoint bean defined in the Spring container. Otherwise, it assumes one-per-application.

Enunciate 1.x and JAX-RS Bean Lifecycle

Note: The following applies to Enunciate version 1.x. Enunciate 2 moved away from the business of managing JAX-RS lifecycles.

Enunciate 1.x supports a number of different configurations for JAX-RS providers. The following table describes the different ways Enunciate 1.x can be configured and how the bean lifecycle is managed.

Configuration Lifecycle Maven Plugin
Jersey (no Spring) Lifecycle is managed by Jersey and is therefore one-per-request maven-enunciate-plugin
Jersey (with Spring) Lifecycle is one-per-request, unless the endpoint bean defined in an imported Spring context, in which case the lifecycle is Spring-managed maven-enunciate-spring-plugin
CXF Lifecycle is managed by CXF, which states one-per-request unless defined differently in the Spring context maven-enunciate-cxf-plugin

So let's say you've configured Enunciate 1.x to use Jersey with Spring. Enunciate 1.x will not automatically define your endpoint beans in a spring application context because we doesn't want to assume you want one-per-application lifecycle. If you do want the lifecycle of your endpoint beans to be managed by Spring, you have to define them in your own beans file and import it in the Enunciate configuration. Alternatively, you could have the lifecycle of your endpoint beans to be managed by Jersey (one-per-request) but have Jersey inject beans that are defined in your Spring application context into the fields of your endpoint bean. For example:

@Path ("/mypath")
public class MyEndpoint  {

 @com.sun.jersey.spi.inject.Inject("my-bean-defined-by-spring")
 MySpringManagedBean bean;

 @GET
 @Path("/hello")
 public String helloWorld() {
   return "hello world!";
 }
}
Clone this wiki locally