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

[jsr344-experts] Re: PRD Review and pending issues

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Mon, 14 Jan 2013 18:32:55 -0500

Hi

Thinking about the problem in ResourceHandler.createViewResource, I have
some additional comments:

Q: What's the difference between createViewTemplateResource and
createResource ?

In theory, createViewTemplateResource should filter resources that cannot
be used by the VDL as part of a view, but from implementation perspective
both are similar, because it is usual to pack templates with css files and
images in a single place.

The idea behind createViewTemplateResource is provide a single point to
load templates. In theory, we need a solution to fix how to resolve
facelet resources. There are two ways to load a template. For example:

/a.xhtml

<ui:decorate template="/templates/mytemplate1.xhml">

/templates/b.xhtml

<ui:decorate template="mytemplate2.xhml">

The first one (a.xhtml) loads the template from an absolute location, but
the second one is relative to the location of the template. So, if
b.xhtml is inside /templates folder, mytemplate2.xhtml is located in
/templates/mytemplate2.xhtml.

Right now, facelets derive the path using a call to:

new URL(from, path)

The problem with this is that the new url is derived using the real
location of the file, skipping ResourceHandler logic at all. Suppose
a composite component using some template internally. The expected
behavior is facelets load the template getting a Resource instance
and calling Resource.getURL() or Resource.getInputStream().

So, we need two createViewTemplateResource methods:

Resource createViewTemplateResource(String resourceName)
Resource createViewTemplateResource(String resourceName, String libraryName)

If a composite component has a relative reference to a template, the
resource should be related to the libraryName and resourceName of
the composite component.

Q: Why fix facelets URL problem?

Because right now we have a logic inside DefaultFaceletFactory that
cache those URLs and the right place to do that is ResourceHandler.

Suppose you have to load a facelet from a database. With this change, it
becomes possible to create a custom FaceletCache/ResourceHandler to load
resources from the database and do the necessary logic to load/unload
facelet instances from memory. FaceletCache will keep Facelet instances,
and ResourceHandler will keep the Resource caching information, like it
should be.

regards,

Leonardo Uribe

2013/1/14 Leonardo Uribe <lu4242_at_gmail.com>:
> Hi
>
> I have checked PRD documentation and I have noticed some pending points that
> it could be good to keep in mind. This is important feedback, and in my
> opinion these points needs to be solved.
>
> ------------------------------------------------------------------------
> Faces Flow
> ------------------------------------------------------------------------
>
> - It seems there are still some examples using the old syntax inside .xhtml
> files and there are people who still believes that syntax is valid, but
> in the spec documentation there are only two ways to define a flow: using
> xml file and using @FlowDefinition.
>
> - In JSF 2.2 section 7.5.1, it says something like this:
>
> "... When the application containing these flows is deployed, the runtime
> discovers the flow definitions and adds them to the internal flow data
> structure. One flow is defined in flow-b-flow.xml. The other flow is defined
> in FlowA.java, an @Named bean with the @FlowDefinition annotation. ..."
>
> That's ok, but I think it is not clear that flow-b-flow.xml is a xml file
> that has a <faces-config> definition inside (note I'm speculating here).
> I suppose that file should allow only a subset of <faces-config> (navigation
> rules, managed beans definitions maybe components/renderers?), or maybe
> it is open to define anything that can be defined in a faces-config (which
> I doubt it). And how @FlowDefinition works? the documentation doesn't
> say anything, so I just can't say anything. In my opinion, this part has
> sense but it requires some clarifications first.
>
> - In JSF 2.2 section 11.4.3.1, it talks about "Packaging Faces Flows
> in JAR Files". Take a look at these lines:
>
> "... Any flow nodes included in the jar must be located within sub entries
> of the META-INF/flows/<flowName> JAR entry, where <flowName> is a JAR
> directory entry whose name is identical to that of a flow id in the
> corresponding faces-config.xml file. ..."
>
> What is a "flow node"? is it a real view that JSF can load? does that
> means that the vdl should be able to load files under
> META-INF/flows/<flowName> like if they were in a webapp directory?.
>
> Note according to the previous answers, it should be some changes or
> clarification about how ResourceHandler.createViewResource() works.
>
> ------------------------------------------------------------------------
> View Actions
> ------------------------------------------------------------------------
>
> - The changes previously proposed are still pending, so any snapshot to
> check how they should looks like is welcome.
>
> ------------------------------------------------------------------------
> Application.createComponent(FacesContext context, String taglibURI,
> String tagName, Map<String,Object> attributes)
> ------------------------------------------------------------------------
>
> Here we have an implementation dependency between the VDL and the Application
> object. It says that it creates a component given a VDL, so it means
> Application object must call an implementation-specific method from the VDL
> (in facelets case a cast to FaceletsViewDeclarationLanguage and a call),
> because the VDL class does not provide a method from the base class. I think
> it does not suppose a problem, just something to take note. Maybe provide a
> default method in ViewDeclarationLanguage can be useful, so if you create a
> VDL wrapper, you can override that one too.
>
> ------------------------------------------------------------------------
> Resource Library Contracts / Resource Handler
> ------------------------------------------------------------------------
>
> I think the only pending point in this part is make some clarifications about
> how and when ResourceHandler.createViewResource() can be called.
>
> It is clear that the idea of this method is allow facelets or any other VDL
> to use ResourceHandler API to load resources used during view construction
> (templates, view definitions, ...) .
>
> According to the new spec, we have some special places that store view related
> resources:
>
> - META-INF/flows/<flow-name>/... : files there should be dealt as views.
> - META-INF/contracts/<contract-name>/... : files there are not views but the
> VDL should be able to load resources like templates that are used when a view
> is processed. It also contains other resource files like .css, .png and so on
> that the ResourceHandler should be able to locate and serve them. It also
> contains composite component files.
> - META_INF/resources/... : Contains resource files like .css, .png and so on
> that the ResourceHandler should be able to locate and serve them. It also
> contains composite component files.
>
> This looks great. The important part is there is a difference between files
> that can use the VDL to create views and files that can use the VDL while
> is building views (like templates).
>
> Since we have 3 different concepts here, it should be 3 different methods to
> deal with this (better names for the methods are welcome):
>
> - ResourceHandler.createResource(...) : load files served by ResourceHandler
> and files that can be used while a view is being built like composite
> components or templates, but those files should never be served by
> ResourceHandler.handleResourceRequest() (excluded using
> "javax.faces.RESOURCE_EXCLUDES" web config param).
>
> - ResourceHandler.createViewTemplateResource(
> FacesContext context, String resourceName) : load template files from
> META-INF/contracts/<contract-name>/... , META_INF/resources/... and
> webapp directory. By default it calls createResource() method. Facelets
> algorithm should be updated to use this method.
>
> - ResourceHandler.createViewResource(
> FacesContext context, String resourceName) : load files inside
> META-INF/flows/<flow-name>/... and webapp directory by default. Some changes
> in JSF 2.2 section 2.2.1 could be required. The idea is do some changes over
> ViewDeclarationLanguage.viewExists(FacesContext facesContext, String viewId)
> method (if the returned Resource instance is null, the resource does not
> exists or maybe a custom method is a good idea) and make the VDL use this
> method to get the views.
>
> I think the proposed change has a lot of sense. It effectively make a
> distinction between resources that can create a facelet that derive a view
> and resource that can create a facelet that are used as templates. It
> enforces the concept that that views cannot be included in resource
> library contracts. It defines that view can be defined as part of a flows
> (I'm under the assumption that a "flow node" by definition is a view).
>
> ------------------------------------------------------------------------
>
> This is it. I know time's up but if I see something else, anyway I'll send
> the feedback as soon as possible. Suggestions are welcome.
>
> regards,
>
> Leonardo Uribe