-
Notifications
You must be signed in to change notification settings - Fork 200
JAX RS 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.
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.
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!";
}
}