jsr372-experts@javaserverfaces-spec-public.java.net

[jsr372-experts] Re: [jsr372-experts mirror] Re: [527-InjectFacesContext] Support and review

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Thu, 25 Sep 2014 18:02:02 +0200

Hi,

On Thu, Sep 25, 2014 at 4:32 PM, Edward Burns <edward.burns_at_oracle.com> wrote:
> Arjan, can you take the action item to investigate this and report back
> to the group? Such investigations and reports are the bread and butter
> of expert group membership and really add significant value because the
> results the produce are so actionable.

I took a quick look, and the results are rather interesting.

First of all, the feature is described here:
http://docs.jboss.org/seam/3/servlet/latest/reference/en-US/html/injectablerefs.html#injectablerefs.http_servlet_request

The producer was created by CDI wizards Dan Allen and Nicklas
Karlsson, and for the HttpServletRequest it looks as follows:

@Produces
@Typed(HttpServletRequest.class)
@RequestScoped
protected HttpServletRequest getHttpServletRequest() {
    return holder.getHttpServletRequest();
}

See: http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.seam.servlet/seam-servlet/3.1.0.Beta2/org/jboss/seam/servlet/http/ImplicitHttpServletObjectsProducer.java?av=f

The holder is an application scoped bean, which has as its main goal
to collect and hold on to among others the HttpServletRequest via a
thread local. Collection happens via a CDI event and the listeners
stores the request object into TLS via a wrapper. Abbreviated it's:

protected void requestInitialized(@Observes @Initialized final
InternalServletRequestEvent e) {
    ServletRequest req = e.getServletRequest();
    // code omitted
    requestCtx.set(new HttpServletRequestContext(req));
}

See: http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.seam.servlet/seam-servlet/3.1.0.Beta2/org/jboss/seam/servlet/event/ImplicitServletObjectsHolder.java#70

But the wrapper doesn't play a role in injection, since when the
producer asks the holder for the request instance, it's unwrapped
again. Abbreviated it's:

public HttpServletRequest getHttpServletRequest() {
      // code omitted
    return HttpServletRequestContext.class.cast(requestCtx.get()).getRequest();
}

See: http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.seam.servlet/seam-servlet/3.1.0.Beta2/org/jboss/seam/servlet/event/ImplicitServletObjectsHolder.java#128

So there's not a lot of magic going at all. The key seems to be that
the producer itself is @RequestScoped, but the instance it produces
doesn't seem to be a request scoped wrapper bean at all, just the
normal instance. I do wonder a bit why they choose TLS storage instead
of a request scoped bean, but that's beside the issue here.

As JSF already stores the FacesContext in TLS, the entire holder
construct isn't needed and seemingly the producer would only need to
be annotated with @RequestScoped.

Kind regards,
Arjan