Jersey 2 - Request scoped binding vs Singleton binding - java

I'm learning Jersey and trying to build a rest api. But I'm having a hard time understanding the difference between various bindings - bind() , AbstractBinder(), bindFactory() and also the scopes - RequestScoped , Singleton and PerLookup. What are the differences between them and when to use which one?
e.g. Say I have some request specific data passed into the request header. I want to use this data multiple times (say in resource classes, DAOs etc) during the request processing. What I figured is that I'll use a request filter and extract the data using the ContainerRequestContext and store it to some class. But i'm not able to figure out how to bind this class so that I can access it later. Which binding to use in this case?

bind() and bindFactory() are methods in the AbstractBinder class that you use to bind your services in the registry. The AbstractBinder is what you register with Jersey so that it knows to configure all your bindings. You use bind() to bind the service itself. You use bindFactory() to bind the service using a Factory (or Supplier in 2.26+) to create the service.
RequestScoped means that the service is scoped to the request, meaning that it will be the same instance for the lifetime of the request. You would use this scope when the service is dependent on information tied to a request, like request headers.
Singleton scope means that there will only be one instance of the service for the lifetime of the application. You would use this scope when the service can safely be used at anytime without being tied to any request.
PerLookup means that a new instance of the service will be created every time it is looked up, either directly through the ServiceLocator (or InjectionManager in 2.26+) or via an #Inject (or other injection) annotation. Even though this is the default scope, the RequestScope and Singleton scope would be more appropriate for most of the use cases in the context of a Jersey application.
For your use case where you want to get information from the request context and use it in the service, you would use a RequestScoped service and use a bindFactory() with a Factory (or Supplier in 2.26+) and inject the request context into the Factory and use the context to create your service. You can see more explanation in How to inject an object into jersey request context?. If you are using Jersey 2.26+, you'll also want to read Jersey 2.26: register #Inject in ResourceConfig bindFactory cannot convert Factory to Supplier

Related

EJB : understanding how container choose bean

I'm trying to understand how statefull beans works (I read the theoretical part and I know the difference between statfull and statelss beans ...), for that reason I created a statefull bean and a rest API to access it.
I find out that the container create/instantiate a new bean for every request.
then I used a servlet to access the same statfull bean, and this time the container crate just one bean that serves all requests.
So my questions are :
why does the container create many bean for rest API ?? I know that it consider each request as a separate client but how it knows, since rest API or servlet are accessed using http requests??
why it consider request when it comes from servlet as one client?? (therefor it create one bean)
in my case (doing test localy) how to force the container to create more beans (how to simulate more than one client) when using servlet.
Thank you in advance
I checked the specs, but I could not find something about this. But that seems reasonable:
Somebody must take care about the SFSB instance, closing it when done.
When exposing an EJB business method of a SFSB as REST service, a generic servlet is used. The only scope available is the request scope of a single (stateless) HTTP call, so after the call is done, the generic servlet should close the SFSB.
The servlet has an explicit lifecycle. An injected EJB is create during initialisation of the servlet and can be closed on destroy.
You can lookup new SFSB instances with every HTTP session created, using the session context for subsequent calls on this session and closing the SFSB when the matching session is closed.

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

Spring run method before starting endpoints

Is it possible to call some method while Spring is being initialized - after database connection is started but before #RestController endpoints are started (available to send requests)?
I need to send some database requests (using JpaRepository) before REST endpoints are ready.
I tried to find similiar post but I wasn't able to. I found annotation #PostConstruct or interfaces CommandLineRunner and ApplicationListener<ContextRefreshedEvent> but I think all of then are called after endpoints are started? Or am I wrong?
#PostConstruct is called after a bean is completely constructed but before it is "put into service"--which, in the case of a controller, means before it starts serving requests. (In the case of a service bean, this would mean before it is wired into any other beans.)
Note that it's best to use constructor injection to provide dependencies to your bean, but it may still be sensible to do database queries in #PostConstruct to avoid heavy operations in an actual constructor.

Scoped web services

The official Axis manual states that:
Scoped Services
Axis supports scoping service objects (the actual Java objects which
implement your methods) three ways. "Request" scope, the default, will
create a new object each time a SOAP request comes in for your
service. "Application" scope will create a singleton shared object to
service all requests. "Session" scope will create a new object for
each session-enabled client who accesses your service. To specify the
scope option, you add a to your service like this (where
"value" is request, session, or application):
Is there any way to specify that using annotation defined by the standard JAX-WS ?
JAX-WS don't provide this out-of-the-box. There is JAX-WS commons, where you can find these annotations:
#HttpSessionScope that allows the creation of an instance of the service class per session. (Equivalent of Session scope).
#ThreadScope that allows the creation of an instance of the service class per each thread request. (Equivalent of Request scope). Note that these beans are reused among requests.
By default, the service class is created per application context.

Injecting using request scope and threads

I have some bussines classes that get injected some dependencies that are provided using servlet request scope.
The problem is that I want to use that bussines classes in some threads that outlive the servlet request.
Whats the most transparent way to do that?
If you are using Spring (which, by the terms you use to describe your problem, you seem to be using), you can use an AOP scoped-proxy for your request-scoped object, and inject this proxy into the objects that outlive the servlet request. The scoped-proxy will take care of using the right instance everytime you access it.
Well,
I'm not sure if I get your problem. I think there is problem with architecture itself, but however this could help you:
Guice module
bind(Bussines.class).annotatedWith(Names.named("request")).to(Bussines.class).in(RequestScoped.class);
bind(Bussines.class).annotatedWith(Names.named("session")).to(Bussines.class).in(SessionScoped.class);
bind(Bussines.class).annotatedWith(Names.named("application")).to(Bussines.class).asEagerSingleton();
Usage
#Inject #Named("request")
private Bussines bussines; //inject a new bussines class every request
#Inject #Named("session")
private Bussines bussines; //inject a new bussines class each session
//This is little bit tricky, cuz Bussines is stored in session. In Stage.PRODUCTION are all injection created eagerly and there is no session at injection time. Session binding should be done in lazy way - inject provider and call bussinesProvider.get() when em is needed;
#Inject #Named("application")
private Bussines bussines; //inject singleton
Also you can use Private modules to bind different scoped objects to a class. Don't forget to expose it.
I see 3 options:
You could add the information you need to an object that has a larger scope like application or session scope
You could persist the information in a file or the database and look it up later
You could save the information on the thread or use a thread scope: http://code.google.com/p/google-guice/issues/detail?id=114
I may not suggest you directly use or inject HttpServletRequest at business bean which is not in request scope . because this will break up app layers. if you want the value from the request or request header, then you can pass value to object to pass to the business layer, because otherwise, it is not secure, and generally, app will apply some security interceptor at that request scope , but if you directly inject to other layer , then it jump over and the interceptor may be skipped... this way also break the encapsulation and obvious is anti-pattern.

Categories

Resources