我正在尝试将动态表单字段添加到jsf表单。 但即使遵循简单的代码也会产生错误。
test.xhtml
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head></h:head>
<body>
<h:form id="form" binding="#{testBean.form}" />
<h:commandButton value="submit" action="#{testBean.submit}" />
</body>
</html>
Field.java
包裹实体;
公共类字段{
private String name;
public Field() {
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
testBean.java
package beans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIInput;
import javax.faces.component.html.HtmlForm;
import javax.faces.component.html.HtmlInputText;
import javax.faces.context.FacesContext;
import Entity.*;
@ManagedBean
@ViewScoped
public class testBean implements Serializable{
private static final long serialVersionUID = 770513161289990805L;
private HtmlForm form = new HtmlForm();
private List<Field> fields=new ArrayList<Field>();
private Map<String, Object> values;
private Field field1 = new Field();
private Field field2 = new Field();
public testBean() {
field1.setName("aaa");
field2.setName("bbb");
fields.add(field1);
fields.add(field2);
values = new HashMap<String, Object>();
}
private ValueExpression createValueExpression(String binding, Class clazz) {
final ValueExpression ve = getExpressionFactory()
.createValueExpression(getELContext(), binding, String.class);
return ve;
}
public static ELContext getELContext() {
return FacesContext.getCurrentInstance().getELContext();
}
public static ExpressionFactory getExpressionFactory() {
return getApplication().getExpressionFactory();
}
public static Application getApplication() {
return FacesContext.getCurrentInstance().getApplication();
}
@SuppressWarnings("el-syntax")
public HtmlForm getForm() {
if (form == null) {
form = new HtmlForm();
for (Field field : fields) {
UIInput input = new HtmlInputText();
input.setId(field.getName()); // Must be unique!
String v = "#{testBean.values['" + field.getName() + "']}";
input.setValueExpression("value",
createValueExpression(v, String.class));
form.getChildren().add(input);
}
}
return form;
}
public void setForm(HtmlForm form) {
this.form = form;
}
public List<Field> getFields() {
return fields;
}
public void setFields(List<Field> fields) {
this.fields = fields;
}
public Map<String, Object> getValues() {
return values;
}
public void setValues(Map<String, Object> values) {
this.values = values;
}
public void submit() {
System.out.println("Worked :)");
}
}
上面的代码给出了“java.io.NotSerializableException:Entity.Field”错误。
java.io.NotSerializableException: Entity.Field
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
java.io.ObjectOutputStream.writeSerialData(Unknown Source)
java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.writeObject(Unknown Source)
java.util.HashMap.writeObject(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
java.io.ObjectOutputStream.writeSerialData(Unknown Source)
java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
java.io.ObjectOutputStream.writeSerialData(Unknown Source)
java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.writeArray(Unknown Source)
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.writeObject(Unknown Source)
java.util.HashMap.writeObject(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
java.io.ObjectOutputStream.writeSerialData(Unknown Source)
java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.writeObject(Unknown Source)
com.sun.faces.renderkit.ClientSideStateHelper.doWriteState(ClientSideStateHelper.java:325)
com.sun.faces.renderkit.ClientSideStateHelper.writeState(ClientSideStateHelper.java:173)
com.sun.faces.renderkit.ResponseStateManagerImpl.writeState(ResponseStateManagerImpl.java:122)
com.sun.faces.application.StateManagerImpl.writeState(StateManagerImpl.java:166)
com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:225)
com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:419)
com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.12 logs.
如果我使Field类Serializable,它会再次出错。
HTTP Status 500 -
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
java.io.NotSerializableException: javax.faces.component.html.HtmlForm
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
java.io.ObjectOutputStream.writeSerialData(Unknown Source)
java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.writeObject(Unknown Source)
java.util.HashMap.writeObject(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
java.io.ObjectOutputStream.writeSerialData(Unknown Source)
java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
java.io.ObjectOutputStream.writeSerialData(Unknown Source)
java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.writeArray(Unknown Source)
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.writeObject(Unknown Source)
java.util.HashMap.writeObject(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
java.io.ObjectOutputStream.writeSerialData(Unknown Source)
java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
java.io.ObjectOutputStream.writeObject0(Unknown Source)
java.io.ObjectOutputStream.writeObject(Unknown Source)
com.sun.faces.renderkit.ClientSideStateHelper.doWriteState(ClientSideStateHelper.java:325)
com.sun.faces.renderkit.ClientSideStateHelper.writeState(ClientSideStateHelper.java:173)
com.sun.faces.renderkit.ResponseStateManagerImpl.writeState(ResponseStateManagerImpl.java:122)
com.sun.faces.application.StateManagerImpl.writeState(StateManagerImpl.java:166)
com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:225)
com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:419)
com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.12 logs.
Apache Tomcat/7.0.12
我的简单代码出了什么问题?提前致谢
答案 0 :(得分:1)
您的bean放在视图范围内。视图范围bean存储在HTTP会话中。存储在HTTP会话中的对象需要Serializable
,包括其所有属性。但是,像HtmlForm
这样的UI组件是不可序列化的,其简单原因是其状态对基于请求的更改敏感,如果可序列化,则仅在反序列化后导致可能的损坏/未同步状态。
基本上,您需要将bean放在请求范围内。
但是,这整个方法过于复杂且存在缺陷。不要使用<h:form binding>
。而是使用<h:dataTable>
(或<ui:repeat>
所以你想要的)。在这个答案中可以找到一个完整的启动示例:How to dynamically add JSF components