添加动态表单字段时出错

时间:2012-10-11 12:54:44

标签: jsf dynamic-forms view-scope

我正在尝试将动态表单字段添加到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

我的简单代码出了什么问题?提前致谢

1 个答案:

答案 0 :(得分:1)

您的bean放在视图范围内。视图范围bean存储在HTTP会话中。存储在HTTP会话中的对象需要Serializable,包括其所有属性。但是,像HtmlForm这样的UI组件是不可序列化的,其简单原因是其状态对基于请求的更改敏感,如果可序列化,则仅在反序列化后导致可能的损坏/未同步状态。

基本上,您需要将bean放在请求范围内。

但是,这整个方法过于复杂且存在缺陷。不要使用<h:form binding>。而是使用<h:dataTable>(或<ui:repeat>所以你想要的)。在这个答案中可以找到一个完整的启动示例:How to dynamically add JSF components