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

Romain Manni-Bucau rmannibucau at gmail.com
Thu Sep 8 08:28:59 EDT 2016


2016-09-08 14:21 GMT+02:00 arjan tijms <arjan.tijms at gmail.com>:

> 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.
>
>
ok, was not clear: point with AuthModule is it is not required to be in the
servlet chain at all (can be before), that's why i pointed out it was maybe
another topic and a small missing integration between 2 specs.


> 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/263abae3/attachment-0001.html 


More information about the cdi-dev mailing list