This question already has an answer here:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
(1 answer)
Closed 6 years ago.
let the following code fragment contains a link to items.xhtml that lists item names and enables the user to select an item in order to view its details:
<?xml ... ?>
<!DOCTYPE ... >
<html ... >
<h:head>
<title>Welcome</title>
</h:head>
<h:body>
<h:outputLink value="#{facesContext.externalContext.requestContextPath}/faces/client/items.xhtml">Items</h:outputLink>
</h:body>
</html>
When the user clicks the link named Items, then the request line states that the resource being requested is /javaee7-training/faces/client/items.xhtml and the desired action that should be applied to it is GET. That is fine.
The following code shows a fragment of items.xml:
<?xml ... ?>
<!DOCTYPE ...>
<html ...>
<h:head>
<title>items</title>
</h:head>
<h:body>
<h:form prependId="false">
<h:selectOneRadio value="#{bean.itemId}"
layout="pageDirection">
<c:forEach items="#{bean.items}" var="itm">
<f:selectItem itemValue="#{itm.itemno}"
itemLabel="#{itm.itemname}" />
</c:forEach>
</h:selectOneRadio>
<h:commandButton value="Details" action="item" />
</h:form>
</h:body>
</html>
Now when the user clicks the button named Details, then the request line states that the resource being requested is /javaee7-training/faces/client/items.xhtml and the desired action that should be applied to it is POST. I donĀ“t expected this result, because when the user clicks the button named Details, then the requested resource is /javaee7-training/faces/client/item.xhtml and the desired action is GET.
Could anyone explain me this result and why I am wrong?
Thank you in advance
<h:commandButton> Always fire a post request because it is supposed to inside the <h:form>. And forms are always submitted as POST request in JSF arena. If you need to fire GET request use <h:button> instead of <h:commandButton>.
Usage Example:
<h:button value="Click Me!!" outcome="item"> <!--viewId is item insted of items-->
<f:param name="item1" value="itemVal1" />
<f:param name="item2" value="itemVal2" />
</h:button>
Related
I have a problem with the JSF 2.2 Feature <f:viewAction action="#{...}/>.
I placed this tag in my XHTML-Page, it's called viewActionStart.xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<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:body>
<f:view>
<f:metadata>
<f:viewAction action="#{redirect.getView()}" onPostback="true"
immediate="true" />
</f:metadata>
</f:view>
<h:outputText value="If you see that text, the viewAction was not performed." />
</h:body>
</html>
If I visit this XHTML-Page directly, everything works fine: The method redirect.getView() is called and a redirect to another page is performed.
Now I have my landing page, that is shown before that viewActionStart-Page. There is a button, that basically should navigate to my viewActionStart-Page to show the <f:viewAction> effect. The following code is from this landing page index.xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<f:view>
<h:form>
<h:commandButton action="viewActionStart.xhtml"
value="To f:viewAction Page" />
</h:form>
</f:view>
</h:body>
</html>
If I hit that command button, the content of the viewActionStart.xhtml is shown. Why does JSF ignore the <f:viewAction>? I do not understand why the viewAction does not work on every page load. I tried around with those onPostback and "immediate" attributes, but nothing changes.
Another weird result is, that after I hit the command button and see the content of viewActionStart.xhtml the URL still remains on localhost:8080/UIIncludeTest/index.xhtml. But shouldn't look this URL like localhost:8080/UIIncludeTest/viewActionStart.xhtml after the command button does navigation?
Am I doing something wrong? Or do I simply misunderstood <f:viewAction>? The weird thing, is, that it works if I browse directly to viewActionStart.xhtml.
I'm trying to get this working on:
JSF-2.2.6
Tomcat-7.0.47
PrimeFaces 5.0
I have read the numerous posts related to <f:viewAction> but nothing helped.
The <f:viewAction onPostback="true"> applies only on postbacks on the very same view. I.e. it runs only when a <h:form> in the very same view has been submitted. The <f:viewAction> is never intented to be executed upon POST navigation triggered by a submit of a <h:form> of another view. Moreover, the term "postback" in the attribute name also confirms this. This term means in web development world "a POST request on the URL of the page itself".
You need to open it by a GET request instead of a POST request. Replace the <h:commandButton> by <h:button>:
<h:button outcome="viewActionStart.xhtml" value="To f:viewAction Page" />
(note: the <h:form> is not necessary anymore)
Or, if you really intend to perform a POST request first for some unclear reason (it would have been a bit more understandable if you were invoking a bean action method, but you're here merely navigating, so the whole POST request doesn't make any sense), then let it send a redirect:
<h:commandButton action="viewActionStart.xhtml?faces-redirect-true" value="To f:viewAction Page" />
Either way, the URL should now be properly reflected in address bar. This was at its own indeed a strong hint that you was donig things the wrong way ;)
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
Difference between h:button and h:commandButton
I have a problem with the JSF 2.2 Feature <f:viewAction action="#{...}/>.
I placed this tag in my XHTML-Page, it's called viewActionStart.xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<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:body>
<f:view>
<f:metadata>
<f:viewAction action="#{redirect.getView()}" onPostback="true"
immediate="true" />
</f:metadata>
</f:view>
<h:outputText value="If you see that text, the viewAction was not performed." />
</h:body>
</html>
If I visit this XHTML-Page directly, everything works fine: The method redirect.getView() is called and a redirect to another page is performed.
Now I have my landing page, that is shown before that viewActionStart-Page. There is a button, that basically should navigate to my viewActionStart-Page to show the <f:viewAction> effect. The following code is from this landing page index.xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<f:view>
<h:form>
<h:commandButton action="viewActionStart.xhtml"
value="To f:viewAction Page" />
</h:form>
</f:view>
</h:body>
</html>
If I hit that command button, the content of the viewActionStart.xhtml is shown. Why does JSF ignore the <f:viewAction>? I do not understand why the viewAction does not work on every page load. I tried around with those onPostback and "immediate" attributes, but nothing changes.
Another weird result is, that after I hit the command button and see the content of viewActionStart.xhtml the URL still remains on localhost:8080/UIIncludeTest/index.xhtml. But shouldn't look this URL like localhost:8080/UIIncludeTest/viewActionStart.xhtml after the command button does navigation?
Am I doing something wrong? Or do I simply misunderstood <f:viewAction>? The weird thing, is, that it works if I browse directly to viewActionStart.xhtml.
I'm trying to get this working on:
JSF-2.2.6
Tomcat-7.0.47
PrimeFaces 5.0
I have read the numerous posts related to <f:viewAction> but nothing helped.
The <f:viewAction onPostback="true"> applies only on postbacks on the very same view. I.e. it runs only when a <h:form> in the very same view has been submitted. The <f:viewAction> is never intented to be executed upon POST navigation triggered by a submit of a <h:form> of another view. Moreover, the term "postback" in the attribute name also confirms this. This term means in web development world "a POST request on the URL of the page itself".
You need to open it by a GET request instead of a POST request. Replace the <h:commandButton> by <h:button>:
<h:button outcome="viewActionStart.xhtml" value="To f:viewAction Page" />
(note: the <h:form> is not necessary anymore)
Or, if you really intend to perform a POST request first for some unclear reason (it would have been a bit more understandable if you were invoking a bean action method, but you're here merely navigating, so the whole POST request doesn't make any sense), then let it send a redirect:
<h:commandButton action="viewActionStart.xhtml?faces-redirect-true" value="To f:viewAction Page" />
Either way, the URL should now be properly reflected in address bar. This was at its own indeed a strong hint that you was donig things the wrong way ;)
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
Difference between h:button and h:commandButton
This question already has answers here:
Retaining GET request query string parameters on JSF form submit
(2 answers)
Closed 8 years ago.
After days of googling I must give up and ask for help. I have xhtml page with jsf tags. Whole page is controlled by PageController.java. Important thing is that controller takes item Id and page number from url parameters. Beside that I have small form which contains current logged user information or username and password input if no one is logged in. I would like have possibility to log in or log out user using that form. But when I call either user logIn() or logOut() function from user controller parameters from url just missing. I've already tried using h:commandbutton and h:commandlink as well. I managed to send parameters via f:param tag but they still missing from url (that's problem because I need bookmarking here). tags like h:link, h:button or h:outputLink cannot be used because they don't allow me to call controller function on click.
Thanks for any help.
Edit:
I forgot to mention, I've tried to solve this via f:ajax. Problem is after log in I cannot log out without refreshing page. This same with other direction.
Edit II:
I will show sample code illustrating the problem. In my project I have template.html which is simple page template containing header, footer, aside menu, and main content. It probably have not influence at the problem I've met. My code looks like that:
<?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:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
<f:metadata>
<f:event type="preRenderComponent" listener="#{PageController.init()}"/>
</f:metadata>
<ui:composition template="/template.xhtml">
<ui:define name="aside-menu">
<h:form id = "sidemenuform">
<h:panelGrid rendered="#{usersController.isLoggedIn()}" columns="1">
<h:commandLink value="LogOut" >
<f:param name="orderId" value="${PageController.groupId}"/>
<f:param name="page" value="${PageController.PageNumber}"/>
</h:commandLink>
</h:panelGrid>
<h:panelGrid rendered="#{!usersController.isLoggedIn()}" columns="1">
<h:outputLabel for="usernameInput" value="#{bundle.LogginUsernameLabel}: "/>
<h:inputText id="usernameInput" value="#{usersController.username}"/>
<h:outputLabel for="passwordInput" value="#{bundle.LogginPasswordLabel}:">
</h:outputLabel>
<h:inputSecret id="passwordInput" value="#{usersController.password}"/>
<h:commandButton action="#{usersController.login()}">
<f:param name="orderId" value="${PageController.GroupNumber}"/>
<f:param name="page" value="${PageController.PageNumber}"/>
</h:commandButton>
</h:panelGrid>
</h:form>
</ui:define>
<ui:define name="body">
<div id="navBar">
<ul>
<li class="previousPage">
<h:commandLink action="#{PageController.previous}" rendered="#{PageController.pagination.hasPreviousPage}">
</h:commandLink>
</li>
<li class="nextPage">
<h:commandLink action="#{PageController.next}" rendered="#{PageController.pagination.hasNextPage}">
</h:commandLink>
</li>
</ul>
</div>
<ui:repeat value="#{PageController.items}" var="item" varStatus="status">
<!-- List of items in group divided into pages -->
</ui:repeat>
</ui:define>
</ui:composition>
PageController.previous and PageController.next functions working well because they returning url with GET parameters as string which looks like:
Page?groupId=1&PageNumber=2&faces-redirect=true
But userController knows nothing about them, neither about page which we currently show. So functions Login and Logout can not return url. Both functions return void. The problem is that when I fire these functions after page reload my address url changed from
/Project/faces/groups/Page.xhtml?groupId=534?pageNumber=1
To
/Project/faces/groups/Page.xhtml
And then init function fail. How to prevent this behavior??
h:link and h:button create javascript links, there's no chance to use them for invoking server side methods. What you need is to POST the server with user credentials and later on invoke a REDIRECT if the login process is correct. Your best is to use a page controller for the current view and a user controller which has the session info for the logged user. You can easily inject one bean into the other one:
#ManagedBean
#SessionScoped
public class UserController{
public boolean doLogin(String email, String password){
//Do your internal request here
}
}
#ManagedBean
#ViewScoped
public class PageController{
//You'll need a setter for this
#ManagedProperty(value=#{userController})
private UserController userController;
public String doLogin(){
if (userController.doLogin(email, password)){
return "page?groupId=" + groupId + "PageNumber=" +
pageNumber +"faces-redirect=true";
}
else{
//Add some faces message describing the error
}
}
}
That way you make the process transparent for the view, which will only acess page controller methods.
Try using f:viewParams inside your f:metadata tags:
<f:metadata>
<f:viewParam name="orderId" value="${PageController.groupId}"/>
<f:viewParam name="page" value="${PageController.PageNumber}"/>
</f:metadata>
and append ?includeViewParams=true to the url returned by userController.login() and userController.logout(). This should append the view parameters to the url automatically.
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
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>