Request-scoped context field injections into RESTE

2019-01-18 14:05发布

While trying to embed RESTEasy with singleton resources in OSGi (using something similar to resteasy-osgi-bundle), to my surprise field-injected @Context UriInfo was available and valid on each request.

Digging deeper I found proxy magic and ThreadLocal in ResteasyProviderFactory. All well and good, but I cannot find any reference to such a behavior in docs, neither in RESTEasy's one nor in JAX-RS spec.

In Jersey docs we can find something like:

The exception exists for specific request objects which can injected even into constructor or class fields [of resources with singleton scope — OP]. For these objects the runtime will inject proxies which are able to simultaneously server more request. These request objects are HttpHeaders, Request, UriInfo, SecurityContext. These proxies can be injected using the @Context annotation.

How does it look in RESTEasy? Is the current implementation stable or experimental? What is the set of request-specific classes that can be injected into singletons?

1条回答
Luminary・发光体
2楼-- · 2019-01-18 14:45

It's not experimental. This behavior (for a set of common objects) is specified in the JAX-RS spec. There aren't any anchors in the spec page to link to a certain section, but where you should look is Chapter 5: Context. I'll post some snippet here.

5.1 Concurrency

Context is specific to a particular request but instances of certain JAX-RS components (providers and resource classes with a lifecycle other than per-request) may need to support multiple concurrent requests. When injecting an instance of one of the types listed in section 5.2, the instance supplied MUST be capable of selecting the correct context for a particular request. Use of a thread-local proxy is a common way to achieve this.

5.2 Context Types

This section describes the types of context available to resource classes, providers and Application subclasses.

5.2.1 Application

The instance of the application-supplied Application subclass can be injected into a class field or method parameter using the @Context annotation. Access to the Application subclass instance allows configuration information to be centralized in that class. Note that this cannot be injected into the Application subclass itself since this would create a circular dependency.

5.2.2 URIs and URI Templates

An instance of UriInfo can be injected into a class field or method parameter using the @Context annotation. UriInfo provides both static and dynamic, per-request information, about the components of a request URI. E.g. the following would return the names of any query parameters in a request:

5.2.3 Headers

An instance of HttpHeaders can be injected into a class field or method parameter using the @Context annotation. HttpHeaders provides access to request header information either in map form or via strongly typed convenience methods. E.g. the following would return the names of all the headers in a request:

5.2.4 Content Negotiation and Preconditions

JAX-RS simplifies support for content negotiation and preconditions using the Request interface. An instance of Request can be injected into a class field or method parameter using the @Context annotation. The methods of Request allow a caller to determine the best matching representation variant and to evaluate whether the current state of the resource matches any preconditions in the request...

5.2.5 Security Context

The SecurityContext interface provides access to information about the security context of the current request. An instance of SecurityContext can be injected into a class field or method parameter using the @Context annotation. The methods of SecurityContext provide access to the current user principal, information about roles assumed by the requester, whether the request arrived over a secure channel and the authentication scheme used.

5.2.6 Providers

The Providers interface allows for lookup of provider instances based on a set of search criteria. An instance of Providers can be injected into a class field or method parameter using the @Context annotation.

One thing to note is that there may more types that can be injected, but any not listed above would be implementation specific. Here is the list from the RESTeasy documentation in the section Chapter 15. @Context

The @Context annotation allows you to inject instances of javax.ws.rs.core.HttpHeaders, javax.ws.rs.core.UriInfo, javax.ws.rs.core.Request, javax.servlet.HttpServletRequest, javax.servlet.HttpServletResponse, javax.servlet.ServletConfig, javax.servlet.ServletContext, and javax.ws.rs.core.SecurityContext objects.

Though the documentation doesn't make any distinction between field and parameter injection, from what I remember, I think I was able to get HttpServletRequest injected into a field. But I would just test them all to make sure.

查看更多
登录 后发表回答