users@javaserverfaces-spec-public.java.net

[jsr344-experts mirror] [jsr344-experts] implications of use FaceletFactory (JAVASERVERFACES_SPEC_PUBLIC-611)

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Fri, 23 Nov 2012 17:58:06 -0500

Hi

I want to remind you a mail sent some months ago

[jsr-344-experts] FaceletFactory.createComponent(...) ?

You can check it here:

http://java.net/projects/javaserverfaces-spec-public/lists/jsr344-experts/archive/2012-06/message/18

I have been reading the latest available snapshot of the spec before
public review, and this is the only point I can see could suppose a
"pandora box".

In few words (if we can find them for such a complex issue), the
problems of use FaceletFactory outside facelets algorithm are:

- PSS algorithm impose some restrictions about facelets algorithm.
For example, every component created by a facelet tag handler
contains a mark that helps later to associate the tag handler and
the component and refresh the component tree. PSS algorithm use
that information to ignore component manipulation, with the
suposition that facelets will take care about the conditions of save
restore. In this case, the intention is use facelets algorithm to
create a component subtree dynamically, but this case should be
done as a programatical addition.

- Facelets algorithm refresh the component tree, usually under a
postback in the call to vdl.buildView() on render response phase.
The intention of the algorithm is deal with tags like <c:if ...> and
<ui:include src="#{...}"/>, evaluating the expressions and according
to that, creating and removing component subtrees. But this
algorithm was designed to skip programatically added components.
In this case, a component subtree created by FaceletFactory or
FaceletContext is not included in the refresh algorithm, so will
never be refreshed and it will be silently removed.

- There is no warrant about how the ids will be generated, and if
the ids will be unique under the current NamingContainer,
because all calls of FaceletFactory and FaceletContext suppose
a "context", which at the end defines how the ids are generated.

These problems are not easy to solve, but the interesting part is
all of them suppose that if we can use facelets to create
component subtrees and add them and then we can make
facelets deal with those components as not bound to facelets tag
handlers, it is possible to solve the problems.

In other words, the instance of FaceletFactory used by users in
programatical component manipulations, should not be the same
variant as the FaceletFactory instance used by facelets algorithm.
To be more clear, what we need is provide a class to use facelets
into programatical component manipulations, not expose
FaceletFactory as is right now. Under that context, a method like:

UIComponent createComponent(FacesContext context,
String taglibURI, String tagName, Map<String,Object> attributes)

has a lot of sense, but not under FaceletFactory, instead under
something else.

In a previous mail I have exposed 5 ways to update a component
tree programatically, but investigating more about this I found
an alternative to inject component subtrees using "binding"
attribute. See:

http://balusc.blogspot.com/2006/06/using-datatables.html#PopulateDatatable

It is another way to "inject" programatically "something" into the
component tree from a bean. The interesting part is in my opinion the
hack is valid, and maybe it is a good example where a createComponent()
method like the one proposed becomes useful.

The issue under FaceletFactory was created claims this:

"... It would probably be useful for developers that wish to provide
custom functionality within the FaceletFactory to be able to do so
in a standard fashion. ..."

I think the intention of FaceletFactory and FaceletFactory.createComponent
are two different requeriments. It is more, in this moment, I think expose
FaceletFactory is risky, because to do that we need an effort to standarize
even more facelets algorithm itself. In this moment, we are trying to expose
something that still we don't know how it looks like, or how to use it.

Another problem we have is FaceletFactory.createComponent cannot be
moved to Application class, because it suppose create a component based on
the current context, which defines the vdl used. Why the VDL does not have
the right to create a component? If you read the documentation of
Application.createComponent(FacesContext context, Resource componentResource),
everything is related to the VDL.

It is also weird the way how @ResourceDependency annotations are processed.
To avoid duplicate component instances, it is necessary to keep track of
the classes processed, but that information is not stored with the view, because
it can be regenerated using PSS algorithm. I know it works, and it is
ok, but in theory
Application object is creating an object based on the context, but if
that so, all
related methods should be able to receive FacesContext instance, right? It is a
waste of resources call FacesContext.getCurrentInstance() over and over.

regards,

Leonardo Uribe