Instance of resource in Java rest api - java

I have a java rest api. What I want to know is this:
Say one specific client (e.g. person named X is using computer Y) makes three calls to the same uri. (e.g. https://stackoverflow.com/firstname/kasav/lastname/bere). Further, say the resource has a non-static counter.
class ResourceA{
int count = 0;
#Get
public Response service(){
count++;
//return count below
}
}
Now does the caller get the same response for all three calls:
1
Or does the caller get 1 for the first call, then 2 for the second call, then 3 for the third call.
For some of you this may be obvious, but not to me. Thanks for helping.

Assuming you are using something that follows JAX-RS spec correctly.
3.1.1 Lifecycle and Environment
By default a new resource class instance is created for each request to that resource. First the
constructor (see section 3.1.2) is called, then any requested
dependencies are injected (see section 3.2), then the appropriate
method (see section 3.3) 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.
As such the answer to your question is all callers will receive 1 as the class is initiated for each request.
See JSR-311 for the JAX-RS spec.

By default JAX RS resources are request scoped, means it create new instances for each request.
To process the multiple requests with the same instance of the resource you can mark the resource (class ResourceA in this case) with the annotation #Singleton.
Marking as Singleton will make the output of the ResourceA class as 1 for first request, 2 for second request and so on.

Related

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.

Shiro throws an UnavailableSecurityManagerException in custom JSON serialiser

I'm working on a REST API of a TomEE 7 based web app, which uses Shiro 1.3.2 for security. When an API request comes in, a SecurityManager and a Subject are created, and the latter is bound to a SubjectThreadState. I can call SecurityUtils.getSubject() anywhere in the endpoint code and the subject is always available.
However, problems arise when I try to do the same inside my custom JSON serialiser. It only serialises specific fields in some classes, so I register it on a per-field basis using this annotation:
#JsonSerialize(using = MySerialiser.class)
Long myRelatedItemId;
I wrote my serialiser based on the example code on this page under "2.7. #JsonSerialize". The serialiser needs to perform a cache lookup, and for that it has to have a Shiro subject. There is none because, thanks to the annotation above, I don't call the serialiser manually; instead Jersey calls it. This exception gets thrown (clarification: when I try to run SecurityUtils.getSubject() from the serialiser code):
org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.
at org.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123)
at org.apache.shiro.subject.Subject$Builder.<init>(Subject.java:627)
at org.apache.shiro.SecurityUtils.getSubject(SecurityUtils.java:56)
I have confirmed that everything works if I call something like ObjectMapper().writeValueAsString() manually from the API endpoint code. However, that is definitely not the proper way to do it, because then the endpoint would effectively send and receive strings instead of the objects they are meant to handle.
I don't understand much about the inner workings of Shiro or Jackson, but it seems like the serialisation is being performed inside another thread, where Shiro's SubjectThreadState doesn't exist. Although if threading really is the cause, then I cannot see why Thread.currentThread().getName() returns the same value both inside and outside the serialiser, as does Thread.currentThread().getId().
I have tried a vast number of things to no avail, including:
Upgrading to Shiro 1.4.0.
Upgrading Jackson from 2.7.5 to 2.9.7.
Saving the SecurityManager instance that is created at the start of the API call inside a static ThreadLocal variable of the serialiser class.
Writing my own implementation of MessageBodyWriter which, not surprisingly, is called in exactly the same fashion.
Setting the staticSecurityManagerEnabled parameter to true in the ShiroFilter configuration in my web.xml.
Can anyone suggest how I could make the SecurityManager (or Subject) visible to the serialiser, when it's running in a thread not started by my code (clarification: or, otherwise running in parallel and started by Jersey, as far as I can tell)? Thanks in advance.
Update:
This stack trace was taken inside the serialiser:
<mypackage>.MySerializer.serialize()
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField()
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields()
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize()
com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue()
com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize()
com.fasterxml.jackson.databind.ObjectWriter.writeValue()
com.fasterxml.jackson.jaxrs.base.ProviderBase.writeTo()
org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo()
org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo()
org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed()
org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo()
org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed()
org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo()
org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed()
org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo()
org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse()
org.glassfish.jersey.server.ServerRuntime$Responder.processResponse()
org.glassfish.jersey.server.ServerRuntime$Responder.process()
org.glassfish.jersey.server.ServerRuntime$2.run()
This one was taken in our interceptor class where the Subject is created and bound:
<mypackage>.MySecurityInterceptor.createSession()
sun.reflect.NativeMethodAccessorImpl.invoke0()
sun.reflect.NativeMethodAccessorImpl.invoke()
sun.reflect.DelegatingMethodAccessorImpl.invoke()
java.lang.reflect.Method.invoke()
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke()
org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed()
org.apache.openejb.monitoring.StatsInterceptor.record()
org.apache.openejb.monitoring.StatsInterceptor.invoke()
sun.reflect.GeneratedMethodAccessor111.invoke()
sun.reflect.DelegatingMethodAccessorImpl.invoke()
java.lang.reflect.Method.invoke()
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke()
org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed()
org.apache.openejb.core.interceptor.InterceptorStack.invoke()
org.apache.openejb.core.stateless.StatelessContainer._invoke()
org.apache.openejb.core.stateless.StatelessContainer.invoke()
org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod()
org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod()
org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke()
org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke()
com.sun.proxy.$Proxy279.getEntity()
org.openapitools.api.impl.MyApiServiceImpl.getEntity()
org.openapitools.api.MyApi.getEntity()
sun.reflect.NativeMethodAccessorImpl.invoke0()
sun.reflect.NativeMethodAccessorImpl.invoke()
sun.reflect.DelegatingMethodAccessorImpl.invoke()
java.lang.reflect.Method.invoke()
org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke()
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run()
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke()
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch()
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch()
org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke()
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply()
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply()
org.glassfish.jersey.server.ServerRuntime$2.run()
There are 46 more calls that are identical in both traces after that last line, so I excluded them. They contain a bunch of org.apache.catalina.core and org.glassfish.jersey.
Take a look at Shiro's Subject Thread Association doc

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. [...]

Interfere in Jersey REST life cycle

I have variant resources that all extend BaseResource<T>
#Component
#Path("/businesses")
public class BusinessResource extends BaseResource<Business>{
#GET
#Path({businessId}/)
public Business getBusiness(#PathParam("businessId") Integer businessId){..}
}
#Component
#Path("/clients")
public class ClientResource extends BaseResource<Client>{
#GET
#Path({clientId}/)
public Client getClient(#PathParam("clientId") Integer clientId){..}
}
I would like, that when there is a call to
/businesses/3, it will first go through a method that I will write which validates the T object and if everything is ok I will tell jersey to continue handling the resource.
Same goes for Client.
I can't use a regular servlet/filter - since it's being called BEFORE jersey servlet and I wouldn't know which resource is being called.
What is the best way to do it in Jersey?
Is there a place to interfere between knowing the method that jersey will invoke and the invokation?
There are 4 basic http methods in REST, namly GET, PUT, POST, DELETE.
Your annotation tells Jersey what method to call when a http request occurs. Jersey looks up the target URI in the request and matches it against your model. If the request is a http get it will execute the method annotiated with #Get from the class with the correct #Path annotiaton.
Usually you dont want to grant access to your resources in this annotated method directly. A common (may not perfect) way is to implement a DAO class that handles access to your resources, and of course does the validation before it returns the resource back to the #Get annotated method, which will itself only pass the resource to the client. So you will get another layer in your application between persisting (SQL, etc) and the client interface (Jersey).
You can use jersey 2.x ContainerRequestFilters with NameBinding. After having matched the resource, the bound filter will be executed prior to executing the method itself.
You can see the Jersey user guide, which states that it is possible:
Chapter 9.2.1.1 explains about PreMatching and PostMatching filters and chapter 9.4 chapter shows the execution order of jersey filters.
See my post for the implementation where I had the problem to make the filters with jersey 2 work.

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

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.

Categories

Resources