I have done JSF work before, but am new to RichFaces. To test my set up and environment, etc. I have tried to make just a simple little app where the user enters two numbers, clicks a button, and the app returns the sum and product of the numbers.
Here's the code summary:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>eSPAR</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<!-- Plugging the skin into the project -->
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>deepMarine</param-value>
</context-param>
<!-- Making the RichFaces skin spread to standard HTML controls -->
<context-param>
<param-name>org.richfaces.CONTROL_SKINNING</param-name>
<param-value>enable</param-value>
</context-param>
</web-app>
Next:
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/jav开发者_运维知识库aee"
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">
<application></application>
</faces-config>
In other words, basically empty except for the version declarations. Next comes the view page:
addmult.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<f:view 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:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<h:head>
</h:head>
<h:body>
<rich:panel header="Sample Add and Multiply App">
<h:form id="addmultForm">
<p>Enter one number here:
<rich:inputNumberSpinner id="num1" minValue="0"
value="# {calcBean.number1}" /></p>
<p>Enter another number here:
<rich:inputNumberSpinner id="num2" minValue="0"
value="#{calcBean.number2}" /></p>
<a4j:commandButton value="Go" action="#{calcBean.go}" immediate="true">
<f:ajax event="click" render="results" />
</a4j:commandButton>
<br /><br />
<h:panelGroup id="results">
<h:panelGroup rendered="#{calcBean.calcDone}">
<p>The sum of your two numbers is: #{calcBean.sum}</p>
<p>The product of your two numbers is: #{calcBean.product}</p>
</h:panelGroup>
</h:panelGroup>
</h:form>
</rich:panel>
</h:body>
</f:view>
Now finally the bean:
CalcBean.java
import javax.faces.bean.ManagedBean;
@ManagedBean
public class CalcBean {
private Integer number1 = 3;
private Integer number2 = 7;
private int sum;
private int product;
private boolean calcDone = false;
public Integer getNumber1() {
System.out.println("I am number1: " + number1);
return number1;
}
public void setNumber1(Integer number1) {
System.out.println("Change in number1");
this.number1 = number1;
}
public Integer getNumber2() {
return number2;
}
public void setNumber2(Integer number2) {
this.number2 = number2;
}
public int getSum() {
return sum;
}
public int getProduct() {
return product;
}
public boolean isCalcDone() {
System.out.println("Returning calcDone: " + calcDone);
return calcDone;
}
public String go() {
System.out.println("Going!");
sum = number1 + number2;
product = number1 * number2;
calcDone = true;
return null;
}
}
My WEB_INF lib contains: commons-beanutils-1.8.3, commons-collections-3.2.1, commons-digester-2.1, commons-logging-1.1.1, cssparser-0.9.5, guava-r08, jhighlight-1.0, jsf-api (mojarra 2.0 version), jsf-facelets-1.1.15, jsf-impl (again mojarra 2.0), richfaces-components-api-4.0.0-FINAL, richfaces-components-ui-4.0.0-FINAL, richfaces-core-api-4.0.0-FINAL, richfaces-core-impl-4.0.0-FINAL, sac-1.3, standard.
Whatever values I initiate the Integers number1 and number2, those are the values initially in the inputs when the page loads. The lower text is initially hidden. When the "Go" button is clicked, the lower panel appears, but no matter what values the user has entered, the sum is always 10 and the product always 21 (as shown).
The sysout in the setter never displays. The one in the getter displays once when the page loads. When "Go" is clicked, the sysout "Going!" shows once, then "Returning calcDone: true" shows six times.
What I have tried: Changing the scope of the bean. Wrapping the expressions in the results panel in <h:outputText>
. Adding the FaceletViewHandler in web.xml (actually causes more problems). Removing the facelet jar file from the lib.
Do I need a value change listener on the inputs? What else should I try?
<a4j:commandButton value="Go" action="#{calcBean.go}" immediate="true">
<f:ajax event="click" render="results" />
</a4j:commandButton>
Remove immediate="true"
. It will cause the inputs which do not have immediate="true"
to be completely skipped in processing. Also remove <f:ajax>
as <a4j:commandButton>
already uses ajax. To get a better understanding what immediate
does and what you need it for, I suggest you to get yourself through this article : Debug JSF lifecycle (yes, it's JSF 1.2 targeted, but general concept applies on JSF 2.x as well)
Here's a summary of relevance:
Okay, when should I use the immediate attribute?
If it isn't entirely clear yet, here's a summary, complete with real world use examples when they may be beneficial:
If set in
UIInput
(s) only, the process validations phase will be taken place in apply request values phase instead. Use this to prioritize validation for theUIInput
component(s) in question. When validation/conversion fails for any of them, the non-immediate components won't be validated/converted.If set in
UICommand
only, the apply request values phase until with update model values phases will be skipped for any of theUIInput
component(s). Use this to skip the entire processing of the form. E.g. "Cancel" or "Back" button.If set in both
UIInput
andUICommand
components, the apply request values phase until with update model values phases will be skipped for any of theUIInput
component(s) which does not have this attribute set. Use this to skip the processing of the entire form expect for certain fields (with immediate). E.g. "Password forgotten" button in a login form with a required but non-immediate password field.
So, you ultimately want this:
<a4j:commandButton value="Go" action="#{calcBean.go}" render="results" />
Unrelated to the concrete problem: there are more pretty serious problems in your configuration. I have the impression that you're reading JSF 1.x and RichFaces 3.x targeted tutorials/documentation instead of JSX 2.x and RichFaces 4.x targeted ones. The first <context-param>
is mandatory for JSF 1.x Facelets only and the remnant is all specific to RichFaces 3.x. Remove them all. You also have an offending JSF 1.x jsf-facelets.jar
file which should be removed as well as JSF 2.x already bundles a JSF 2.x Facelets implementation.
精彩评论