Hi Jay,
Thanks for your response. I am using MyFaces 1.1.3. You are right about the
"immediate" attribute of the Previous button bypassing lifecycle events. It
looks like this:
<h:commandButton action="#{registrationController.onActionPrevious}"
actionListener="#{registrationController.updateInputValues}" immediate="true"
value="#{menuResources[previousMenuItemData.labelKey.resourceKeyName]}"
rendered="true" disabled="false"
title="#{menuResources[previousMenuItemData.tooltipKey.resourceKeyName]}"
type="submit" style="font-size: x-small" />
Even if I make the input controls "immediate" the values entered by the user
are never updated back to the model/backing bean. In fact I traced the
lifecycle phases here and when the user presses the "Previous" button the
following sequence of lifecycle event occurs:
RESTORE_VIEW(1)
APPLY_REQUEST_VALUES(2)
RENDER_REPONSE(6)
PROCESS_VALIDATIONS(3) (even of "immediate" input components) and
UPDATE_MODEL_VALUES(4) phases appear to be skipped. This is all pretty-much as
expected, which is why I've added the actionListener on the Previous button
(see above) which invokes the following logic to persist the entered values
back into the model:
public void updateInputValues( ActionEvent event )
{
FacesContext facesContext = FacesContext.getCurrentInstance();
UIViewRoot uiViewRoot = facesContext.getViewRoot();
uiViewRoot.processUpdates( facesContext );
}
Again, this works fine and the values entered by the user are persisted back to
the model when they hit the "Previous" button. I did notice that *only* values
which pass validation are persisted back to the model though, so there must be
some validation which gets run, I just don't see it in my Phase Event Logger.
Strangely enough, after breaking it down more carefully, here is what generates
the exception. I can only assume that it is a bug:
1. Put the follow 2 input controls on my JSP page:
<h:outputText value="#{formResources.firstNameLabel}"/>
<h:inputText id="firstName" immediate="true"
value="#{registrationPersonalInfoView.firstName}"
title="#{formResources.firstNameTooltip}" required="true">
<f:validateLength minimum="1" maximum="50" />
</h:inputText>
<h:message styleClass="errorMessageStyle" for="firstName" tooltip="true"
showSummary="false" showDetail="true" />
<h:outputText value="#{formResources.middleNameLabel}"/>
<h:inputText id="middleName" immediate="true"
value="#{registrationPersonalInfoView.middleName}"
title="#{formResources.middleNameTooltip}" required="true">
<f:validateLength minimum="1" maximum="50" />
</h:inputText>
<h:message styleClass="errorMessageStyle" for="middleName" tooltip="true"
showSummary="false" showDetail="true" />
2. Enter a valid value into one of them and leave the other one blank
3. The user then hits the "Previous" button and the exception is generated
If they enter a value into BOTH of the fields or NEITHER of the fields
everything is fine and no exception occurs. It only happens if they enter a
value into one of them and not the other.
-------------- Original message --------------
From: "Jay Balunas" <[EMAIL PROTECTED]>
Hello,
I'm taking a look at the code, but I need to know what version of myfaces you
are using?
My initial thought is that by having the immediate set to true on the previous
button you are bypassing some of the life cycle events (validation of
non-immediate components). But you have immediate & required input components
so they are validated prior to the previous button.
The validation would fail because they are required. This is what I'm
suspecting is the issue. Because with the validation failing - future events
may be nulling out. But because the command button is also immediate it may
still try to process. This may be a bug that the immediate input components
fail validation - and the command still tries to execute - but I'm not sure.
Try to take out the immediate setting on the inputs - it should keep them from
being validated, but still be set in the "update model".
The wiki page on this discusses some other items too.
You have probably already seen this but it contains alot of this information.
http://wiki.apache.org/myfaces/How_The_Immediate_Attribute_Works
-Jay
On 1/29/07, [EMAIL PROTECTED] < [EMAIL PROTECTED]> wrote:
(I posted this to the "dev" email list by accident, so I am reposting here with
a bit more information...)
I am implementing a multi-step registration wizard which functions as follows:
1. Uses one backing bean per wizard page
2. Uses Tomahawk saveState to save model data between pages
3. "Next" button performs full-validation on all required and critical input
fields for each page
4. "Previous" button navigates back to the previous wizard page, without
performing any validation. However, if the user has entered any values on the
page, it pushes those values into the model/backing bean before navigating to
the previous page
I am using the "immediate" attribute on the "required" input components, along
with the "immediate" attribute on the "Previous" commandButton component, as
well as an actionListener which invokes a method to processUpdates() on the
UIViewRoot when the button is clicked. All this works fine, the user's entries
are saved to the model and restored when the come back to the page (even though
they have not been validated yet), and validation occurs when they hit the
"Next" button on every page.
Here's my problem though:
When the user navigates to a new page and does not enter ANY data for the
"required"/"immediate" input fields, then clicks the "Previous" button a Null
Pointer exception is thrown during the applyRequestValues() phase (see stack
trace below). However, if they actually enter data into each of the
"required"/"immediate" input fields everything works just fine. Also, if I
remove the "required" attribute, then the exception disappears but of course
there is no validation which runs when the user subsequently clicks the "Next"
button either so that is not really an option. Any ideas? I have set
breakpoints in many places, but cannot figure out exactly why this exception is
being thrown or how to get around it.
javax.servlet.ServletException
javax.faces.webapp.FacesServlet.service(FacesServlet.java:156)
org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:144)
root cause
java.lang.NullPointerException
javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:112)
javax.faces.component.UIViewRoot.processDecodes
(UIViewRoot.java:136)
org.apache.myfaces.lifecycle.LifecycleImpl.applyRequestValues(LifecycleImpl.java:219)
org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:71)
javax.faces.webapp.FacesServlet.service
(FacesServlet.java:137)
org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:144)