How does an JAX-RS 'endpoint' behave when making a request? - java

There is something I am not sure I understand correctlty, therefore, I need help:)
I have seen this: example,
#Path("/resource")
public class Resource {
#Context
private HttpHeaders headers;
#GET
public void get(#Context UriInfo uriInfo) {
/* use headers or uriInfo variable here */
}
}
Does this mean that for each request the class that is transformed to 'endpoint' creates a separate thread? Because, otherwise, the headers information would not be accurate...
Can you please indicate a (short:) ) resource, not JAX-WS specifications, where I can find info about this?

I can't think of a shorter and more direct resource than the JAX-RS 1.1 spec itself. It is clear about what you are asking:
JAX-RS provides facilities for obtaining and processing information about the application deployment context and the context of individual requests. (...)
Context is specific to a particular request (...).
May I add for completeness: that context information is obtained through the #Context annotation. As of resources, the context information is only available to the ones annotated with #Path (also called root resources). Also, #Context can inject the following context types: Application, UriInfo, HttpHeaders, Request, SecurityContext and Providers.
And about the lifecycle (request/thread management):
3.1.1 Lifecycle and Environment
By default a new resource class instance is created for each request
to that resource. First the constructor is called,
then any requested dependencies are injected (context is one of those dependencies), then
the appropriate method is invoked and finally the
object is made available for garbage collection.
An implementation MAY
offer other resource class lifecycles, mechanisms for specifying these
are outside the scope of this specification. E.g. an implementation
based on an inversion-of-control framework may support all of the
lifecycle options provided by that framework.
The conclusion is:
Each request is, by default, handled by a different resource instance;
The context is injected at request time (thus a different context per instance).
Each specific implementation may change this lifecycle a bit, but the principles should be maintained (a context specific to each request).
As you can see, also, the spec says nothing about thread management. Since most JAX-RS implementations are Servlet-based, we can assume with certain safety that the each request instance goes to a different thread - as servlet containers are thread per request.

Related

Difference between javax.security.enterprise.SecurityContext and javax.ws.rs.core.SecurityContext?

I am struggling to understand when and how to use the different interfaces.
They seem to be quite similar, with some minor differences in method names to dynamically check security roles or retrieve the Principal, but - as far as I am currently understanding - are only accessible in their specific context.
I am trying to implement fine grained authorization with specific requirements.
Mainly the roles are not stored in the tokens, but must be read from a table in the database.
Therefore I have an implementation of IdentityStore that provides a CallerPrincipal with all available roles.
The IdentityStore is used by my HttpAuthenticationMechanism implementation, which is fairly simple, thus all it does is for valid requests to call HttpMessageContext.notifyContainerAboutLogin to push the CallerPrincipal into the SecurityContext - as far as I know.
Because there are a lot of generic endpoints in the codebase with path parameters, that decide which role has to be checked I need a generic way of checking if the user is in a role depending on the value of some path segments of the requested uri.
I created a method interceptor for that, where I want to access the SecurityContext, but both interfaces have their problems here:
#Interceptor
public class RolesAllowedInterceptor {
#Context
private UriInfo uriInfo;
// this injection is always null
#Context
private javax.security.enterprise.SecurityContext securityContext;
// this injection works
#Context
private javax.ws.rs.core.SecurityContext securityContext;
#AroundInvoke
public Object validate(InvocationContext ctx) throws Exception {
... // read path param to retrieve role and check SecurityContext.isUserInRole()
}
}
The injection of javax.security.enterprise.SecurityContext does not work. I assume the reason for this is, that the interceptor is called in a JAX-RS context.
The injection of javax.ws.rs.core.SecurityContext works (my assumption in 1. is based on this). But when SecurityContext.isUserInRole(String) is called, the debugger shows, that the Principal does not have any of the groups (roles in my business context) that were assigned via my IdentityStore implementation and thus the validation incorrectly fails.
I am currently using another approach with ContainerRequestFilter to set the javax.ws.rs.core.SecurityContext explicitly, which is working fine for the interceptor, but not with the javax.annotation.security.RolesAllowed annotation. For that I shifted the invocation of my IdentityStore into the filter, because I obviously do not want to call it twice.
I am not looking for complete code examples/solutions.
I am merely trying to understand why there are different interfaces of SecurityContext, as the Java Docs do not elaborate on that.
And therefore hopefully understand how I can use RolesAllowed for static endpoints and my interceptor for generic endpoints, without the need of a ContainerRequestFilter to set the SecurityContext for the later.
--
For context: I am using Payara Micro and jakartaee-api:8.0.0

Request scoped bean is always available when running code outside of request scope in Spring 4

Stuck on this thing in Spring 4, probably the same will be for 5.
So, what I have:
Spring Boot 1.5 web app
Request scoped bean:
#RequestScope
#Component
public class APIAction { ... }
Code which accesses this component from threads related or not related to webrequest:
private final ObjectProvider<APIAction> apiAction;
apiAction.getIfAvailable()...
When it runs in Thread bounded to web request everything is fine. But when I invoke it from daemon thread I expect to get null, exception or something else. Instead I'm receiving some proxy object which can't be tested for null, or any kind of state indicating that bean is really available. If I'll try to invoke any bean method, I'll get exception finally saying accessing to bean outside of thread bounded to web request.
So the question is, am I using it wrong? Right now, I'm checking request scope before accessing to bean by invoking this: RequestContextHolder.getRequestAttributes() != null, which is really ugly, and I need all the time to tell people why they should use it like this.
And bonus question, is it possible actually to instantiate that bean in threads without request bound?
TL;DR: You can't use ObjectProvider.getIfAvailable() to check if in request scope.
Use if (RequestContextHolder.getRequestAttributes() != null) instead.
As the javadoc of ObjectProvider says:
A variant of ObjectFactory designed specifically for injection points, allowing for programmatic optionality and lenient not-unique handling.
For singleton beans, ObjectProvider<APIAction> is an alternative to #Autowired(required = false) List<APIAction> with methods that better represent the purpose.
For prototype beans, it allows the on-demand creation of the prototype, including optional constructor arguments.
However, it's all about the existence of the bean, i.e. about whether the bean has been registered (and how many). Any #Component (or other) annotated class is registered by the component scanning, regardless of the bean scope.
The #RequestScope bean exists, so the code could be changed to #Autowired private final APIAction apiAction;, and it would always be non-null.
The fact that the object referred to by apiAction is a proxy that will apply method calls to different instances depending the the request context is besides the point.
When you call an APIAction method, you will get an IllegalStateException saying:
No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Internally, a #RequestScope annotated class has a Scope of type RequestScope, and the javadoc says:
Relies on a thread-bound RequestAttributes instance.
It does this by calling RequestContextHolder.currentRequestAttributes(), which throws the above exception.
Solution: To check if you are in a request context, call RequestContextHolder.getRequestAttributes() and check for null return value.

How will a Rest Service execute when a user access a resource from resource class?

When multiple users are requesting the same resource method from a service class, how will requests be handled at the server?
How will a rest service execute for each request? How different the execution life cycle of rest service from the servlet execution?
For example, if below is the Resource, how will it be instantiated and executed in the following scenarios:
case 1: two users call the two different methods at a time
case 2: two users call the same method at a time
#Path("greet")
public class GreetingResource {
#GET
#Path("welcome/{username}")
#Produces(MediaType.TEXT_PLAIN)
public String sayWelcome(#PathParam("username") String User) {
return "Welcome!" + User;
}
#GET
#Path("hello/{username}")
#Produces(MediaType.TEXT_PLAIN)
public String sayHello(#PathParam("username") String User) {
return "Hello " + User;
}
}
From Jersey documentation which is JAX-RS implementation:
Default lifecycle (applied when no annotation is present). In this
scope the resource instance is created for each new request and used
for processing of this request. If the resource is used more than one
time in the request processing, always the same instance will be used.
This can happen when a resource is a sub resource and is returned more
times during the matching. In this situation only one instance will
serve the requests.
From Life Cycle of JAX-RS Resource Class:
By default the life-cycle of root resource classes is per-request
which, namely that a new instance of a root resource class is created
every time the request URI path matches the root resource.
In short, following things happen in sequence.
Path’s are matched with Resource classes.
Constructor is called.
Dependencies are injected.
Appropriate method is called.
Resource is garbage collected.
Strangely, JAX-RS resource classes are not by default singleton. In
general this is unlikely to be a cause of performance issues. Class
construction and garbage collection of JVMs has vastly improved over
the years and many objects will be created and discarded to serve and
process the HTTP request and return the HTTP response.
While endpoint class is created new upon request by default, you can make it singleton to have one instance per JAX-RS application: JAX-RS Resource Lifecycle Performance Impact
Talking about your examples, in both case 1 and 2 instantiation wouldn't differ and users would use 2 instances of GreetingResource and get their name on return. In case 2, if the method would use database and 2 users would modify the same resource, you would need to manage concurrent access with optimistic locking or other solution.
Servlet classes
A servlet container creates a single instance of a servlet class to handle all the requests to that servlet. See the following quote from from the JSR 369 the defines the Servlet 4.0 specification:
For a servlet not hosted in a distributed environment (the default), the servlet container must use only one instance per servlet declaration. [...]
The Servlet interface defines methods to initialize a servlet, to service requests, and to remove a servlet from the server:
The servlet is constructed, then initialized with the init method.
Any calls from clients to the service method are handled.
The servlet is taken out of service, then destroyed with the destroy method, then garbage collected and finalized.
Don't hesitate to check the specification for further details.
Resource classes
While servlet classes are managed by the servlet container, resource classes are managed by the JAX-RS runtime. By the way, JAX-RS applications don't even require a servlet container to be deployed.
By default, resource classes (the ones annotated with #Path) are request-scoped. It means that the JAX-RS runtime will create a new resource class instance for each request to that resource. Quoting the JSR 370, the document the defines the JAX-RS 2.1 specification:
By default a new resource class instance is created for each request to that resource. First the constructor is called, then any requested dependencies are injected, then the appropriate
method is invoked and finally the object is made available for garbage collection. [...]
According to Jersey documentation, in general this is unlikely to be a cause of performance issues. Class construction and garbage collection of JVMs has vastly improved over the years and many objects will be created and discarded to serve and process the HTTP request and return the HTTP response.
Also this makes for a very natural programming model where constructors and fields can be utilized without concern for multiple concurrent requests to the same resource.
EJB and CDI
For an implementation that supports EJB, resource classes can be annotated with #Stateless or #Singleton.
JAX-RS implementations may also support CDI however JAX-RS and CDI have slightly different component models. By default, JAX-RS resource classes are managed in the request scope, and no annotations are required for specifying the scope. CDI managed beans annotated with #RequestScoped or #ApplicationScoped can be converted to JAX-RS resource classes.
See the Java EE 8 Tutorial for examples.
Provider classes
Differently from resource classes, provider classes (the ones annotated with #Provider) are application-scoped by default. It means that the JAX-RS runtime will create only a single instance for each provider class. From the JSR 370:
By default a single instance of each provider class is instantiated for each JAX-RS application. First the constructor is called, then any requested dependencies are injected, then the appropriate provider methods may be called multiple times (simultaneously), and finally the object is made available for garbage collection. [...]

Avoiding repetitive arguments in Java EE

TL;DR The question is about avoiding repetitive arguments in method signatures without performance degradation.
public void foo(Context context, Config config, Request request);
void helper(Context context, Request request);
void otherHelper(Context context, Config config, Request request);
I need signatures like this:
public void foo(Request request);
void helper(Request request);
void ohterHelper(Request request);
Configuration won't change very often, some arguments will be request scoped. Caches may have a broader, conversation scope etc.
I want to apply this idea to Java Enterprise environment.
It should be a bean with injected field config that calls other beans f and g (also with fields config) and concatenates results as in example. It should extend to many more fields like config (e.g. context or cache), but only request data from client is allowed in actual method signature (in this example there is none to be concise).
Lifecycle of all config fields should be managed so that all beans in see same config value for the duration of some externally managed scope (e.g. request to facade).
There may exist an EE pattern that solves this problem.
I am explicitly not looking for solutions using ThreadLocal as I want to be able to run tasks in parallel (if at all possible). I am also not looking for AOP and scoped beans (constant allocation and work for GC, I have done profiling before in similar situation).
I have feeling that solution might be an "lost art" today and may be as simple as proper container management (with dependency injection) of pooled of session beans. The trick would be for container to know how to manage lifecycle of g and h within f while injecting (or mutating) all fields when a scope changes (e.g. new request, new conversation).
Assuming some way to get the config and context, set your current methods to private and create a public convenience function:
public void foo(Request request) {
Context context = getContext();
Config config = getConfig();
foo(context, config, request);
}

What objects can I inject using the #Context annotation?

I'm new to JAX-RS and I'm trying to understand how the #Context annotation is supposed to work.
At the javadoc there is a list of six classes (Application, UriInfo, Request, HttpHeaders, SecurityContext, Providers). However I find code on the web that use the this annotation with other types, for example:
#GET
public String something(#Context HttpServletRequest req) {
}
Is there a list of supported types that can be used with this annotations? Does this list change between implementation of the standard?
I'm currently experimenting with Jersey and I'm worried that I'll write code that cannot be ported to other JAX-RS implementation.
The #Context annotation allows you to inject request/response context details into JAX-RS provider and resource classes. Injection can be performed into a class field, a bean property or a method parameter.
The following list summarizes all the types that can be injected using the #Context annotation, according to the JAX-RS 2.0 specification:
javax.ws.rs.core.Application
javax.ws.rs.core.HttpHeaders
javax.ws.rs.core.Request
javax.ws.rs.core.SecurityContext
javax.ws.rs.core.UriInfo
javax.ws.rs.core.Configuration
javax.ws.rs.container.ResourceContext
javax.ws.rs.ext.Providers
Except for Configuration and Providers, which
are injectable in both client and server-side providers, all the other types are server-side only.
The following types are available only when the application is deployed in a servlet container:
javax.servlet.HttpServletRequest
javax.servlet.HttpServletResponse
javax.servlet.ServletConfig
javax.servlet.ServletContext
JAX-RS 2.1 introduced other types that can be injected with #Context:
javax.ws.rs.sse.Sse
javax.ws.rs.sse.SseEventSink
Besides the standard types listed above, JAX-RS implementations, such as Jersey, RESTEasy and Apache CXF, might define their own types that can be injected using #Context.
Find below a quick description of each JAX-RS type available for injection:
Application: The instance of the application-supplied Application subclass can be injected into a class field or method parameter. Access to the Application subclass instance allows configuration information to be centralized in that class.
URIs and URI templates: UriInfo provides both static and dynamic, per-request information, about the components of a request URI.
Headers: HttpHeaders provides access to request header information either in map form or via strongly typed convenience methods. Response headers may be provided using the Response class.
Content negotiation and preconditions: 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.
Security context: The SecurityContext interface provides access to information about the security context of the current request. 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.
Providers: The Providers interface allows for lookup of provider instances based on a set of search criteria. This interface is expected to be primarily of interest to provider authors wishing to use other providers functionality. It is injectable in both client and server providers.
Resource context: The ResourceContext interface provides access to instantiation and initialization of resource or subresource classes in the default per-request scope. It can be injected to help with creation and initialization, or just initialization, of instances created by an application.
Configuration: Both the client and the server runtime Configurations are available for injection in providers (client or server) and resource classes (server only).
SSE events: SseEventSink represents the incoming SSE connection and provides methods to send events. Sse provides factory methods for events and broadcasters.
This post written by Arjan Tijms suggests that future versions of JAX-RS may have a stronger integration with CDI. So #Context may be deprecated and then removed in favor of #Inject:
JAX-RS 2.2
For some reason, one that has largely been lost in time, JAX-RS uses its own dependency injection system based on #Context instead of CDI's #Inject. While JAX-RS was updated at the last moment before its initial release to have some level of support for CDI, the fact that JAX-RS resources are not CDI beans has unnecessarily hold back the spec and has caused confusion even since JAX-RS was introduced in EE 6 (2009).
This changeover to CDI could possibly happen in 2 steps; in JAX-RS 2.2 everything that can now be injected by #Context should also be injectable using #Inject and JAX-RS resources would be CDI beans by default (perhaps unless explicitly disabled). At the same time #Context would be deprecated. In JAX-RS 3.0 #Context would then be actually removed.
The riveting JAX-RS specification defines all the standard types you can inject via #Context.
But if I were you, I would just consult the specific documentation of your chosen provider to see what is available.
For example, RESTEasy provides these values via #Context. Meanwhile, Jersey provides these. Obviously there will be overlap because of the standard context values.
The #Context annotation can be used to inject 12 objects. Here is a quick summary of each of them
HttpHeaders - HTTP header valuesand parameters
UriInfo - URI query parameters and path variables
SecurityContext - Gives access to security-related data for the given HTTP request
Request - Allows precondition request processing
ServletConfig - The ServletConfig
ServletContext - The ServletContext
HttpServletRequest - The HttpServletRequest instance for the request
HttpServletResponse - The HttpServletResponse instance
Application, Configuration, and Providers -> Provide information about the JAX-RS application, configuration and providers
ResourceContext - Gives access to resource class instances
All of these instances can be injected in the resource method
#Path("/")
public class EndpointResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getAllHttpHeaders(final #Context HttpHeaders httpHeaders){
// Code here that uses httpHeaders
}
}
or as a field:
#Path("/")
public class EndpointResource {
private final #Context HttpHeaders httpHeaders;
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getAllHttpHeaders(){
// Code here that uses httpHeaders
}
}
Here is a five part series answering the question What is #Conext used for?
To extend already provided answers: JAX-RS implementations usually provide a way to access the context. For RESTEasy it's ResteasyContext. The context can be listed by
ResteasyContext.getContextDataMap()
Keys of returned map can look like:
interface javax.ws.rs.core.Request
interface javax.ws.rs.core.HttpHeaders
interface javax.ws.rs.ext.Providers
class org.jboss.resteasy.plugins.server.Cleanables
class org.jboss.resteasy.core.PostResourceMethodInvokers
class org.jboss.resteasy.core.InternalDispatcher
interface javax.ws.rs.container.ResourceInfo
interface io.vertx.core.http.HttpServerResponse
interface io.vertx.core.Context
interface org.jboss.resteasy.spi.Registry
interface org.jboss.resteasy.spi.HttpRequest
interface org.jboss.resteasy.spi.ResteasyDeployment
interface javax.ws.rs.container.ResourceContext
interface org.jboss.resteasy.spi.Dispatcher
interface io.vertx.ext.web.RoutingContext
interface io.vertx.core.http.HttpServerRequest
interface io.vertx.core.Vertx
interface javax.ws.rs.core.Configurable
interface org.jboss.resteasy.spi.ResteasyAsynchronousContext
interface javax.ws.rs.core.SecurityContext
interface javax.ws.rs.core.Configuration
interface javax.ws.rs.core.UriInfo
interface org.jboss.resteasy.spi.HttpResponse

Categories

Resources