Redirect from an action with onstart attribute - jsf

I noticed that since I defined an onstart behavior in my button, navigation rules are ignoring me.
My button:
<p:commandButton
id="btnSend"
value="#{txt['button.send']}" process="#form"
immediate="true"
action="#{controller.goToSend}"
onstart="generate();">
</p:commandButton>
and my faces-config:
<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
<from-action>#{controller.goToSend}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/private/menu/lists/index.xhtml</to-view-id>
<redirect include-view-params="true">
<view-param>
<name>back</name>
<value>1</value>
</view-param>
</redirect>
</navigation-case>
</navigation-rule>
If I remove the onstart attribute it works.
What do you think?

Related

h:commandButton's action not being invoked [duplicate]

This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 5 years ago.
i'm using JSF 2.0 and I'm having a commandButton inside div section in home.xhml. it's not working. I don't see the destinationPage, remaining only in home.xhtml.
home.xhmtl:
<div id="left_side">
<ui:include src="login.xhtml" />
<h:form>
<h:commandButton value="register" action="register"/>
</h:form>
</div>
register.xhtml is inside a h:body and a h:form
and the faces-config.xml configuration:
<navigation-rule>
<from-view-id>home.xhtml</from-view-id>
<navigation-case>
<from-outcome>register</from-outcome>
<to-view-id>register.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
If home.xhtml and register.xhtml are at the root of your application, then you need to define the navigation rule as follows:
<navigation-rule>
<from-view-id>/home.xhtml</from-view-id>
<navigation-case>
<from-outcome>register</from-outcome>
<to-view-id>/register.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Otherwise you add the path relative to the root.. which would be indicated by a backlash
Update
Actually in your case it seems that you do not really need the POST request which is generated by thecommandButton. A simple button which would generate a GET request seems to be sufficient:
<h:button outcome="register" value="register" />

JSF FlowFaces Unable to find matching navigation case from view ID 'CURRENT_PAGE' for outcome '<FLOW_NAME>'

I have created a JSF Flow. My definition is as follows:
<flow-definition id="registration">
<initializer>#{registrationBean.initializeFlow}</initializer>
<start-node>personalDetails</start-node>
<view id="personalDetails">
<vdl-document>/registration/personal-details.xhtml</vdl-document>
</view>
<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
<from-outcome>registration</from-outcome>
<to-view-id>/registration/personal-details.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/registration/personal-details.xhtml</from-view-id>
<navigation-case>
<from-outcome>next</from-outcome>
<to-view-id>/registration/cultural-details.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/registration/cultural-details.xhtml</from-view-id>
<navigation-case>
<from-outcome>previous</from-outcome>
<to-view-id>/registration/personal-details.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>next</from-outcome>
<to-view-id>/registration/profile-details.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/registration/profile-details.xhtml</from-view-id>
<navigation-case>
<from-outcome>previous</from-outcome>
<to-view-id>/registration/cultural-details.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>next</from-outcome>
<to-view-id>/registration/preview.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/registration/preview.xhtml</from-view-id>
<navigation-case>
<from-outcome>previous</from-outcome>
<to-view-id>/registration/profile-details.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/registration-complete.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<flow-return id="cancel">
<from-outcome>cancel</from-outcome>
</flow-return>
<finalizer>#{registrationBean.finalizeFlow}</finalizer>
</flow-definition>
When I move through the Faces Flow, there are no problems in the actual flow pages, but the template is outputting a strange error:
Unable to find matching navigation case from view ID '/registration/personal-details.xhtml' for outcome 'registration'
Where /registration/personal-details.xhtml is the current file name and registration is the name of the current Flow Scope.
The rendered link I have in my menu is also rendered as:
Sign Up
Outside the flow, or:
Sign Up: This link is disabled because a navigation case could not be matched.
Inside the flow.
At the same time, the Glassfish log is giving me this:
Warning: JSF1064: Unable to find or serve resource, /registration/registration.xhtml.
This registration.xhtml doesn't exist, but I thought I could override the default file name by changing the <start-node> in the config.
Is there a way I can keep my file structure with the non-default value and get this working? What exactly is the problem?
It seems that the first view must be registration.xhtml (or <FLOW_NAME>.xhtml in general), so I can get rid of the error message, and technically this "answers" my question, but I would prefer to be able to name my views as I see fit, and not have to default if possible, so I'll hold out for a while on selecting an answer in case anybody has any better input on this matter.
You can rename the start page (or use any arbitrary faces page in any directory) using the FlowBuilder inside a #Producer method instead of XML configuration.
See: https://blog.oio.de/2014/02/12/a-comprehensive-example-of-jsf-faces-flow/
This would require switching from face-config.xml to code based configuration... Faces/directory based configuration is not very flexible and requires sticking to the standard convention.

Navigation rule not firing

I have a navigation rule that looks like this:
<navigation-rule>
<display-name>forgotPwd</display-name>
<from-view-id>/login/forgotpwd.jsf</from-view-id>
<navigation-case>
<from-outcome>pass</from-outcome>
<to-view-id>/login/pwdresetcomplete.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>fail</from-outcome>
<to-view-id>/login/forgotpwd.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
So I do this to trigger the navigation rule:
Navigate to /login/forgotpwd.jsf?uuid=fed8b3f7-ed33-4941-8306-3d2afbb8d1d0
This page has the following form:
<h:form id="resetForm">
<!-- Omitting the login fields -->
<h:commandButton type="submit" id="resetPassword" value="Save" styleClass="btn small" action="#{registration.resetPassword}" >
<f:param name="uuid" value="#{facesContext.externalContext.requestParameterMap.uuid}" />
</h:commandButton>
</h:form>
(Takes the uuid passed as a query string parameter, and will call the registration.resetPassword function.)
Here is the registration.resetPassword java code:
(Details omitted for brevity)
public String resetPassword() {
// If good
return "pass";
// If bad
return "fail"
}
Problem: When it returns "pass", the navigation rule is not firing. It goes back to /login/forgotpwd.jsf instead of /login/pwdresetcomplete.jsf
Is this because it has the UUID parameter appended to it? Why is my navigation not firing?
Is there some log4j logging that I can trigger to see why this isn't working?
<from-view-id>/login/forgotpwd.jsf</from-view-id>
The from-view-id must be the view ID, not the virtual URL. So, it should not contain .jsf extension.
<from-view-id>/login/forgotpwd.xhtml</from-view-id>
By the way, request parameters are in the view available by #{param}. This saves some characters as compared to #{facesContext.externalContext.requestParameterMap}.
<f:param name="uuid" value="#{param.uuid}" />
See also implicit objects in EL. Another by the way, it's not exactly clear which JSF version you're using, but since JSF 2.0 (which I guess you're using as you're on Facelets already) you don't need the navigation case XML hell anymore. You can just return the (relative and/or extension-less) to-view-id directly from the action method.
public String resetPassword() {
// If good
return "pwdresetcomplete";
// If bad
return "forgotpwd"
}
This way you can get rid of the whole <navigation-rule>. See also implicit navigation.
I added these two rules... now it works. Not sure which one did it but using the from-action made it a lot more happy.
<navigation-rule>
<display-name>forgotPwd</display-name>
<from-view-id>/login/forgotpwd.xhtml</from-view-id>
<navigation-case>
<from-action>#{registration.resetPassword}</from-action>
<from-outcome>pass</from-outcome>
<to-view-id>/login/pwdresetcomplete.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-action>#{registration.resetPassword}</from-action>
<from-outcome>fail</from-outcome>
<to-view-id>/login/forgotpwd.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<display-name>forgotPwd</display-name>
<from-view-id>/login/forgotpwd.jsf</from-view-id>
<navigation-case>
<from-action>#{registration.resetPassword}</from-action>
<from-outcome>pass</from-outcome>
<to-view-id>/login/pwdresetcomplete.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-action>#{registration.resetPassword}</from-action>
<from-outcome>fail</from-outcome>
<to-view-id>/login/forgotpwd.xhtml</to-view-id>
</navigation-case>
</navigation-rule>

Richfaces 4 fileUpload redirect following uploadcomplete

I would like to redirect to another page following the upload of a single file. The source xhtml and destination xhtml are in the same directory. I have tried returning a String in the fileUploadListenerMethod:
public String loadFills(FileUploadEvent event) throws Exception {
return "treeOrderRequestStatus";
}
but this does not result in a redirect.
I have also tried accomplishing it via faces-config.xml:
<navigation-rule>
<from-view-id>/userpages/manualDataLoad.xhtml</from-view-id>
<navigation-case>
<from-action>#{manualDataLoader.loadFills}</from-action>
<to-view-id>/userpages/treeOrderRequestStatus.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/userpages/manualDataLoad.xhtml</from-view-id>
<navigation-case>
<from-outcome>treeOrderRequestStatus</from-outcome>
<to-view-id>/userpages/treeOrderRequestStatus.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
and neither of these worked.
Finally, I have tried executing a link triggered by the uploadcomplete event:
<rich:fileUpload fileUploadListener="#{manualDataLoader.loadFills}"
maxFilesQuantity="1" createTempFiles="false" uploadLabel="Import Fill Data"
addLabel="Select Fill File">
<a4j:ajax event="uploadcomplete" execute="redirect"/>
</rich:fileUpload>
<h:link id="redirect" outcome="treeOrderRequestStatus"/>
and still no dice. In each of these attempts I have tried multiple different combinations of specifying the destination page (e.g.: including the .xhtml extension, including the directory, ...) but have not yet succeeded.
What am I doing wrong?
The execute attribute tag is to define the components that will be sent in the request to the server. You can try clicking a link/button using the uploadcomplete JavaScript method from the <rich:fileUpload> tag component:
<rich:fileUpload fileUploadListener="#{manualDataLoader.loadFills}"
maxFilesQuantity="1" createTempFiles="false" uploadLabel="Import Fill Data"
addLabel="Select Fill File">
<a4j:ajax event="uploadcomplete" onbegin="document.getElementById('yourFormName:redirect').click();" />
</rich:fileUpload>
<h:commandButton id="redirect" action="treeOrderRequestStatus" style="display: none"
tabindex="-1" />
Also, it would be better if you erase those navigation rules in your faces-config.xml to keep the file clean of needless configurations.

Navigation to same page in JSF1.2

I am having a h:commandButton button named cancel on a JSF1.2 page, when a user press this button he should be redirected to the same page. How it can be achieved in JSF1.2?
First remember to set immediate="true" attribute, by default, the tag will invoke all the validators etc.., before invoking the application.
Your button:
<h:commandButton value="cancel" action="cancel" title="Cancel this page" />
Your faces-context.xml:
<navigation-rule>
<from-view-id>index.xhtml</from-view-id>
<navigation-case>
<from-outcome>cancel</from-outcome>
<to-view-id>index.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>

Resources