Hi,

On Thu, Sep 8, 2016 at 2:14 PM, Martin Kouba <mkouba@redhat.com> wrote:
The best solution might be to let the servlet container provide the beans for all the servlet artifacts (HttpServletRequest, HttpSession and ServletContext).

+100 for that.

Several issues were already created for that in the past, but to my understanding it was misunderstood by some in the Servlet EG and subsequently closed. See https://java.net/jira/browse/SERVLET_SPEC-116

Specifically this comment was a little problematic:

GW> More over,
GW> I'm concerned that by making CDI to servlet mapping a responsibility
GW> of the servlet container, then we are going to have to do a
GW> container to CDI adaptation for every CDI implementation out there.

I think this is missing the key insight that CDI extensions are portable and that it's "just" providing a 1 class extension that adds 3 orso build-in beans.

Kind regards,
Arjan Tijms



 

But it's more complicated then it sounds. For example, HttpServletRequest attibutes might be used as backing storage of the request context. So that it cannot simply change...

Anyway, I think this problem deserves some attention from both the CDI and the Servlet EG.

Martin

Dne 8.9.2016 v 13:31 arjan tijms napsal(a):
Hi,

On Thu, Sep 8, 2016 at 1:09 PM, Romain Manni-Bucau
<rmannibucau@gmail.com <mailto:rmannibucau@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().getRequestDispatcher(...);
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@gmail.com
    <mailto:arjan.tijms@gmail.com>>:

        Hi,

        On Thu, Sep 8, 2016 at 12:40 PM, Martin Kouba <mkouba@redhat.com
        <mailto:mkouba@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@lists.jboss.org <mailto:cdi-dev@lists.jboss.org>
                https://lists.jboss.org/mailman/listinfo/cdi-dev
                <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
                <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@lists.jboss.org <mailto:cdi-dev@lists.jboss.org>
        https://lists.jboss.org/mailman/listinfo/cdi-dev
        <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
        <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.