JSF redirect via commandButton - jsf

I cannot redirect to another page if the code is like this:
<h:commandButton type="button" value="Enter" action="index?faces-redirect=true" >
But the redirect works if the code is:
<h:commandButton type="button" value="Enter" action="index?faces-redirect=true" >
<f:ajax />
</h:commandButton>
Could anyone explain this? Thanks!
-----------------------EDIT------------------------
The entire xhtml code for your reference:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form id="form">
<h:commandButton id="enterModelButton" type="button" value="Enter" action="index?faces-redirect=true" >
<f:ajax />
</h:commandButton>
</h:form>
</h:body>
</html>

The <h:commandButton type="button"> doesn't generate a submit button. It just generates a "dead" button without any effects, purely intented to be used for custom onclick="..." scripts and like. This is somewhat a leftover of the dark JSF 1.0/1.1 era, when it wasn't nicely possible to just use plain vanilla HTML in JSF for this kind of things.
The <f:ajax> performs the submit by ajax powers through JSF-generated onclick. It doesn't care about the button's type.
Essentially, removing type="button" and relying on its default type="submit" should fix your problem.
<h:commandButton value="Enter" action="index?faces-redirect=true" />
However, all with all, if this is the real code and you don't actually intend to invoke a bean action, then you're going in completely the wrong direction as to implementing the functional requirement of navigating to a different page by a button. You should be using <h:button> instead.
<h:button value="Enter" outcome="index" />
See also:
Difference between h:button and h:commandButton
How to navigate in JSF? How to make URL reflect current page (and not previous one)

Related

JSF 2.3 Facet in Composite Component with wrong ID

I have the following simple code in a composite component (using Mojarra 2.3.9 / Primefaces 7):
<composite:implementation>
<h:form id="form">
<composite:insertChildren />
<ui:fragment rendered="#{!empty cc.facets.actions}">
<div class="actions">
<composite:renderFacet name="actions" />
</div>
</ui:fragment>
</div>
</h:form>
</composite:implementation>
And the following part is used in a page, trying to fill the composite form with life:
<cc:compForm id="mySpecialForm">
<f:facet name="actions">
<p:commandButton
id="myBtn"
value="Submit"
process="#form"
update="#form">
</p:commandButton>
</f:facet>
</cc:compForm>
The form and all the children are rendered correctly and working quite well. But the button in the renderFacet block has - in my opinion - a wrong client ID, because instead of:
mySpecialForm:form:myBtn
the button only gets the following clientId:
mySpecialForm:myBtn
This leads to an error rendering the page:
Cannot find component for expression "#form" referenced from
"mySpecialForm:myBtn".:
org.primefaces.expression.ComponentNotFoundException: Cannot find
component for expression "#form" referenced from
"mySpecialForm:myBtn".
Am i doing something wrong or is this a bug in JSF/Primefaces? I also tried to configure the componentType to an #FacesComponent extending from UIForm, but in this case no form will be rendered at all.
Update 1:
I tried to create a "minimal, reproducible example (reprex)" like mentioned by Kukeltje. All what is needed are those 2 Parts in a web application (both files under resources):
cc/compForm.xhtml:
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:composite="http://xmlns.jcp.org/jsf/composite">
<composite:interface name="compForm" displayName="A composite form">
<composite:facet name="actions" />
</composite:interface>
<composite:implementation>
<h:form id="form">
<composite:insertChildren />
<composite:renderFacet name="actions" />
</h:form>
</composite:implementation>
</html>
compFormTest.xhtml:
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:cc="http://xmlns.jcp.org/jsf/composite/cc">
<cc:compForm id="mySpecialForm">
<h:inputText id="inputParam" value="" />
<f:facet name="actions">
<h:commandButton id="myBtn" value="Test" />
</f:facet>
</cc:compForm>
</html>
All todo is call the .xhtml page: http:localhost/YOUR_APP/compFormTest.xhtml.
After using it (at least with Mojarra JSF implementation), the input field has the following correct client ID mySpecialForm:form:inputParam. But the command button retrieves another client ID outside the form: mySpecialForm:myBtn, what is a bug from my point of view, regarding the JSF VDL: " ... will be rendered at this point in the composite component VDL view.".
But as i downstriped the example files, it is clearly not a primefaces problem, because the wrong client ID is also included, if using the standard h:commandButton component.
Perhaps someone can use the mentioned 2 files above in a MyFaces environment to check if the behaviour differs or is the same?
Or has someone a workaround in mind? Using an additional #FacesComponent and moving the button from facet to the right spot under the form leads to the following "funny" duplicate ID error:
"Cannot add the same component twice: mySpecialForm:form:myBtn" (at least the client ID was what i expected in the first place)

JSF page lost style after partial update

I have some troubles with partial update of jsf 2.0 page.
I have dropdown menu with few choices. Depending on choice I show different page. When I load page first time it shows css and javascript works fine. When I change another option in dropdown menu this part of page which has been re rendered appearing without css and javascript on it doesn't work.
This is example of page itself which I using, template.xhtm and bean are pretty generic therefor I didn't include it.
<ui:composition template="/template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:h="http://java.sun.com/jsf/html">
<ui:define name="body">
<h:form>
<h:selectOneMenu value="#{bean.answer}">
<f:selectItems value="#{bean.answers}" />
<f:ajax event="change" render="includeContainer #All" />
</h:selectOneMenu>
</h:form>
<h:panelGroup id="includeContainer">
<h:panelGroup library="primefaces" name="jquery/jquery.js"
rendered="#{bean.answer == 'yes'}">
<ui:include src="answer_yes.xhtml"></ui:include>
</h:panelGroup>
<h:panelGroup rendered="#{bean.asnwer == 'no'}">
<ui:include src="answer_no.xhtml"></ui:include>
</h:panelGroup>
</h:panelGroup>
</ui:define>
</ui:composition>
One important remark regarding template that I use this statement to include css, it's located on remote server and I can't download and place it locally, it's company's policy.
<link href="http://server.com/resources/w3.css" rel="stylesheet" title="w3" type="text/css" />
Thank you in advance for your help.
You can put rendered panel group inside an <h:form id="toberendred"> and re-render this form instead of h:panelGroup.
For proper (JSF way) loading your css file from remote server you can use Omnifaces CDNResourceHandler
In addition you got some serious issues in your code:
Why use #all (fix to lowercase) with additional (includeContainer) selector? , do view source and see that you can't render <ui:include in view source you will see content of both yes and no xhtmls + <h:panelGroup got no attributes library and name...

p:commandLink not fires action

p:commandLinks with ids cl1 and cl2 do not fire actions. There is nothing on Tomcat console, nothing on Firebug console.
Where should i look for the problem in such situations, i think i am totally desperate without any error or exception, in both consoles.
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:o="http://openfaces.org/"
xmlns:p="http://primefaces.org/ui">
<h:form>
<ui:repeat var="sharing" value="#{sharingController.myList}">
<ui:repeat var="sharingComment" value="#{sharing.subCommentList}">
<p:commandLink id="cl1" value="" process="#this" action="#{reportController.reportSharingComment(sharingComment)}" style="float:right;" id="sharingComment_alert" styleClass="icon_alert" title="#{msg['label.report']}" update=":messages" >
</p:commandLink>
<p:commandLink value="" id="cl2" process="#this" action="#{sharingController.deleteComment(sharingComment)}" style="float:right;" id="sharingComment_delete" styleClass="icon_delete" title="#{msg['label.delete']}" update="#form :messages">
</p:commandLink>
</ui:repeat>
</ui:repeat>
</h:form>
</ui:composition>
I tried with a concrete list in the nested ui:repeat in post construct then commandlinks was fired, but I must iterate over field lists like sub commentlists of every sharing in myList. I'm loading both myList and for every sharing I load the subCommentlist in a for in post construct, but I still cannot make the commandLinks fire.
h:commandLink / h:commandButton is not being invoked
The 4. point solved:
Putting the bean in the view scope and/or making sure that you load the data model in (post)constructor of the bean (and thus not in the getter method!) should fix it.

How to create links relative to the right context?

I have this composition :
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:panelGroup rendered="#{empty userc.userb.user.id}">
<h:panelGrid columns="2" >
<h:outputLink value="system/register.xhtml">Register</h:outputLink>
<h:outputLink value="system/login.xhtml">Login</h:outputLink>
</h:panelGrid>
</h:panelGroup>
</ui:composition>
If the user click in Login the page is redirect to system/login.xhtml, which is correct, but if the user, click in Login again, it is redirect to system/system/login.xhtml.
I know a solution for this, which BalusC help me out a long time ago:
<base href="#{fn:replace(request.requestURL, fn:substring(request.requestURI, 1, fn:length(request.requestURI)), request.contextPath)}/" />
It solve my problem, but if I have some ManageBean instancied when I click in some link the bean it's invalidate.
How mantain the url path in every link page and keep the session in the Managed beans ?
Use <h:link> instead. JSF will append the right context path and FacesServlet mapping.
<h:link value="Register" outcome="/system/register" />
<h:link value="Login" outcome="/system/login" />
See also:
Communication in JSF 2.0 - Implicit navigation

Making p:commandButton work like h:button

I have this working code in my webapp:
<h:button value="Edit user..." outcome="/public/user" >
<f:param name="userName" value="#{authBean.authUser}"/>
</h:button>
What it does:
It makes the button send a GET
It passes the specified parameter in the URL, making it bookmarkable.
What I need:
It should work like h:button above (send GET)
the button should look like other Primefaces buttons (eg. decorated with an image... etc).
This is the closest I could get:
<p:commandButton value="Edit user..." action="/public/user?faces-redirect=true" ajax="false" immediate="true" >
<f:param name="userName" value="#{authBean.authUser}"/>
</p:commandButton>
It sends a POST that gets redirected to the new URL with a GET. However the parameter is lost in the process.
Another idea:
<p:linkButton value="Edit user..." href="http://localhost:8080/contextpath/faces/public/user.xhtml">
<f:param name="userName" value="#{authBean.authUser}"/>
</p:linkButton>
The GET request is aborted (??? according to Firebug) and the current page is POSTed again.
What is the proper way of doing this?
UPDATE: this works (on an empty page, with no p:dataTable):
<p:linkButton value="Edit user..." href="http://localhost:8080/contextpath/faces/public/user.xhtml?userName=myusername">
but this does not:
<p:linkButton value="Edit user..." href="http://localhost:8080/contextpath/faces/public/user.xhtml?userName=myusername&secondParam=otherValue">
the latter results in:
500: javax.servlet.ServletException:
Error Parsing /sample0.xhtml: Error
Traced[line: 14] The reference to
entity "secondParam" must end with the
';' delimiter.
UPDATE2: the & should be escaped:
<p:linkButton value="Edit user..." href="http://localhost:8080/contextpath/faces/public/user.xhtml?userName=myusername&secondParam=otherValue">
and it looks good... but I still get the GET aborted and POST resent:
alt text http://img64.imageshack.us/img64/1017/primefaceslinkbutton.jpg
This is the full empty page I've been trying it with:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head />
<h:body>
<h:form>
<p:linkButton value="Click me" href="http://stackoverflow.com" />
</h:form>
</h:body>
</html>
Primefaces 2.1 release.
In PrimeFaces 2.2., we'll deprecate linkButton and introduce p:button. Issue ticket;
http://code.google.com/p/primefaces/issues/detail?id=1037
Use p:linkButton.
Update: as per your update with the code example, the URL should be specified in href attribute, not in the url attribtue. Also see the component's documentation which I linked here above.
The symptoms at least sounds like as if you're firing an asynchronous (Ajax) GET request, not a synchronous one. FireBug would then indeed give this kind of error when the request is fired on a different domain.
Don't you have some other Javascripts which are disturbing/colliding with the linkButton's default behaviour? The button is navigating by a simple onclick="window.location=newurl;".
Update 2: does it work if you test it standalone in a simple page? E.g.
<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<p:linkButton value="test" href="http://stackoverflow.com" />
</h:body>
</html>

Resources