[jsr-314-open] Metadata complete jar files
by Andy Schwartz
Gang -
Section 11.5.1 of the spec defines the following annotation scanning
behavior:
> Requirements for scanning of classes for annotations
> * If the <faces-config> element in the WEB-INF/faces-config.xml file
> contains metadata-complete attribute whose value is “true”, the
> implementation must not perform annotation scanning on any classes
> except for those classes provided by the implementation itself.
> Otherwise, continue as follows.
> * If the runtime discovers a conflict between an entry in the
> Application Configuration Resources and an annotation, the entry in
> the Application Configuration Resources takes precedence.
> * All classes in WEB-INF/classes must be scanned.
> * For every jar in the application's WEB-INF/lib directory, if the jar
> contains a “META-INF/faces-config.xml” file or a file that matches the
> regular expression “.*\.faces-config.xml” (even an empty one), all
> classes in that jar must be scanned.
Since application developers have the ability to disable annotation
scanning at a global level, this means that any component set that wants
to support this mode would need to provide a metadata complete
faces-config.xml file. I don't think this is a hardship for most
component vendors, since presumably component vendors are going to want
to provide design-time metadata (eg. JSR-276 metadata), which, for the
moment, requires a faces-config.xml file anyway.
A question that came up here is whether we can tweak section 11.5.1 to
accommodate metadata complete jar files. That is, can we specify that
any jar that contains a faces-config.xml with a metadata-complete="true"
attribute would not be scanned? This would allow component vendors to
indicate that their jar files are metadata complete, and thus avoid the
cost of annotation scanning for the contents of the jar.
Note that while the annotation scan is typically a one time hit (during
application startup), design-time tools may end up starting/stopping JSF
repeatedly during the development process. Thus, avoiding unnecessary
scanning should provide for a more efficient development experience.
Any thoughts on whether we could/should make this change? Does anyone
know of reasons why we avoided specifying this originally?
Also - if we agree to make this change, is this small enough that we
could get this into the the next MR?
Andy
13 years, 11 months
[jsr-314-open] PostAddToViewEvent publishing conditions still inconsistent
by Leonardo Uribe
Hi
Some days ago, I tried to check if publishing conditions for
PostAddToViewEvent were fixed, but unfortunately it was not. These issues:
- PostAddToViewEvent delivery specification needs clarification
http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-805 (for 2.0 rev A)
- Fix PostAddToViewEvent and PreRemoveFromViewEvent publishing conditions
http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-782 (for
2.1_gf31_m5)
were marked as fixed.
This is what javadoc for JSF 2.1 says about it (I put the javadoc to make it
more easier to understand):
- (see UIComponent.getChildren method, the part in orange)
"... After the child component has been added to the view,
Application.publishEvent(javax.faces.context.FacesContext, java.lang.Class,
java.lang.Object) must be called, passing PostAddToViewEvent.class as the
first argument and the newly added component as the second argument if any
the following cases are true.
* FacesContext.getCurrentPhaseId() returns PhaseId.RESTORE_VIEW and
partial state saving is enabled.
* FacesContext.isPostback() returns false and
FacesContext.getCurrentPhaseId() returns something other than
PhaseId.RESTORE_VIEW..."
- Another reference to the previous point (see PostAddToViewEvent class
description)
"... The implementation must guarantee that
Application.publishEvent(javax.faces.context.FacesContext, java.lang.Class,
java.lang.Object) is called, immediately after any UIComponent instance is
added to the view hierarchy except in the case where
ResponseStateManager.isPostback(javax.faces.context.FacesContext) returns
true at the same time as FacesContext.getCurrentPhaseId() returns
PhaseId.RESTORE_VIEW. When both of those conditions are met,
Application.publishEvent(javax.faces.context.FacesContext, java.lang.Class,
java.lang.Object) must not be called. ..."
- (see UIComponent.setParent method)
"... Set the parent UIComponent of this UIComponent. If parent.isInView()
returns true, calling this method will first cause a PreRemoveFromViewEvent
to be published, for this node, and then the children of this node. Then,
once the re-parenting has occurred, a PostAddToViewEvent will be published
as well, first for this node, and then for the node's children, but only if
any of the following conditions are true.
* FacesContext.getCurrentPhaseId() returns PhaseId.RESTORE_VIEW and
partial state saving is enabled.
* FacesContext.isPostback() returns false and
FacesContext.getCurrentPhaseId() returns something other than
PhaseId.RESTORE_VIEW ..."
The first thing to notice is the description here is not what is happening
right now in Mojarra (2.0 and 2.1). The description found in
UIComponent.setParent is more close to the reality (the conditions related
to parent.isInView() ) but the part that says "... but only if any of the
following conditions are true ..." is not being preserved.
The intention of those conditions are clear. See this coment from Andy
Schwartz (JAVASERVERFACES_SPEC_PUBLIC-805):
"... 2. We don't actually want to deliver PostAddToViewEvents during render
response when Facelets temporarily removes/re-adds existing components from
the tree. ..."
Unfortunately, in practice the previous two conditions does not warrant
that. Its more, there are valid scenarios in facelets when it is required to
throw PostAddToViewEvent (for example, an ui:include src="#{someEL}" should
propagate that event so the view could be restored).
- (see PostAddToViewEvent class description)
"... When an instance of this event is passed to
SystemEventListener.processEvent(javax.faces.event.SystemEvent) or
ComponentSystemEventListener.processEvent(javax.faces.event.ComponentSystemEvent),
the listener implementation may assume that the source of this event
instance is a UIComponent instance and that either that instance or an
ancestor of that instance was just added to the view. Therefore, the
implementation may assume it is safe to call UIComponent.getParent(),
UIComponent.getClientId(), and other methods that depend upon the component
instance being added into the view. ..."
In practice, that's not true in Mojarra, but it is on MyFaces. The reason is
Mojarra still uses a Listener attached to PostAddToViewEvent, making
UIComponent.getClientId() "unstable". If the developer has a listener that
is executed before the one doing relocation, UIComponent.getClientId() call
will not work correctly.
The central point of this mail is how should PostAddToViewEvent should
really behave?
In theory, and according to the latest JSF 2.1 spec, the original intention
must be preserved. That means:
- Deliver PostAddToViewEvents during restore view when partial state saving
is enabled.
- Don't deliver PostAddToViewEvents during render response when Facelets
temporarily removes/re-adds existing components from the tree, but propagate
it when the component is removed or added permanently.
The current behavior of Mojarra, from the point of view of the spec should
be consider a bug. How to do fix it? I propose do the following for Mojarra:
1. Check when a component is temporally removed/added on
ComponentTagHandlerDelegate implementation. If that so, disable event
processing using FacesContext.setProcessingEvents() method temporally while
removal and addition is done.
2. Propagate another internal event (for example PostAddToViewOnRefreshBuild
or something like that) to notify the listeners used for relocation
(cc:insertChildren, cc:insertFacet, h:outputScript, h:outputStylesheet) to
do their job like before.
Anyway, it could be good to know how this should really work, and fix the
relevant points on the spec.
Suggestions are welcome.
regards,
Leonardo Uribe
14 years
[jsr-314-open-mirror] [jsr-314-open] Should the ViewDeclarationLanguage be responsible to indicate if a viewId can be created?
by Leonardo Uribe
Hi
The current algorithm to check if a view with a specific viewId does not
allow to add or extends a new ViewDeclarationLanguage using a new
prefix/extension.
This issue is related to
https://issues.apache.org/jira/browse/MYFACES-2628 Facelets ResourceSolver
can't work
and
https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1567
The problem resides on a "hidden" requeriment for Restore View Phase
algorithm, that is ignored silently. On mojarra, this is the code on
MultiViewHandler.getViewDeclarationLanguage:
public ViewDeclarationLanguage getViewDeclarationLanguage(FacesContext
context,
String viewId)
{
String actualViewId = derivePhysicalViewId(context, viewId, false);
return vdlFactory.getViewDeclarationLanguage(actualViewId);
}
Now on myfaces is this:
@Override
public ViewDeclarationLanguage getViewDeclarationLanguage(
FacesContext context, String viewId)
{
// return a suitable ViewDeclarationLanguage implementation for the
given viewId
return _vdlFactory.getViewDeclarationLanguage(viewId);
}
The difference is subtle, but very, very important. This method is called
from many locations, but only once (from RestoreViewPhase) it is passed the
"raw" viewId. To "derive" the physical viewId it is required to know if
prefix or suffix mapping is used and if suffix mapping is used, try to check
if a view "resource" exists or not with different derived ids with the
extensions configured ".xhtml .jsp".
javax.faces.view.facelets.ResourceResolver documentation says this:
"... Provide a hook to decorate or override the way that Facelets loads
template files. A default implementation must be provided that satisfies the
requirements for loading templates as in Pre-JSF 2.0 Facelets ..."
So, in theory it is possible to override ResourceResolver interface and
serve resources from a different location. But the algorithm in
MultiViewHandler.derivePhysicalViewId does not take into account this
interface, so it try to check if the view "resource" exists on the same
location and fails.
The solution proposed is add a method on ViewHandler,
ViewDeclarationLanguageFactory and ViewDeclarationLanguage called:
public boolean existsViewId(String viewId)
So the VDL can indicate if a viewId exists or not. In this way, on Facelets
VDL we can check if a viewId exists using the ResourceResolver instance. It
is curious that ViewDeclarationFactory implementation has some methods that
indicate if a vdl can handle a viewId or not (it is not the same, but
similar). I'm not done too much work on this issue, but it could be good to
take a look at this one. It could be good to open an issue on the spec for
this one too (if no objections I'll open an issue for this one, but better
to ask first).
Suggestions are welcome.
regards,
Leonardo Uribe
14 years, 1 month
[jsr-314-open] Partial state saving + tree visiting
by Andy Schwartz
Gang -
I have been spending time looking partial state saving lately - mostly
trying to understand what Trinidad/ADF Faces need to do to fully support
this. I have some questions regarding the use of tree visiting to
save/restore partial state. This touches on implementation, though think
it is important to have a consistent story, so sending to jsr-314-open.
At the moment our implementations are somewhat mixed in how they handle
the partial state traversals:
- Mojarra 2.1 performs a tree visit for both the partial state save and
restore traversals.
- Mojarra 2.0 performs a tree visit for the partial state restore but
uses a good old facets + children traversal for the save.
- MyFaces 2.0 performs a facets + children traversal for both save and
restore.
I believe the reason for the inconsistency has to do with the fact that
we did not have an explicit VisitHint.SKIP_ITERATION in 2.0. (Though, at
some point last year we agreed to temporarily go with a FacesContext
property until we could add the new VisitHint to the API.) As a result,
the implementation teams avoided tree visiting (at least partially) in
order to avoid unnecessary/incorrect UIData iteration. Now that we've
got our visit hint in 2.1, in theory this should make the correct
behavior clearer: we can now use tree visits for both the save and
restore and specify the SKIP_ITERATION visit hint to avoid iterating
over rows in iterating components.
However, after thinking this through in more detail, I am not quite sure
whether the correct behavior is as obvious as I originally thought it was.
Here's why…
One of the main benefits of tree visiting over a traditional facets +
children traversal is that tree visiting allows components to be visited
"in context" - ie. ancestor components can override visitTree() to set
up context on behalf of their children. The most typical case is an
ancestor setting up context that influences EL evaluation for the
ancestor's subtree.
We (ADF) have some cases where setting up context can be expensive and
as such we'll want to avoid this work if not strictly necessary. More
generally, we don't want to set up any tree visiting-related context
during state saving/restoring since it is simply not necessary. We have
never performed context set up/tear down during full state saving (ie.
processRestoreState()/processSaveState() don't do anything interesting).
There is no point in introducing this now for partial state saving.
Doing so would introduce unnecessary overhead, plus result in
inconsistent behavior between partial and full state saving.
I had been thinking that the way to handle this is to have some way for
our components to distinguish between visitTree() calls that occur for
partial state saving/restoring purposes (in which case we don't want to
set up context) vs. other tree visits (in which case we do want to set
up context). As of 2.1, we have all of the APIs in place to allow us to
do just this. In particular:
- We can detect the partial state saving tree visit via the
StateManager.IS_SAVING_STATE FacesContext property.
- We can detect the partial state restoring tree visit by checking the
phase id + VisitHint.EXECUTE_LIFECYCLE. (Though implementations will
need to be sure to set this hint - logged Mojarra issue 1929 for this.)
By examining these properties/hints, a visitTree() implementation can
make an informed decision about whether it is necessary to set up context.
While it is now possible for visitTree() implementations to do the right
thing, I worry that this is overly complex and possibly unnecessary. If
we want to:
- Visit all (non-transient) components, but…
- Skip iteration (for UIData-like cases). And…
- Avoid setting up context.
Is tree visiting even the right tool for the job?
Should we perhaps avoid this complexity altogether by sticking with a
facets + children traversal (eg. as currently implemented by MyFaces)
for partial state saving/restoring?
Or are there cases where component implementations do in fact need
control over the way that this traversal is performed, in which case an
internal iteration solution (like tree visiting) is necessary?
Andy
14 years, 1 month
[jsr-314-open] ViewScoped severe bug or expected behavior?
by Werner Punz
Hi I ran into following issue while doing some testing on MyFaces and after
testing it on Mojarra I noticed that Mojarra behaves the same. So I am not
sure if this is a bug or expected behavior. Hence I am posting it here.
Following usecase.
a Page with a managed bean as page controller which is ViewScoped.
Now the page keeps some data which is serialized per definition on the
scope.
An action is triggered from the page which then issues an implicit
navigation case onto itself.
Now what happens on both implementations is, that the ViewScoped bean is
dropped and the data is lost.
This is easily reproducable with the case in the attachments.
As you can see the value is initially set to another value by the
postConstruct and then once the action is triggered it is reset to the
initial value, although it should
have been restored to the last value which was present before issuing the
action onto itself.
I could reproduce this behavior on MyFaces 2.0.3 and on Mojarra. Any ideas
if this is a bug or expected behavior? Because from a logical point of view
a nav case should not retire the view scope if it hits the same page again
no matter if a redirect is in between if it is implicit or explicit or if it
is just
a null restore case.
Werner
14 years, 1 month
[jsr-314-open] f:param in f:ajax
by Jakob Korherr
Hi,
Yesterday we got an issue in the MyFaces issue tracker saying that the
following peace of code should append paramName=paramValue as request
parameter to the ajax call (see [1]):
<h:inputText>
<f:param name="paramName" value="paramValue" />
<f:ajax />
</h:inputText>
The reason why the developer thinks this should work is because it
also works for h:commandXxx.
IMO it is clear why this should work for h:commandXxx: A UICommand
always triggers a new request (ajax or normal) and thus it should
support adding request parameters via f:param (this fact is also
stated in the spec). But a UIInput component isn't supposed to
generate a new request (at least not a normal request) and thus should
not support f:param.
Can anyone confirm this behavior for JSF 2.0 and 2.1 or did I miss something?
However, thinking about the fact that f:param was introduced before
JSF had any ajax support, it kinda does make sense to adopt it for
f:ajax, because now _every_ component can trigger a new (ajax) request
and thus should be able to add request parameters. Note that pre JSF
2.0 this was only true for UICommand.
Furthermore I looked at the spec javascript documentation of
jsf.ajax.request() and found out that there is already a way to add
request parameters to the ajax request: The options element supports a
"params" parameter: params - object containing parameters to include
in the request. Thus it is already possible to do it, but you have to
use the native javascript function instead of f:ajax.
So maybe the above example should work or maybe also something like
this should work:
<h:input...>
<f:ajax>
<f:param name="name1" param="param1" />
</f:ajax>
</h:input...>
WDYT?
Regards,
Jakob
[1] https://issues.apache.org/jira/browse/MYFACES-3012
--
Jakob Korherr
blog: http://www.jakobk.com
twitter: http://twitter.com/jakobkorherr
work: http://www.irian.at
14 years, 2 months