Jersey REST Server: instantiating resource classes - java

A tutorial on the Jersey REST server [1] says of the Jersey servlet:
This servlet analyzes the incoming HTTP request and selects the correct class and method to respond to this request. This selection is based on annotations in the class and methods.
When the servlet "selects the correct class and method", does it re-instantiate the class every time? Or does it keep one instance of every resource class?
This would seem to matter because, if these resources classes have references to objects that store application-wide state, these state objects would be re-instantiated along with the resources, and would not end up storing state data correctly.
[1] http://www.vogella.com/articles/REST/article.html#restjersey

Jersey will establish a new instance of each class per request unless you annotate the class with #Singleton.
See: https://jersey.java.net/documentation/latest/jaxrs-resources.html#d0e2331

Actually according to this post default annotation type is change from singleton to per-request. Which means before one instance is used for every request but now create new class object for per-request. If you postwant to change it you can use resourceFactory annotation.
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#ResourceFactory(SingletonProvider.class)
public #interface Singleton {}
Also you can check this link for com.sun.jersey.spi.resource JavaDoc

Related

what is default http method in rest web services

Is there any default method for java restful web services.
If I dont annotate my root resource class method with any html method annotation then will it match the upcoming get request to that method
#Path("xyz")
class abc
{
String methodName(String name)
{
//processing
}
}
In this case if I have an get request , then will this method be treated as resource .
I read that when our resource methods are annotated with #Path and not with #AnyHttpMehtod then its a sub resource locator. I want to know when we dont have any http method annotation then will there be some default behavior.
From the documentation:
By default, the JAX-RS runtime will automatically support the methods HEAD and OPTIONS if not explicitly implemented. For HEAD, the runtime will invoke the implemented GET method, if present, and ignore the response entity, if set. For OPTIONS, the Allow response header will be set to the set of HTTP methods supported by the resource. In addition, the JAX-RS runtime will return a Web Application Definition Language (WADL) document describing the resource; see https://wadl.dev.java.net/ for more information.
source

When to use #Singleton annotation of Jersey?

I am developing a RESTful Web Service and while reading the Jersey documentation I came across an annotation #Singleton
In my web service I am mostly returning data based on the unique keys provided as parameter.
An analogy would be return all the information of a Student when the Student_Id is passed.
So my question is when #Singleton would be suited in such kind of Web Services?
As per documentation for #RequestScoped
If the resource is used more than one time in the request processing, always the same instance will be used.
Then in that case we should not bother to use #Singleton right?
Also what could be the use cases where we have to make a new instance for every request?
I did have a look at this post but my question was not answered.
By default Jersey creates a new instance of the resource class for every request. So if you don't annotate the Jersey resource class, it implicitly uses #RequestScoped scope. It is stated in Jersey documentation:
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 is returned more
times during the matching. In this situation only on instance will
server the requests.
Most cases you use this default setting so you don't use #Singleton scope. You can also create a singleton Jersey resource class by using #Singleton annotation. Then you need to register the singleton class in the MyApplication class, e.g.,
#Path("/resource")
#Singleton
public class JerseySingletonClass {
//methods ...
}
public class MyApplication extends ResourceConfig {
/*Register JAX-RS application components.*/
public MyApplication () {
register(JerseySingletonClass.class);
}
}
Came along this question, because for the first time I had a use case for not using #Singleton annotation.
Singleton is a design pattern, you should use it if:
The object you are "singletonizing" keeps a state that must be shared and kept unique (example: a global counter)
Generally, I design REST API without keeping a state, everything is handled in the method (full closure): so generally all my resources are singletons (use case: better performance)
That said, today I found this use case for not using Singleton:
#Path("/someendpoint/{pathparam}/somethingelse/")
//#Singleton
public class MyResource {
#PathParam("pathparam")
private String pathparam;
}
Using this, I'm bounding the path param to my instance, so it must be RequestScoped.
Generally, I'd have put #PathParam annotation in every method, so #Singleton would have been right on the class.
I'm not sure about the performances however, creating and destroying an object isn't a free operation
In most cases default scope #RequestScoped should be sufficient for your needs.
#Singleton may hold state. I had the problem when my endpoint was annotated as #Singleton so it reused the same EntityManager during concurrent calls. After removing #Singleton, during concurrent calls, different EntityManager object instances are used. If endpoint calls are subsequent, it may be that previous/old EntityManager will be used. - Jersey, Guice and Hibernate - EntityManager thread safety
There is actually a use case specified in the Jersey 2 manual for using the SseBroadcaster when serving Server-Sent events, it is covered in this provided example
The BroadcasterResource resource class is annotated with #Singleton annotation which tells Jersey runtime that only a single instance of the resource class should be used to serve all the incoming requests to /broadcast path. This is needed as we want to keep an application-wide single reference to the private broadcaster field so that we can use the same instance for all requests. Clients that want to listen to SSE events first send a GET request to the BroadcasterResource, that is handled by the listenToBroadcast() resource method.
Using the #Singleton, The application will only contain one SseBroadcaster for all incoming requests, one such broadcaster is enough to serve multiple clients, so it only needs to be instantiated once!
JAX-RS SSE API defines SseBroadcaster which allows to broadcast individual events to multiple clients.

How do you configure a JAX-RS MessageBodyWriter on a per-request basis?

Essentially, I have a MessageBodyWriter that writes objects as JSON, and I'd like to be able to control some aspects of the output based on which resource method handled the request. However, the default lifecycle of #Provider classes is singleton (one per JVM), so I can't inject an instance of some configuration object. This leaves me with 2 obvious workarounds:
Use custom annotations: Each call to writeTo(...) includes the list of annotations on the method that was invoked, so I could check for the existence of some annotation. However, JAX-RS methods are already pretty laden with metaprogramming.
Use a ThreadLocal property map: Assuming one request per thread, but this approach breaks encapsulation a bit. The resource methods needs to be aware that there is some other class out there, looking for this map.
Is there a way to change the lifecycle of the Provider itself? I am using Jersey.
Not sure why you need a MessageBodyWriter Provider with per-request basis. If you just want to distinguish which methods are with JSON ouput and which are not, then jersey-json does already support.
And although the #Provider is singleton. You still can use per-request object within it like below.
#Provider
public class StViewProcessor implements ViewProcessor<ST> {
......
#Context
HttpServletRequest request;
public void writeTo(ST st, Viewable viewable, OutputStream out)
throws IOException {
System.out.println(request.getRequestURI());
...
}
}
And if you want to inject your instance per request, you can have a look at PerRequestTypeInjectableProvider. Here is a link about it.
The JAX-RS 1.1 spec requires that implementations support singleton providers and allows support for other lifecycles but doesn't suggest anything else along those lines. As far as I'm aware, pure Jersey doesn't support anything beyond singletons. With the jersey-spring contrib module, you get support for using Spring as Jersey's IoC container (where it gets its resource and provider instances from). I know Spring supports multiple lifecycles, including request, but I'm not sure if support for that is built into jersey-spring.

How to set objects on Spring 3.1 MVC controller from an interceptor?

I'm having a couple of issues related to interceptors since upgrading to 3.1. In version 3.0.x and earlier I used the following pattern to intercept Spring MVC controllers:
Create an interface called something like RoleAware which defines one or more setters.
Have one or more controllers implement the interface
Register a new global interceptor which does a "handler instanceof RoleAware" check in the preHandle
If the interceptor is an instanceof RoleAware, then set one or more objects on the implementing controller
The first issue is that something changed in 3.1 so the instanceof check fails. I've fixed this by using the new explicit elements in my servlet context configuration. Not a big deal and a bit cleaner approach than the instanceof check.
The second issue is that when I attempt to cast the handler (Controller) to my RoleAware interface I get a ClassCastException.
I'd like a solution that will enable me to continue to arbitrarily set objects on the intercepted controllers. For example, set a Role object on any Controllers that are intercepted. Also, I'd like to know more about the changes in 3.1 that is causing this to break.
The reference doc says:
When using the RequestMappingHandlerMapping the actual handler is an
instance of HandlerMethod which identifies the specific controller
method that will be invoked.
So I guess that you should just cast the handler to HandlerMethod, call its getBean() method, and check is the returned bean is an instance of RoleAware.
Not tested though. You could try using a debugger to inspect the handler argument and see what it is if it is neither the handler itself, nor the HandlerMethod.

Passing an object from JSP to Spring controller

I created a class named Person. Then I pass an object of this class via Spring controller to JSP page, say abc.htm.
Now I want it to transfer back from abc.htm to another controller.
How could I do that?
Also tell me if any other class object (say Address class object) uses that person object as parameter, then how would I pass that Address class object to the controller.
I am very confused, please help me.
After the page is rendered you are no longer in the "Java realm", so you don't have your objects. You can rebuild them based on the parameters that are sent back in the next request.
This is called "binding". In Spring MVC this is done automatically (more or less) if you are using the <form:x> tags. Then in your controller your objects will be accessible as method attributes:
#RequestMapping(..)
public String foo(YourObject object) {..}
You might need a #ModelAttribute annotation if the name of your param and the one in the JSP are not the same. The MVC docs write:
Command or form objects to bind parameters to: as bean properties or fields, with customizable type conversion, depending on #InitBinder methods and/or the HandlerAdapter configuration. See the webBindingInitializer property on AnnotationMethodHandlerAdapter. Such command objects along with their validation results will be exposed as model attributes by default, using the non-qualified command class name in property notation. For example, "orderAddress" for type "mypackage.OrderAddress". Specify a parameter-level ModelAttribute annotation for declaring a specific model attribute name.
I'd suggest you review the PetClinic Sample Application to see how this works in practice.

Categories