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

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

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Tue, 18 Dec 2012 15:19:29 -0500

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

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