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

[jsr372-experts] Re: 1099-ViewsInDedicatedFolder

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Tue, 3 Feb 2015 15:35:13 +0100

Hi,

I'd like to resume the discussion for this issue. Since 1099 talks
about a default views folder, default mapping the facelets servlet and
extensionless mapping all at the same time, I thought it was better to
create a new issue for just loading views. This became:
https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1359

While this issue is still related to 1099, I'd like to focus there
only on a /views folder.

The idea of /views is a folder for which the runtime can be sure that
it contains only top-level views, i.e. no templates, includes,
composite components or non-JSF files that happen to have the .xhtml
extension.

As such there is a relation with /contracts, which if I'm not mistaken
does (or should) only contain templates and resources, but not
top-level views.

I've been prototyping and testing the feature a little in the Mojarra
source code. Basically in FaceletWebappResourceHelper#findResource
there's now the following segment of code:

if (null == url) {
    url = Resource.getResourceUrl(ctx, path);
}

if (null == url) {
    ClassLoader cl = Util.getCurrentLoader(this);
    Enumeration<URL> matches =
cl.getResources(RIConstants.FLOW_IN_JAR_PREFIX + resourceName);


Which I changed to:

if (url == null && !"/".equals(path)) {
    // A request for "/" is done by the FaceletFactory to set the base url.
    // We want to keep that on the web context root.
    // See com.sun.faces.facelets.impl.DefaultFaceletFactory#init
    url = Resource.getResourceUrl(ctx, "/views" + path);
}

if (null == url) {
    url = Resource.getResourceUrl(ctx, path);
}

if (null == url) {
    ClassLoader cl = Util.getCurrentLoader(this);
    Enumeration<URL> matches =
cl.getResources(RIConstants.FLOW_IN_JAR_PREFIX + resourceName);

After some tests with different use cases (includes from various
folders and such) things seem to work. Effectively what happens is
pretty much identical to what happens when a custom
ResourceResolver/Handler first tries to load from ("/views" + path),
and if that doesn't work delegates to the parent Resolver/Handler.
This is what OmniFaces does for its FacesViews feature as well.

In the above prototype code "/views" is hardcoded, but in the real
code it would be a setting just like /contracts has now, including
some guards that prevent loading from /views/ directly from an
external request, etc.

Thoughts?

Kind regards,
Arjan Tijms





On Thu, Oct 23, 2014 at 6:03 PM, Neil Griffin
<neil.griffin_at_portletfaces.org> wrote:
> Hi Arjan,
>
> In the case of portlets, javax.portlet.faces.GenericFacesPortlet [1] calls
> through to an implementation of javax.portlet.faces.Bridge [2] and the
> FacesServlet is completely bypassed. So in that sense, the servlet-mappings
> are ignored/irrelevant in a portlet environment.
>
> However, the JSF runtime has a webapp (non-portlet) interpretation of the
> values returned by ExternalContext.encodeActionURL(String),
> getRequestPathInfo(), and getRequestServletPath(). Additionally, portlets do
> not have access to the underlying HttpServletRequest. Therefore the JSF
> Portlet Bridge must parse the servlet-mappings in the WEB-INF/web.xml
> descriptor and manufacture values that the JSF runtime is happy with. If JSF
> 2.3 introduces a new default extension/suffix-mapped default-mapping then
> JSF 2.3 compatible JSF Portlet Bridges will need to implement the check for
> the opt-in and setup the default mapping.
>
> Detailed requirements for these ExternalContext methods are documented in
> Section 6.1.3.1 of the JSR 329 Spec [3].
>
>
> Best Regards,
>
> Neil
>
> [1]
> http://myfaces.apache.org/portlet-bridge/2.0/api/apidocs/javax/portlet/faces/GenericFacesPortlet.html
> [2]
> http://myfaces.apache.org/portlet-bridge/2.0/api/apidocs/javax/portlet/faces/Bridge.html
> [3] https://jcp.org/aboutJava/communityprocess/final/jsr329/index.html
>
> On Oct 23, 2014, at 11:03 AM, arjan tijms <arjan.tijms_at_gmail.com> wrote:
>
> Hi,
>
> On Thu, Oct 23, 2014 at 4:39 PM, Neil Griffin
> <neil.griffin_at_portletfaces.org> wrote:
>
> FYI, adding adding *.xhtml to the default mappings affects existing
> requirements of the JSF Portlet Bridge. Specifically, the requirements for
> ExternalContext.encodeActionURL(String), getRequestPathInfo(), and
> getRequestServletPath() in section 6.1.3.1 titled "Methods that deviate from
> Faces 1.2 Javadoc”
>
>
> I'm not that familiar with Portlets, but what will change for Portlets
> there?
>
> For Servlets both methods are pretty straightforward.
>
> encodeActionURL first adds the client window parameters (if any) and
> then calls straight through to HttpServletResponse.encodeURL.
>
> getRequestPathInfo and getRequestServletPath are even simpler, as they
> call directly through to HttpServletRequest.getPathInfo and
> HttpServletRequest.getServletPath.
>
> At any length the idea is thus that the default mapping will only be
> altered for application that opt-in to JSF 2.3.
>
> Maybe Portlets will then "just" need to specify a new bridge for JSF
> 2.3? (I know it's never that easy, but wasn't there talk about this
> already?)
>
> Kind regards,
> Arjan
>
>
>
>
>
>
> On Oct 22, 2014, at 5:51 PM, Edward Burns <edward.burns_at_oracle.com> wrote:
>
> On Wed, 22 Oct 2014 00:03:31 +0200, arjan tijms <arjan.tijms_at_gmail.com>
> said:
>
>
> [...]
>
> AT> An optimal solution going forward and absolutely trivial to implement
> AT> is just adding *.xhtml to the default mappings. However, this may have
> AT> backwards compatibility issues and has therefor been rejected
> before.
>
> Indeed.
>
> AT> Another solution is to use the recently introduced switch, that uses a
> AT> 2.3 faces-config and/or 4.0 web.xml for possibly incompatible EL
> AT> resolving behavior, to switch between having *.xhtml as a default
> AT> mapping or not. Meaning a 2.3 faces-config.xml causes a mapping on
> AT> *.xhtml by default, any lower versioned or no faces-config keeps the
> AT> current mappings.
>
> I can see this, and it would be easy to implement in the
> ServletContainerInitializer impl. In Mojarra this is FacesInitializer.
> Can someone code up a patch for this?
>
> AT> Yet another solution, that incidentally also ties in with the
> AT> extensionless URL mappings that were discussed on this list a while
> AT> back, is to have a dedicated folder from which views are loaded.
>
> AT> This is not entirely unlike the dedicated folders for contracts and
> AT> composites that already exist today. Views in that folder would be by
> AT> definition JSF views, so the runtime can safely map them, with or
> AT> without extension. A while back I created
> AT> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1099 for this
> AT> and implemented it in OmniFaces.
>
> That sounds good too.
>
> Ed
>
> --
> | edward.burns_at_oracle.com | office: +1 407 458 0017
> | 12 work days til Devoxx 2014
>
>
>