I have what I thought was simple JSF navigation setup but when I hit the h:commandButton the page reloads, not the page I want to load. The faces-config snippet is here:
<navigation-rule>
<from-view-id>/index.jsf</from-view-id>
<navigation-case>
<from-outcome>hello</from-outcome>
<to-view-id>/next.jsf</to-view-id>
</navigation-case>
</navigation-rule>
the index.xhtml file contains this:
<f:view>
<a4j:region id="topRegion">
<rich:page pageTitle="myapp" markupType="xhtml" id="top">
<f:facet name="header">
<h:form>
<rich:toolBar height="45" itemSeparator="disc">
<rich:toolBarGroup location="left">
<h:form name="selectForm">
<h:panelGrid columns="5" style="padding: 2px;">
<h:outputText style="text-align: center" value="Node Select " />
<h:selectOneMenu id="nodes" value="#{MyBacking.chosenNode}">
<f:selectItems value="#{MyBacking.nodes}" />
</h:selectOneMenu>
<h:commandButton value="Retrieve" styleClass="ctrlBtn"
id="retrieveBtn" style="margin-bottom: 2px;"
action="hello"
image="/img/btnRetrieve26.png" />
</h:panelGrid>
</h:form>
</rich:toolBarGroup>
</rich:toolBar>
</h:form>
It's as simple as that. Can anyone tell me why it's not working?
As far as I'm aware, the from-outcome of hello should be used by the h:commandbutton and load next.xhtml file.
Your files are .xhtml not .jsf
have you tried:
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>hello</from-outcome>
<to-view-id>/next.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Related
I have a button, when i click a modal panel opened - it's work fine. Now i tried to add a button to hide the panel - it's work also, but the problem is when i tried to show a text "panel closed" after button click it doesn't work. I use Jsf 1.2 and richfaces 3.3.3.
I have the following error message:
org.apache.jasper.el.JspELException: /index.jsp(35,7) 'javascript:Richfaces.hideModalPanel('myModalPanel');#{welcomeBean.showText(true)}' Method not found: class com.firstjsf.backingbeans.WelcomeBean.showText(java.lang.Boolean) at org.apache.jasper.el.JspValueExpression.getValue(JspValueExpression.java:123)
above the code:
index.jsp
<%#taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%#taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%# taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%# taglib uri="http://richfaces.org/rich" prefix="rich"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<f:view>
<h:form>
<rich:panel>
<f:facet name="header">
<h:outputText value="Product"></h:outputText>
</f:facet>
<h:form>
<a4j:commandButton
id="newWid"
value="New Widget..."
immediate="true" ajaxSingle="true"
reRender="text"
oncomplete="javascript:Richfaces.showModalPanel('myModalPanel');"
styleClass="verboseButton noprint" />
</h:form>
<rich:modalPanel id="myModalPanel">
<f:facet name="header">
<h:outputLabel value="123" />
</f:facet>
From Modal Panel
<a4j:commandButton value="Hide" id="btn_hide"
oncomplete="javascript:Richfaces.hideModalPanel('myModalPanel');#{welcomeBean.setShowText(true)}" />
</rich:modalPanel>
<h:outputText id="text"
value="Panel closed"
rendered="#{helloMessage.showText eq true}">
</h:outputText>
</rich:panel>
</h:form>
</f:view>
</html>
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
version="1.2">
<managed-bean>
<managed-bean-name>welcomeBean</managed-bean-name>
<managed-bean-class>com.firstjsf.backingbeans.WelcomeBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>helloMessageBean</managed-bean-name>
<managed-bean-class>com.firstjsf.backingbeans.HelloMessageBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<navigation-rule>
<description>Welcome page to message page</description>
<from-view-id>/index.jsp</from-view-id>
<navigation-case>
<from-outcome>helloMessage</from-outcome>
<to-view-id>/message.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<description>Welcome page to message page</description>
<from-view-id>/message.jsp</from-view-id>
<navigation-case>
<from-outcome>back</from-outcome>
<to-view-id>/index.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
BeanAction
public class WelcomeBean {
private boolean showText =false;
public String sayHello(){
return "helloMessage";
}
public boolean isShowText() {
return showText;
}
public void setShowText(boolean showText) {
this.showText = showText;
}
}
You're mixing JavaScript and EL expressions, #oncomplete is for executing JavaScript, if you want to do something on the server use #action or #actionListener. Otherwise the expression will be evaluated and the browser will try to execute the return value as if it was JavaScript.
By the way, your code shows you're using setShowText(true) (which is correct), but the exception says you're using just showText(true), which is it then?
Hi i'm trying to develop my first application with j2ee using oracle jdeveloper i want to redirect a jsf page by clicking on the login button!!
this is my function in the sessionBean
public String authentification(String login, String pwd) {
try{
Query query;
query = em.createQuery("select o from UserEntity o where " + " o.login = :LOGIN AND o.pwd = :PWD");
query.setParameter("LOGIN",login);
query.setParameter("PWD",pwd);
UserEntity ue = (UserEntity) query.getSingleResult();
return"/untitled2?faces-redirect=true";
}catch(Exception e){
return "/untitled3?faces-redirect=true";
}
}
this is my button in the jsf page
<af:button actionListener="#{bindings.authentification.execute}" text="authentification"
disabled="#{!bindings.authentification.enabled}" id="b1"/>
my faces-config would be like
<faces-config version="2.1" xmlns="http://java.sun.com/xml/ns/javaee">
<application>
<default-render-kit-id>oracle.adf.rich</default-render-kit-id>
</application>
<navigation-rule>
<from-view-id>/untitled1.jsf</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/untitled2.jsf</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>fail</from-outcome>
<to-view-id>/untitled3.jsf</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
this is my untitled2.jsf
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html>
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
<af:document title="untitled2.jsf" id="d1">
<af:messages id="m1"/>
<af:form id="f1">
<af:panelGridLayout id="pgl1">
<af:gridRow height="50px" id="gr3">
<af:gridCell width="auto" halign="stretch" valign="stretch" id="gc3">
<!-- Header -->
</af:gridCell>
</af:gridRow>
<af:gridRow height="100%" id="gr1">
<af:gridCell width="auto" halign="stretch" valign="stretch" id="gc2">
<!-- Content -->
<af:panelFormLayout id="pfl1">
<af:panelFormLayout id="pfl2"
inlineStyle="background-color:transparent; width:752px; height:193px;">
<af:inputText value="#{bindings.id.inputValue}" label="#{bindings.id.hints.label}"
required="#{bindings.id.hints.mandatory}"
columns="#{bindings.id.hints.displayWidth}"
maximumLength="#{bindings.id.hints.precision}"
shortDesc="#{bindings.id.hints.tooltip}" id="it1">
<f:validator binding="#{bindings.id.validator}"/>
<af:convertNumber groupingUsed="false" pattern="#{bindings.id.format}"/>
</af:inputText>
<af:inputText value="#{bindings.pwd.inputValue}" label="#{bindings.pwd.hints.label}"
required="#{bindings.pwd.hints.mandatory}"
columns="#{bindings.pwd.hints.displayWidth}"
maximumLength="#{bindings.pwd.hints.precision}"
shortDesc="#{bindings.pwd.hints.tooltip}" id="it2">
<f:validator binding="#{bindings.pwd.validator}"/>
</af:inputText>
<af:inputText value="#{bindings.login.inputValue}" label="#{bindings.login.hints.label}"
required="#{bindings.login.hints.mandatory}"
columns="#{bindings.login.hints.displayWidth}"
maximumLength="#{bindings.login.hints.precision}"
shortDesc="#{bindings.login.hints.tooltip}" id="it3">
<f:validator binding="#{bindings.login.validator}"/>
</af:inputText>
<af:button actionListener="#{bindings.persistUserEntity.execute}"
text="persistUser" disabled="#{!bindings.persistUserEntity.enabled}"
id="b4"/>
<af:button actionListener="#{bindings.Delete.execute}" text="Delete"
disabled="#{!bindings.Delete.enabled}" id="b3"/>
<af:button text="Submit" id="b1"/>
<f:facet name="footer">
<af:button actionListener="#{bindings.Create.execute}" text="Create"
disabled="#{!bindings.Create.enabled}" id="b2"/>
</f:facet>
</af:panelFormLayout>
</af:panelFormLayout>
<af:button actionListener="#{bindings.First.execute}" text="First"
disabled="#{!bindings.First.enabled}" partialSubmit="true" id="b5"/>
<af:button actionListener="#{bindings.Last.execute}" text="Last"
disabled="#{!bindings.Last.enabled}" partialSubmit="true" id="b6"/>
<af:button actionListener="#{bindings.Next.execute}" text="Next"
disabled="#{!bindings.Next.enabled}" partialSubmit="true" id="b7"/>
<af:button actionListener="#{bindings.Previous.execute}" text="Previous"
disabled="#{!bindings.Previous.enabled}" partialSubmit="true" id="b8"/>
</af:gridCell>
</af:gridRow>
<af:gridRow height="50px" id="gr2">
<af:gridCell width="100%" halign="stretch" valign="stretch" id="gc1">
<!-- Footer -->
</af:gridCell>
</af:gridRow>
</af:panelGridLayout>
</af:form>
</af:document>
</f:view>
when i excute my page jsf i get the error Nom id introuvable dans l'objet donné : /untitled2.jsf.
I am using JSF 2.0 in a simple application. I have three beans 1st which is login is in request scope while other 2 in view scope. I have configured in faces-config.xml.
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
<from-outcome>loginSuccess</from-outcome>
<to-view-id>/pages/ReportSubmit.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>reportStatus</from-outcome>
<to-view-id>/pages/ReportStatus.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>logout</from-outcome>
<to-view-id>/pages/logout.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<managed-bean>
<managed-bean-name>UserBean</managed-bean-name>
<managed-bean-class>com.cognizant.reportgen.LoginBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>ReportBean</managed-bean-name>
<managed-bean-class>com.cognizant.reportgen.ReportGeneratorBean</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>ReportStatus</managed-bean-name>
<managed-bean-class>com.cognizant.reportgen.ReportStatusBean</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
</faces-config>
I have a menu.jsp which has below code
menu item1 <h:commandLink action="loginSuccess" value="Generate Reports"></h:commandLink>
menu item 2<h:commandLink action="reportStatus" value="Report Status"></h:commandLink>
In 2 beans, I have methods whose return type is void.
On Login request, I am creating session and setting user detail in session attribute.
Now The problem which I am facing is that
I login with user1, select menu item 1, so corresponding data is displayed.
I login with user2 in next browser window, select menu item 1, so corresponding data is displayed.
I go back to browser window1 (user1), select menu item 1 again, but now in header it displays the user2 name., Also it displays data corresponding to user2.
Please help me with this issue.
//ReportStatusBean.java
public class ReportStatusBean {
private List<ReportAttrDO> reportList;
private HtmlDataTable reportStatusTable;
// getters and setter for above included....
public void checkReportStatus(ActionEvent event) {
ReportGenService reportGenObj = new ReportGenServiceImpl();
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
UserDetail user = (UserDetail)session.getAttribute("user");
List<ReportAttrDO> reportList = reportGenObj.getReportStatusList(user.getUserId());
setReportList(reportList);
if(reportList.isEmpty())
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "No Records to display.", null));
}
public void viewReport(ActionEvent event) {
ReportAttrDO reportAttrDO = (ReportAttrDO)getReportStatusTable().getRowData();
System.out.println(reportAttrDO.getRequestHeaderId());
}
}
// ReportStatus.jsp
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%# taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
<html>
<head>
....some script functions..
</head>
<body onload="noBack();" onpageshow="if (event.persisted) noBack();" onunload="">
<center>
<div class="wrapper">
<%#include file="../include/pageheader.jsp"%>
<%#include file="../include/menu.jsp"%>
<h:form id="form2">
<table border="0">
<tr>
<td colspan="2"><h:messages style="color:red;margin:8px;" /></td>
</tr>
<tr>
<td colspan="2"><h:commandButton value="Check Status" actionListener="#{ReportStatus.checkReportStatus}" /></td>
</tr>
</table>
<c:if test="${not empty ReportStatus.reportList}" >
<div style="height:200px;width:600px;overflow:auto;">
<h:dataTable id="table" border="1"
var="row" value="#{ReportStatus.reportList}" cellpadding="5" cellspacing="5"
binding="#{ReportStatus.reportStatusTable}">
<h:column>
<f:facet name="header">
<f:verbatim>
<h:outputText value="Application Name" />
</f:verbatim>
</f:facet>
<h:outputText id="applName" value="#{row.applicationName}" ></h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<f:verbatim>
<h:outputText value="Report Name" />
</f:verbatim>
</f:facet>
<h:outputText id="reportReqName" value="#{row.reportRequestName}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<f:verbatim>
<h:outputText value="Generated Report" />
</f:verbatim>
</f:facet>
<h:commandLink id="viewReport" value="View" rendered="#{row.status == 'Completed'}" actionListener="#{ReportStatus.viewReport}"></h:commandLink>
</h:column>
</h:dataTable>
</div>
</c:if>
</h:form>
</div>
</center>
</body>
</html>
</f:view>
HTTP session is shared among browser's tabs, so what you're experiencing is an expected behaviour. When you did login in a next tab you most probably replaced the existing session attribute.
You can as well try it in different browsers, but not different tabs of the same browser, to see it work as you expect it to work. In the end, session is a per user construct and should be viewed as such. You must define the proper scopes for your beans for the application to run in accordance with your expectations and for good user experience.
Unrelated to your concrete problem, using command links that use POST requests for plain page-to-page navigation is considered to be a bad practice: you should use <h:link> instead. For details see the third reference below.
Also, using faces-config.xml to solely configure navigation rules and declare managed beans in a JSF 2.0 application is somewhat old-school, in my opinion. The last but not the least, JSP is a deprecated view technology nowadays, that was superseded by facelets, so developing new application using JSP as a view technology should be carefully rethought.
See also:
How to choose the right bean scope?;
Communication in JSF 2.0, section on bean scopes;
When should I use h:outputLink instead of h:commandLink?.
You need to render your menu conditionnaly of your session user and not your login result, for example :
<h:form>
<h:panelGroup rendered="#{not userbean.isLogged}">
<h:inputText value="#{userBean.username}" />
<h:inputText value="#{userBean.password}" />
<h:commandButton actionListener="#{userBean.login}" />
</h:panelGroup>
<h:panelGroup rendered="#{userBean.isLogged}">
<h:commandLink rendered="#{userBean.user eq "user1"}" action="loginSuccess" value="Generate Reports"></h:commandLink>
<h:commandLink rendered="#{userBean.user eq "user2"}" action="reportStatus" value="Report Status"></h:commandLink>
</h:panelGroup>
</h:form>
Of course it will require some function inside userBean to get the username for example.
Also you mean that you have configured your bean using ViewScoped, they are all RequestScoped in the code provided.
I suggest you to use .xhtml file name extensions, which is the standard in JavaServer Faces views.
I am looking for a another way of JSF navigation other than mentioning navigation-cases in faces-config.xml.
At present i am using faces-config.xml to navigate. I want to clean it up.
Please suggest all other ways so that i can use whatever suits my need.
For simple page-to-page navigation (without submitting anything) you should be using <h:outputLink> instead of <h:commandLink>.
So, instead of
<h:form>
<h:commandLink value="Page 1" action="page1" />
<h:commandLink value="Page 2" action="page2" />
<h:commandLink value="Page 3" action="page3" />
</h:form>
and those navigation cases
<navigation-rule>
<navigation-case>
<from-outcome>page1</from-outcome>
<to-view-id>page1.jsf</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>page2</from-outcome>
<to-view-id>page2.jsf</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>page3</from-outcome>
<to-view-id>page3.jsf</to-view-id>
</navigation-case>
</navigation-rule>
you should use
<h:outputLink value="page1.jsf">Page 1</h:outputLink>
<h:outputLink value="page2.jsf">Page 2</h:outputLink>
<h:outputLink value="page3.jsf">Page 3</h:outputLink>
For real form submits you should rewrite the action methods to return void or null instead of an outcome. So, instead of
<h:form>
<h:inputText value="#{bean.query}" />
<h:commandButton value="Search" action="#{bean.search}" />
</h:form>
with
public String search() {
results = searchService.find(query);
return "results";
}
on one page and
<h:dataTable value="#{bean.results}" var="result">
...
</h:dataTable>
on other page and this navigation case
<navigation-rule>
<from-view-id>search.jsf</from-view-id>
<navigation-case>
<from-outcome>results</from-outcome>
<to-view-id>results.jsf</to-view-id>
</navigation-case>
</navigation-rule>
you should use
<h:form rendered="#{empty bean.results}">
<h:inputText value="#{bean.query}" />
<h:commandButton value="Search" action="#{bean.search}" />
</h:form>
<h:dataTable value="#{bean.results}" var="result" rendered="#{not empty bean.results}">
...
</h:dataTable>
with
public void search() {
results = searchService.find(query);
}
You can if necessary include page fragments by <jsp:include>.
See also:
When should I use h:outputLink instead of h:commandLink?
//JSF
<h:outputLink value="login.xhtml" >
Login page
</h:outputLink>
//HTML output
<a href="login.xhtml">
Login page
</a>
Refer this URL for more info:-
commandLink and outputLink example
You can set the return value of a navigation action to the name of the page you want to go to (e.g. return "page2"; to switch to page2.jsf). But as far as I know, this feature has been implemented first in JSF 2.0.
I have an application that contains commandLinks within a Primefaces dataTable. The commandLinks link to other pages within the application and pass parameters. When I try to export the dataTable using Primefaces' ExcelExporter, the generated .xls file contains the value attribute for the commandLink, not the value attribute for the outputText nested within the commandLink.
Column within dataTable code:
<p:dataTable var="dataRow" id="myTable">
<p:column>
<f:facet name="header">
<h:outputText value="MyColumn" />
</f:facet>
<h:outputLink value="myPage.xhtml">
<f:param name="columnId" value="#{dataRow.columnId}" />
<h:outputText value="#{dataRow.columnName }" />
</h:outputLink>
</p:column>
</p:dataTable>
ExcelExporter code:
<h:commandLink>
<h:outputText value="Export" />
<p:dataExporter type="xls" target="myTable" fileName="tableResults"/>
</h:commandLink>
When I export the table using the ExcelExporter, the exported data is "myPage.xhtml", when I want it to be the data contained in "#{dataRow.columnId}". Is there a way to format the links so they are exported with the text that I want?
I was able to solve this problem by changing the links to commandLinks with actions that determine navigation and setPropertyActionListeners to pass parameters. It looks like PrimeFaces always takes the value from the parent component, so this seemed to be the best workaround. The dataExporter code stayed the same.
Modified xhtml code:
<p:dataTable var="dataRow" id="myTable">
<p:column>
<f:facet name="header">
<h:outputText value="MyColumn" />
</f:facet>
<h:commandLink value="#{dataRow.columnName}" action="myPage">
<f:setPropertyActionListener target="#{myPage.columnId}"
value="#{dataRow.columnId}"/>
</h:commandLink>
</p:column>
</p:dataTable>
Navigation rule added to faces-config.xml:
<navigation-rule>
<navigation-case>
<from-outcome>myPage</from-outcome>
<to-view-id>/myPage.xhtml</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>