[cdi-dev] Which version of HttpServletRequest is injected?

arjan tijms arjan.tijms at gmail.com
Thu Sep 8 08:21:56 EDT 2016


Hi,

Sorry, forget the AuthModule for now ;) I just put it there because it's
often forgotten that it also gets to see the request and can wrap it, but
for a change (I know, it's rare with me ;)) the issue here is primarily
unrelated to auth.

Kind regards,
Arjan Tijms



On Thu, Sep 8, 2016 at 2:14 PM, Romain Manni-Bucau <rmannibucau at gmail.com>
wrote:

> Well supposes @Current means something for the component getting the
> injection, I can see where you go starting from AuthModule but more your
> browse the chain less it makes sense IMO -> maybe something to work on auth
> side more than CDI?
>
> That said CDI has a notion for conversions which is to define a provided
> filter. Maybe that's the easiest here: a user could define one or multiple
> filters ("CDI Filter" or whatever name) which would set CDI position in the
> filter chain, defining it N times would update "current" request and the
> produces one so we keep current default and enable the user to control it
> himself finely when needed.
>
>
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://blog-rmannibucau.rhcloud.com> | Old Wordpress Blog
> <http://rmannibucau.wordpress.com> | Github
> <https://github.com/rmannibucau> | LinkedIn
> <https://www.linkedin.com/in/rmannibucau> | Tomitriber
> <http://www.tomitribe.com> | JavaEE Factory
> <https://javaeefactory-rmannibucau.rhcloud.com>
>
> 2016-09-08 14:10 GMT+02:00 arjan tijms <arjan.tijms at gmail.com>:
>
>> Hi,
>>
>> I see what you mean.
>>
>> There's perhaps 2 solutions.
>>
>> 1. Specify @Inject HttpServletRequest to inject the current one (the top
>> one from the stack)
>> 2. Let @Inject HttpServletRequest as it's now (you get an arbitrary one,
>> which is hopefully at least always the same for a given server), and
>> introduce a qualifier @Current orso.
>>
>> I don't think you'd ever need @Inject @Web(FilterX.class) Request, which
>> would mean searching back through the stack. If users would want that, they
>> have to make their own producer.
>>
>> What we could do now is:
>>
>> AuthModule
>> |
>> |
>> Filter1 (calls) ---> BeanX.foo() #1
>> |
>> |
>> Filter2
>> |
>> |
>> Servlet1 (calls) ---> BeanX.foo() #2
>> |
>> |
>> (forward) ---> Servlet2 (calls) ---> BeanX.foo() #3
>>
>>
>>
>> If BeanX is injected with @Inject HttpServletRequest or
>> @Inject @Current HttpServletRequest, then:
>>
>>
>> In #1, BeanX.foo() sees the HttpServletRequest as it was passed in to
>> Filter1
>>
>> In #2, BeanX.foo() sees the HttpServletRequest as it was passed in to
>> Servlet1
>>
>> In #3, BeanX.foo() sees the HttpServletRequest as it was passed in to
>> Servlet2
>>
>>
>>
>> Since the request processing is strictly sequential here, a given thread
>> always has the concept of the request that was passed it to the
>> module/filter/servlet that's highest up the call stack. That one would IMHO
>> be the most logical one that you want to work with.
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> On Thu, Sep 8, 2016 at 1:53 PM, Romain Manni-Bucau <rmannibucau at gmail.com
>> > wrote:
>>
>>> AFAIK the server propagates by designt he request/response pair so even
>>> if there is a way to know which one it is at each moment you still have the
>>> issue you don't know what @Inject Request; means. @Inject
>>> @Web(FilterX.class) Request; is possible but not sure the real meaning and
>>> IMO it breaks the loose coupling of CDI so not sure it does worth to
>>> spec-ed it.
>>>
>>>
>>> Romain Manni-Bucau
>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>> <https://blog-rmannibucau.rhcloud.com> | Old Wordpress Blog
>>> <http://rmannibucau.wordpress.com> | Github
>>> <https://github.com/rmannibucau> | LinkedIn
>>> <https://www.linkedin.com/in/rmannibucau> | Tomitriber
>>> <http://www.tomitribe.com> | JavaEE Factory
>>> <https://javaeefactory-rmannibucau.rhcloud.com>
>>>
>>> 2016-09-08 13:31 GMT+02:00 arjan tijms <arjan.tijms at gmail.com>:
>>>
>>>> Hi,
>>>>
>>>> On Thu, Sep 8, 2016 at 1:09 PM, Romain Manni-Bucau <
>>>> rmannibucau at gmail.com> wrote:
>>>>
>>>>> Hit that issue as well several times.
>>>>>
>>>>> It is more vicious than it looks like IMO cause CDI will *never* get
>>>>> *the* right request for everybody, it is as simple as that. Any part of the
>>>>> app can rely on the wrapper level N (of course N being different for each
>>>>> mentionned parts of the app).
>>>>>
>>>>
>>>> What I was thinking, but maybe I'm wrong, is that the application never
>>>> "just" wraps the request and uses it for itself. It always passes it to the
>>>> container, which then passes it on to the next Filter, Servlet, or
>>>> whatever. So at that point the container code has the opportunity to store
>>>> the request as being the "current" one.
>>>>
>>>> E.g. if you do:
>>>>
>>>> RequestDispatcher dispatcher = servletContext().getRequestDis
>>>> patcher(...);
>>>> dispatcher.forward(wrap(request), response);
>>>>
>>>> Then the RequestDispatcher, which is a container class, receives the
>>>> wrapped request and can make it available.
>>>>
>>>> The other way around, eventually every AuthModule, Filter or Servlet
>>>> has to be called by the container at some point. E.g. the "protected void
>>>> service(HttpServletRequest req, HttpServletResponse resp)" is called by the
>>>> container.
>>>>
>>>> So just before the container invokes the HttpServlet#service method,
>>>> the container can store the request, and CDI (via an SPI) can pick it up
>>>> from there.
>>>>
>>>> That way in every context you can always have the *current* request
>>>> (the request that's passed in to the last Servlet or Filter call on the
>>>> stack).
>>>>
>>>> Kind regards,
>>>> Arjan Tijms
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>> Best CDI can do is to provide the request it has (already the case and
>>>>> cost pretty much nothing) and enable the user to produces very easily its
>>>>> own request from its filter (or equivalent) for its usage IMO - which is
>>>>> IMO already doable but maybe there is another shortcut we can introduce I
>>>>> didnt think about. If you look one step further any web framework built on
>>>>> top of CDI does it and therefore runs in a well known context.
>>>>>
>>>>>
>>>>> Romain Manni-Bucau
>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>>>> <https://blog-rmannibucau.rhcloud.com> | Old Wordpress Blog
>>>>> <http://rmannibucau.wordpress.com> | Github
>>>>> <https://github.com/rmannibucau> | LinkedIn
>>>>> <https://www.linkedin.com/in/rmannibucau> | Tomitriber
>>>>> <http://www.tomitribe.com> | JavaEE Factory
>>>>> <https://javaeefactory-rmannibucau.rhcloud.com>
>>>>>
>>>>> 2016-09-08 13:03 GMT+02:00 arjan tijms <arjan.tijms at gmail.com>:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> On Thu, Sep 8, 2016 at 12:40 PM, Martin Kouba <mkouba at redhat.com>
>>>>>> wrote:
>>>>>>
>>>>>>> that's a good question. In Weld, the request object is captured
>>>>>>> during request context activation, i.e. during
>>>>>>> ServletRequestListener.requestInitialized() notification and before
>>>>>>> any filter or servlet is invoked. So wrappers are ignored and the
>>>>>>> original/first request is used.
>>>>>>>
>>>>>>
>>>>>> Indeed, although do note that some servers (Liberty and WebLogic I
>>>>>> think) send the ServletRequestListener.requestInitialized()
>>>>>> notification rather late, and do that after the application already has
>>>>>> seen the request and has had a chance to wrap it. This by itself is a
>>>>>> separate problem. So on these servers, Weld would receive an early request
>>>>>> but not necessarily the earliest.
>>>>>>
>>>>>>
>>>>>>> But TBH I don't think we can fix this easily as I'm not aware of any
>>>>>>> portable way to listen for "wrapping actions".
>>>>>>>
>>>>>>
>>>>>> This would have to happen with Server specific code I guess, just as
>>>>>> Weld now requires an SPI to obtain the current principal for injection.
>>>>>>
>>>>>> You could say that the Servlet container could store the request
>>>>>> "somewhere" on a stack structure, just before it invokes the
>>>>>> ServerAuthModule, Filter, Servlet and anything else I may have forgotten,
>>>>>> and then when control flows back to each Servlet, Filter, etc unwind that
>>>>>> stack.
>>>>>>
>>>>>> At the very least the spec for now should perhaps clarify this?
>>>>>>
>>>>>> Kind regards,
>>>>>> Arjan Tijms
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> Martin
>>>>>>>
>>>>>>> Dne 8.9.2016 v 11:02 arjan tijms napsal(a):
>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> The CDI spec defines a built-in bean for the type
>>>>>>>> HttpServletRequest. In
>>>>>>>> 3.8 it says:
>>>>>>>>
>>>>>>>> "A servlet container must provide the following built-in beans, all
>>>>>>>> of
>>>>>>>> which have qualifier @Default:
>>>>>>>>
>>>>>>>> a bean with bean type javax.servlet.http.HttpServletRequest,
>>>>>>>> allowing
>>>>>>>> injection of a reference to the HttpServletRequest"
>>>>>>>>
>>>>>>>> An HttpServletRequest however can be wrapped multiple times and by
>>>>>>>> multiple artefacts. I.e. by a ServerAuthModule, Filter and a
>>>>>>>> RequestDispatcher.
>>>>>>>>
>>>>>>>> The question now is; which version of the HttpServletRequest is
>>>>>>>> supposed
>>>>>>>> to be injected?
>>>>>>>>
>>>>>>>> * The first one in the chain?
>>>>>>>> * The last one in the chain?
>>>>>>>> * The current one at a given point in the chain?
>>>>>>>>
>>>>>>>> A little bit of experimenting seems to indicate it's now often "one
>>>>>>>> of
>>>>>>>> the first ones", e.g. the one that happened to be current when e.g.
>>>>>>>> a
>>>>>>>> ServletRequestListener that initialises a specific CDI
>>>>>>>> implementation is
>>>>>>>> called.
>>>>>>>>
>>>>>>>> I think this is a little confusing, as working with an injected
>>>>>>>> request
>>>>>>>> can now totally ignore the request wrapping that has been done and
>>>>>>>> break
>>>>>>>> an application badly.
>>>>>>>>
>>>>>>>> Thoughts?
>>>>>>>>
>>>>>>>> Kind regards,
>>>>>>>> Arjan Tijms
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> cdi-dev mailing list
>>>>>>>> cdi-dev at lists.jboss.org
>>>>>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>>>>>
>>>>>>>> Note that for all code provided on this list, the provider licenses
>>>>>>>> the code under the Apache License, Version 2 (
>>>>>>>> http://www.apache.org/licenses/LICENSE-2.0.html). For all other
>>>>>>>> ideas provided on this list, the provider waives all patent and other
>>>>>>>> intellectual property rights inherent in such information.
>>>>>>>>
>>>>>>>>
>>>>>>> --
>>>>>>> Martin Kouba
>>>>>>> Software Engineer
>>>>>>> Red Hat, Czech Republic
>>>>>>>
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> cdi-dev mailing list
>>>>>> cdi-dev at lists.jboss.org
>>>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>>>
>>>>>> Note that for all code provided on this list, the provider licenses
>>>>>> the code under the Apache License, Version 2 (
>>>>>> http://www.apache.org/licenses/LICENSE-2.0.html). For all other
>>>>>> ideas provided on this list, the provider waives all patent and other
>>>>>> intellectual property rights inherent in such information.
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/cdi-dev/attachments/20160908/32f74a4b/attachment-0001.html 


More information about the cdi-dev mailing list