users@javaserverfaces-spec-public.java.net

[jsr344-experts mirror] [jsr344-experts] Re: 1012 ExternalContext.getApplicationContextPath()

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Tue, 18 Dec 2012 17:50:09 -0500

2012/12/18 Neil Griffin <neil.griffin_at_portletfaces.org>:
> Comments inline below..
>
> On Dec 18, 2012, at 3:19 PM, Leonardo Uribe <lu4242_at_gmail.com> wrote:
>
> Hi
>
> 2012/12/18 Neil Griffin <neil.griffin_at_portletfaces.org>:
>
> Hi Ed,
>
> Regarding issue 1012 [1], the JSF 2.2 JavaDocs expose a new method on
> ExternalContext named getApplicationContextPath() which has the following
> requirements:
>
> * <p class="changed_added_2_2"><em>Servlet:</em>
> * Return the result of calling
> * <code>getContextPath()</code> on the
> * <code>ServletContext</code> instance for this application. It is
> * valid to call this method during application startup or shutdown.</p>
>
> Since FacesContext.getCurrentInstance() is a ThreadLocal singleton bound to
> the request thread, it is not possible to call
> FacesContext.getCurrentInstance().getExternalContext() during application
> startup or shutdown.
>
>
> In my understanding, allow FacesContext.getCurrentInstance() during
> application
> startup/shutdown was added since JSF 2.0, at least in MyFaces, but I'm
> pretty
> sure about the same for Mojarra, because it was discussed long time ago.
>
> In MyFaces there is an interface called
> org.apache.myfaces.webapp.FacesInitializer with these methods:
>
> void initFaces(ServletContext servletContext);
> void destroyFaces(ServletContext servletContext);
> FacesContext initStartupFacesContext(ServletContext servletContext);
> void destroyStartupFacesContext(FacesContext facesContext);
> FacesContext initShutdownFacesContext(ServletContext servletContext);
> void destroyShutdownFacesContext(FacesContext facesContext);
>
> You can set the initializer using a web config param called:
> org.apache.myfaces.FACES_INITIALIZER
>
> This interface is very helpful when you need some special initialization
> steps.
> In MyFaces there are 3 initializers:
>
> org.apache.myfaces.webapp.Jsp20FacesInitializer
> org.apache.myfaces.webapp.Jsp21FacesInitializer
> org.apache.myfaces.webapp.FaceletsInitilializer (only facelets, disable jsp)
>
> I know for user application it is better to use a JSF application
> scope bean with
> eager=true and use @PostConstruct and @PreDestroy annotations, but in
> portlet
> case a similar interface could be useful, obviously doing some changes
> to make it more neutral interface
>
> Note there is a difference between startup/shutdown FacesContext and the one
> used for requests in JSF, but for now that startup/shutdown FacesContext is
> an
> implementation detail, and in some way bound to a servlet container because
> to get the "context" of the application it is necessary to retrieve a
> ServletContext instance, usually from a Listener
> (see org.apache.myfaces.webapp.StartupServletContextListener).
>
> Also, the Portlet API does not provide access to the underlying
> ServletContext. I suppose that the best we could do in a portlet environment
> would be to register a ServletContextListener and remember the
> ServletContext instance for later reference.
>
> When you get a chance, could you elaborate on what made it necessary to add
> the getApplicationContextPath() feature?
>
>
> That method shows the missing piece of the puzzle. In portlet case you
> want to override
> that method, but since startup/shutdown FacesContext/ExternalContext are
> implementation details, you cannot pass the PortletContext or
> PortletConfig or what's
> necessary to make it work.
>
> regards,
>
> Leonardo Uribe
>
>
> @Leonardo: Thanks for the feedback regarding MyFaces. I see that MyFaces has
> a StartupFacesContextImpl class and Mojarra has an InitFacesContext class.
> And... each of these have their own "startup" version of ExternalContext.
> Additionally, Section 6.1.4 of the Spec says the following about
> FacesContext.getExternalContext():
>
> "The default implementation must return a valid value when this method is
> called during startup time. See the javadocs for this method for the
> complete specification."
>
> @Leonardo/_at_Ed:
>
> Perhaps it would be more straightforward (from the API perspective) if
> FacesContextFactory and/or ExternalContextFactory had methods for acquiring
> startup instances?
>

Probably, but probably that requires create wrapper classes for
FacesContextFactory and ExternalContextFactory. Another option is include a
StartupFacesContextFactory / StartupExternalContextFactory.

MyFaces makes difference over startup/shutdown just for logging purposes, but
the instances is the same. Note the difference between a FacesContext created
on startup is that there is no request, so all related methods should throw
UnsupportedOperationException, but the ones related to config or context should
work without problem.

> If not, then given the current startup design of MyFaces and Mojarra, is it
> safe to assume that the portlet bridge implementation of
> ExternalContext.getApplicationContextPath() would only be called during a
> request?
>

It does not look nice, but I think there is no need to call that method on
startup/shutdown more than use it in the log.

regards,

Leonardo

> Thanks guys,
>
> -- Neil
>
>
> Thanks,
>
> Neil
>
> [1] http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1012
>
>