I've the following question:
ContainerRequestFilter is a singleton, but reading this:
Jaxrs-2_0 Oracle Spec
in chapter 9.2, they say:
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 9.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.
In the chapter 9.2, the HttpServletRequest is not mentioned.
So the question is: is it safe in terms of concurrency to inject the HttpServletRequest inside a custom ContainRequestFilter?
I mean this:
#Provider
#PreMatching
public class AuthenticationFilter implements ContainerRequestFilter {
#Context private HttpServletRequest request;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// This is safe because every thread call the method with its requestContext
String path = requestContext.getUriInfo().getPath(true);
// Is this safe? The property request is injected by using #Context annotation (see above)
String toReturn = (String)request.getAttribute(name);
[...]
}
I did some empirical tests on my IDE in debug mode, sending with two different browsers two different and concurrent requests and it seems to work well; I noticed that the filter's instance is ever the same (it's a singleton), but the injected HttpServletRequest is different in the two cases.
I readed even this thread: How to access wicket session from Jersey-2 request filter? and it seems that my tests are confirmed.
But I still have doubts.
Confirm?
Yes it's safe. To understand the problem, you should understand how scopes work. In any framework that deals with scopes (and injection), the feature is implemented similarly. If an object is in a singleton scope and another object in a lesser scope needs to be injected, usually a proxy of the object will be injected instead. When a call is made on the object, it's actually a call on the proxy.
Though the spec may not mention the HttpServletRequest specifically, most JAX-RS implementation have support for this. With Jersey in particular, if this was not possible (meaning the object is not proxiable), then you would get an error message on startup with something like "not within a request scope". The reason is that the ContainerRequestFilter is created on app startup, and all the injections are handled at that time also. If the HttpServletRequest was not proxiable, it would fail to inject because on startup, there is no request scope context.
To confirm that it is not the actual HttpServletRequest and is a proxy, you can log the request.getClass(), and you will see that it is indeed a proxy.
If you are unfamiliar with this pattern, you can see this answer for an idea of how it works.
See Also:
Injecting Request Scoped Objects into Singleton Scoped Object with HK2 and Jersey
Related
Can anyone explain to me the difference between calling resourceResolver by annotating #ScriptVariable and by annotating #SlingObject? In what context do they behave differently?
The key difference is in the way the object is retrieved. #ScriptVariable and #SlingObject are injector-specific annotations. This means that you can use them to instruct Sling Models to use a particular injector.
The injector that recognises the #ScriptVariable annotation can inject objects available as Scripting Variables. In case ot the resourceResolver, it should be the one associated with the request. Same as slingRequest.getResourceResolver().
Looking at the code, the injector that kicks in on fields annotated with #SlingObject is a bit more interesting in that it will inspect the adaptable (from which your Sling Model is being adapted) and obtain the resolver accordingly:
If the adaptable is a Resource, it'll return resource.getResourceResolver(), i.e. the resolver originally used to load the resource. This may be quite aribtrary.
If the adaptable is a SlingHttpServletRequest, it'll return request.getResourceResolver(), i.e. the resolver instantiated by Sling in association with the request and the session of the user issuing the request.
If the adaptable itself is a ResourceResolver, it will be returned directly.
In some cases, the difference between the three will be negligible, but sometimes it will be important which resolver you choose. If your model is, for example, supposed to be used outside the scope of a request (imagine it's instantiated by an OSGi service that runs on a schedule and there's no incoming request), you'll be better off using resource or resourceResolver as an adaptable.
What is the correct scope for a DAF pipeline servlet component used for REST services (like ActorServlet)? Should it be set to global or request?
From the ATG Documentation:
If a component’s $scope property is not explicitly set, it automatically has global scope.
Looking at the ActorServlet in the Component Browser in dynadmin it shows that there is no explicit scope set so it should indicate it is global scope by default.
Looking into this a bit more, the ActorServlet (which is the component of the RestPipelineServlet) extends the the PipelineableServletImpl which implements the PipelineableServlet interface. Here there is an abstract method passRequest which forms part of the actual pipeline 'chain' being executed.
public abstract void passRequest(ServletRequest paramServletRequest, ServletResponse paramServletResponse)
throws IOException, ServletException;
This means you will always have access to the current request. In the PipelineableServletImpl it internally calls the service method.
public void service(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws IOException, ServletException {
//Insert your logic here
passRequest(pRequest, pResponse);
}
You would normally override the service method and add your own logic in there but still have access to the current request which should indicate to you that, as long as the rest of your variables are thread safe, specifying your Pipeline Servlet as global scope is the correct way to go.
I'm trying to add a RESTful web service with RESTeasy to our application running on JBoss 7.x, using Seam2.
I wanted to use as little Seam as possible, but I need it for Dependancy Injection.
My REST endpoints are as follows:
#Name("myEndpoint")
#Stateless
#Path("/path")
#Produces(MediaType.APPLICATION_JSON+"; charset=UTF-8")
public class MyEndpoint {
#In private FooService fooService;
#GET
#Path("/foo/{bar}")
public Response foobar(#CookieParam("sessionId") String sessionId,
#PathParam("bar") String bar)
{ ... }
}
I'm using a class extending Application. There is no XML config.
I can use the web service methods and they work, but I always get an IllegalStateException:
Exception processing transaction Synchronization after completion: java.lang.IllegalStateException: No event context active
Complete StackTrace
I did try everything in the documentation, but I can't get it away. If I leave out the #Stateless annotation, I don't get any Injection done. Adding #Scope doesn't do jack. Accessing the service via seam/resource/ doesn't even work (even without the Application class with #ApplicationPath).
It goes away if I don't use Dep. Injection, but instead add to each and every method
fooService = Component.getInstance("fooService");
Lifecycle.beginCall();
...
Lifecycle.endCall();
which isn't really a good solution. Nah, doesn't work either...
I have resolved the issue. For some reason (still not sure why, maybe because I tried to use Annotations and code exclusivly and no XML config), my REST service was availiable under a "non-standard" URL.
Usually it'd be something like "/seam/resources/rest".
Anyway, if you have a "custom" path, Seam doesn't know it should inject a context. You need to add <web:context-filter url-pattern="something" /> to your component.xml.
Specifically we already had this tag, but with the attribute regex-url-pattern and I extended it to match the REST URL.
We are using CXF 2.4.2 to create a RESTful interface. I have a bean resource class that is defined as follows:
#Path("/mypath")
public class MyResource {
#GET
#Path("/myget")
public final Response myGet() { ... }
Does anyone know why the method can't be final in order to access the resource?
Sometimes JAX-RS is implemented in such a way, that instead of original class (that we create) JAX-RS is using proxy class which inherits from our class. Since final method cannot be overriden, usage of final methods is prohibited.
Usage of proxy enables adding to JAX-RS framework various interceptors, providers, etc. Obviously the same functionality can be obtain without using proxy, so other providers might allow usage of final methods.
The specification does not say anything about final methods.
Side note: very often usage of final method is a bad idea. Sometimes even if we think that given method should not be overriden, it may appear that is necessary. Even Java creators made a few such mistakes. Obviously there are classes, which methods should not be overriden (String), but there are not a lot of them.
I have a Jersey rest webservice that runs on tomcat 6. I have a #Post method that consumes Multipart:
#Path("identify")
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_XML)
public String identifyReception(com.sun.jersey.multipart.MultiPart multiPart) throws Exception {
I would like to get the client IP address inside this method. I found out that you can use #Context HttpServletRequest inside Get method. But in post method I need the multipart input argument. I have also found out that tomcat does not support Servlet specification...
Is there another way I can do it?
I found out that you can use #Context HttpServletRequest inside Get method. But in post method I need the multipart input argument.
I don't think the two are mutually exclusive. Let your method take two arguments (I don't think it matters what order they're in) and annotate one of them with #Context. I believe that will work whether it's a get, post, whatever. You could also just annotate a field with #Context and Jersey will initialize it for you before it calls your #GET method.