2

我有这些简单的页面:

列表.xhtml

<h:form id="form">  
    <h:dataTable value="#{testBean.model}" var="elem">
        <h:column>
            <f:facet name="header">code</f:facet>
            #{elem.code}
        </h:column>
        <h:column>
            <f:facet name="header">description</f:facet>
            #{elem.description}
        </h:column>
        <h:column>
            <f:facet name="header">action</f:facet>
            <h:commandButton action="#{testBean.edit(elem)}" value="edit"/>
        </h:column>
    </h:dataTable>
</h:form>

编辑.xhtml

<h:form id="form">
    <h:panelGrid columns="2">
        <h:outputLabel value="code"/>
        <h:inputText value="#{testBean.selection.code}"/>

        <h:outputLabel value="description"/>
        <h:inputText value="#{testBean.selection.description}"/>
    </h:panelGrid>

    <h:commandButton action="#{testBean.update}" value="update"/>
</h:form>

这个豆子:

@ManagedBean
public class TestBean implements Serializable
{
    private static final long serialVersionUID = 1L;

    @EJB
    private PersistenceService service;
    private Object selection;
    private List<UnitType> model;

    @PostConstruct
    public void init()
    {
        model = service.findAll(UnitType.class);
    }

    public String edit(Object object)
    {
        System.out.println(Tracer.current(object));
        setSelection(object);
        return "edit";
    }

    public String update()
    {
        System.out.println(Tracer.current(selection));
        return "list";
    }

    // getters and setters
}

所以表格被渲染,当我单击“编辑”按钮之一时,它导航到“edit.jsf”显示填充输入,但是当我单击“更新”按钮时,它给了我这个错误:

javax.el.PropertyNotFoundException: /test2/edit.xhtml @27,54 value="#{testBean.selection.code}": Target Unreachable, 'null' returned null

请注意,我知道如何实现 @ViewScoped 接口来管理 CRUD 操作,但这是一个简单的概念证明,我需要更好地理解 JSF 生命周期。

所以我希望“testBean”成为@RequestScoped


更新尝试f:viewParam,仍然不明白......

列表.xhtml

<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>test list</title>
    </h:head>

    <h:body>
        <h:messages/>

        <h:form id="form">
            <h:dataTable value="#{testBean2.model}" rows="10" var="elem">
                <h:column>
                    <f:facet name="header">converterString</f:facet>
                    #{elem.converterString}
                </h:column>
                <h:column>
                    <f:facet name="header">first name</f:facet>
                    #{elem.firstName}
                </h:column>
                <h:column>
                    <f:facet name="header">last name</f:facet>
                    #{elem.lastName}
                </h:column>
                <h:column>
                    <f:facet name="header">action</f:facet>
                    <h:commandButton action="#{testBean2.edit}" value="edit">
                        <f:param name="entity" value="#{elem.converterString}"/>
                    </h:commandButton>
                    <h:commandButton action="#{testBean2.edit2}" value="edit2">
                        <f:param name="entity" value="#{elem.converterString}"/>
                    </h:commandButton>
                </h:column>
            </h:dataTable>
        </h:form>
    </h:body>
</html>

编辑.xhtml

<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
    <f:metadata>
        <f:viewParam id="entityParam" name="entity" value="#{testBean2.selection}" converter="entityConverter" required="true"/>
    </f:metadata>

    <h:head>
        <title>test edit</title>
    </h:head>

    <h:body>
        <h:messages/>

        <h:form id="form">
            <h:panelGrid columns="2">
                <h:outputLabel value="selection"/>
                <h:outputText value="#{testBean2.selection.converterString}"/>

                <h:outputLabel value="firstName"/>
                <h:inputText value="#{testBean2.selection.firstName}"/>

                <h:outputLabel value="lastName"/>
                <h:inputText value="#{testBean2.selection.lastName}"/>
            </h:panelGrid>

            <h:commandButton action="#{testBean2.update}" value="update" ajax="false">
                <f:param name="entity" value="#{testBean2.selection.converterString}"/>
            </h:commandButton>
        </h:form>
    </h:body>
</html>

testBean2.java

@ManagedBean
public class TestBean2 implements Serializable
{
    private static final long serialVersionUID = 1L;

    @EJB
    private PersistenceService service;

    private Object selection;
    private List<Person> model;

    @PostConstruct
    public void init()
    {
        Tracer.out();
        model = service.queryAll(Person.class);
    }

    public String edit()
    {
        JsfUtils.addSuccessMessage("edited");
        return "edit";
    }

    public String edit2()
    {
        JsfUtils.addSuccessMessage("edited");
        return "edit?faces-redirect=true&amp;includeViewParams=true";
    }

    public void update()
    {
        Tracer.out(selection);
        JsfUtils.addSuccessMessage("updated");
    }

    // getters and setters
}

如果我按“编辑”按钮,它会转到edit页面,但选择为空,并且没有显示任何消息。

如果我按下“edit2”按钮,它会转到edit页面,但选择为空,显示所需的消息并且 url 是edit.jsf?entity=

我究竟做错了什么?

4

3 回答 3

1

据我了解,当您的第二个请求来到 testBean 时,选择对象为空。如果您使用会话 bean 运行它,您可能不会收到此错误。

于 2012-08-16T12:05:49.730 回答
0

在我看来,没有干净的方法可以实现您想要的。

我建议您只需在请求之间传递一个 Id attr 作为一个简单的请求参数。因此,在您的后期构造函数中,检查是否设置了参数值并基于此,在您的持久层中执行查看。

或者,使用您已有的设置,绑定:

<h:inputText value="#{testBean.selection.code}"/>

组件到您的支持 bean 并getValue()在必要时调用它。无论哪种方式,仍然不整洁。

如果您发现任何其他方式,请告诉我们。

于 2012-08-28T03:45:46.087 回答
0

最后我找到了一种方法:数据将在一个长范围内,简称为bean。

请注意,这只是概念证明,而不是真实用例。并且在处理@RequestScopebean时要注意PrimeFaces 惰性 DataTable 模型范围

@ManagedBean
public class TestBean
{
    @EJB
    private PersistenceService service;

    @ManagedProperty("#{viewScope.item}")
    private Item item;

    @ManagedProperty("#{sessionScope.model}")
    private EntityDataModel<Item> model;

    @PostConstruct
    public void init()
    {
        if(model == null)
        {
            model = new EntityDataModel<Item>(Item.class);
            Faces.setSessionAttribute("model", model);
        }
    }

    public String update()
    {
        Faces.getFlash().setKeepMessages(true);

        try
        {
            item = service.update(item);
            Faces.setViewAttribute("item", item);

            JsfUtils.addSuccessMessage("updated");

            return "view?faces-redirect=true&includeViewParams=true";
        }
        catch(Exception e)
        {
            e.printStackTrace();
            JsfUtils.addErrorMessage(e);
        }

        return null;
    }

    // getters and setters, other actions, ...
}

列表.xhtml

<p:dataTable value="#{testBean.model}" var="elem" ...>
    ...

    <p:column exportable="false" toggleable="false" headerText="#{bundle.actions}">

        <!-- two techniques available for navigation -->

        <p:button outcome="view?id=#{elem.converterString}" icon="#{icons.view}" />

        <p:commandButton rendered="#{user.isEditAllowed(elem)}"
            action="edit?faces-redirect=true&amp;includeViewParams=true" process="@form"
            icon="#{icons.edit}">
            <f:param name="id" value="#{elem.converterString}" />
        </p:commandButton>
    </p:column>
</p:dataTable>

视图.xhtml

<f:metadata>
    <o:viewParam id="itemId" name="id" value="#{viewScope.item}" required="true"
        converter="entityConverter" />
</f:metadata>

<ui:composition template="/WEB-INF/templates/template.xhtml">
    <ui:define name="content">
        <p:panelGrid columns="2">
            <h:outputLabel value="#{bundle.name}" />
            <h:outputText value="#{item.name}" />

            ...
        </p:panelGrid>

        <p:button outcome="list" value="#{bundle.list}" icon="#{icons.list}" />

        <p:button rendered="#{user.isEditAllowed(item)}" 
            outcome="edit?id=#{item.converterString}" value="#{bundle.edit}"
            icon="#{icons.edit}" />
    </ui:define>
</ui:composition>

编辑.xhtml

<f:metadata>
    <o:viewParam id="itemId" name="id" value="#{viewScope.item}" required="true"
        converter="entityConverter" />
</f:metadata>

<ui:composition template="/WEB-INF/templates/template.xhtml">
    <ui:define name="content">
        <p:panelGrid columns="2">
            <h:outputLabel value="#{bundle.name}" />
            <h:panelGroup>
                <p:inputText id="name" value="#{item.name}" />
                <p:message for="name" />
            </h:panelGroup>

            ...
        </p:panelGrid>

        <p:commandButton process="@form" update="@form" action="#{testBean.update}" 
            value="#{bundle.update}" icon="#{icons.update}" />

        <p:button outcome="view?id=#{item.converterString}" value="#{bundle.cancel}" 
            icon="#{icons.cancel}" />
    </ui:define>
</ui:composition>
于 2014-11-04T09:02:44.170 回答