users@javaserverfaces-spec-public.java.net

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

From: Leonardo Uribe <leonardo.uribe_at_irian.at>
Date: Thu, 25 Sep 2014 12:25:48 -0500

Hi

The other use case you need to consider is what happen
when a FacesContext wrapper is used in a section. In that
case, you want to get the right FacesContext in the wrapped
section. One example is UIViewAction, but there are others
out there.

Suppose this "hypothetical" use case. You have a task invoked
by a timer, or a REST service using JAX-RS, or a websocket
request and you need to access a CDI bean somewhere to
grab some data, and by some reason you need the
FacesContext. What do you do?

1. Construct a custom FacesContext, taking what you can from
the environment (servletContext, servletRequest, ...). If you don't
have a servlet request, use the mock classes from MyFaces
Test.
2. Call the method, passing FacesContext instance.

What if the CDI container deals with FacesContext instantiation
and release by itself, inspecting the context and building or
getting the right instance? Wouldn't that be nice? I think it can
be done.

I also see the possibility of provide a "simplified" FacesContext.
Not one that takes the context, request and response, but
one that can be called inline to do some simple tasks like
render plain html with minimal configuration (viewId + params).
That could be created/destroyed inline.

regards,

Leonardo Uribe


2014-09-25 11:58 GMT-05:00 Neil Griffin <neil.griffin_at_portletfaces.org>:
> The JSF Portlet Bridge will make beans annotated with
> javax.faces.bean.RequestScoped survive from the ACTION_PHASE to the
> RENDER_PHASE.
>
> But CDI does not do that. If a JSF portlet developer annotates a bean with
> javax.enterprise.context.RequestScoped, then CDI creates a new bean in both
> the ACTION_PHASE and RENDER_PHASE.
>
> If there is a successor to JSR 329, then one of the requirements for that
> new JSR *might* be to re-define the behavior of
> javax.enterprise.context.RequestScoped.
>
> On Sep 25, 2014, at 12:36 PM, Leonardo Uribe <leonardo.uribe_at_irian.at>
> wrote:
>
> Hi
>
> I know that the trick using @RequestScoped works, but
> Is there a 1-1 relationship between FacesContext lifecycle
> and the request lifecycle? That works fine on servlets but
> it doesn't on portlets (action request / render request).
>
> It is possible to imagine other scenarios where this
> assumption just fail. In my opinion, we should take the
> long route, create a CDI scope and use that scope to
> store the producer, so it get the right instance. After all
> JSF should be in control of FacesContext lifecycle.
>
> regards,
>
> Leonardo Uribe
>
>
> 2014-09-25 11:02 GMT-05:00 arjan tijms <arjan.tijms_at_gmail.com>:
>
> 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
>
>