【问题标题】:Delete from list and order of execution of backing bean methods从支持 bean 方法的列表和执行顺序中删除
【发布时间】:2013-12-02 08:28:37
【问题描述】:

我有一个简单的 CDI bean。问题是当我从 JSF 页面调用方法 removeCustomer 时,方法 getCustomers()removeCustomer 之前执行,而不是相反的方式。首先,我认为生产者本身就是问题,但是如果我将列表放在控制器中,我会得到相同的行为。当我得到响应页面时,表中的行不会被删除,它会从数据库中删除。当我再次刷新页面时,我看不到已删除的行。

@Named
@RequestScoped
public class CustomersController {

    @Inject
    private CustomerService customerService;

    @Produces()
    @RequestScoped
    @Named("customers")
    public List<Customer> getCustomers() {
        return customerService.findCustomers();
    }

    /**
     * @param customerId
     */
    public String removeCustomer(Long customerId) {
        customerService.deleteCustomer(customerId);
        return null;
    }

}

<h:form id="customers-form">
    <h:dataTable value="#{customers}" var="customer"
    styleClass="table">

    <h:column>
        <f:facet name="header">#{msg['customer.name']}</f:facet>
    #{customer.name}
</h:column>

    <h:column>
        <f:facet name="header">#{msg['customer.vat']}</f:facet>
    #{customer.vat}
</h:column>
    <h:column>
        <a
            href="#{facesContext.externalContext.requestContextPath}/customers/customer.xhtml?id=#{customer.id}">#{msg['global.edit']}</a>
    </h:column>
    <h:column>
        <h:commandButton styleClass="btn btn-danger"
            action="#{customersController.removeCustomer(customer.id)}"
            value="#{msg['global.delete']}" aria-hidden="true">
            <f:ajax render="@form"></f:ajax>
        </h:commandButton>
    </h:column>
</h:dataTable>

我正在使用 JBoss WildFly beta 1,但我猜它使用的是稳定的 JSF 2.x 版本。

【问题讨论】:

    标签: jsf-2 cdi


    【解决方案1】:

    其实很容易实现我想要的。 这是更新的 CDI bean。

    @命名 @RequestScoped 公共类客户控制器 {

    @Inject
    private CustomerService customerService;
    @Inject
    private List<Customer> customers;
    
    @Produces()
    @RequestScoped
    @Named("customers")
    public List<Customer> getCustomers() {
        return customerService.findCustomers();
    }
    
    /**
     * @param customerId
     */
    public void removeCustomer(Customer customer) {
        customerService.deleteCustomer(customer.getId());
        customers.remove(customer);
    }
    

    }

    如您所见。在方法 removeCustomer 之前调用删除客户生产者的 ajax 请求。逻辑上是因为在恢复视图阶段 jsf 正在恢复视图和评估 EL 表达式,这发生在事件处理阶段之前。所以我们有请求范围内的客户列表,我们需要将其注入控制器 bean,以便我们可以在 removeCustomer 方法中从列表中删除选定的客户。我希望我已经足够清楚了。

    【讨论】:

      【解决方案2】:

      查看this answer

      之前调用了方法 getCostumers,因为在处理请求时,EL 表达式 (#customers) 被多次评估(链接中的更多详细信息)。

      解决方案是让你的 getter 和 setter 变得“愚蠢”。只需让他们更改您班级的变量即可。避免有副作用的逻辑(如customerService.findCustomers();)。如果需要初始化,可以在 @PostConstruct 方法或由 JSF 事件触发的方法中执行。

      另外,请注意对于 @RequestScoped bean,将为每个请求创建一个新的 bean 实例(渲染页面或保存对值的更改)。

      【讨论】:

      • 谢谢。我现在知道了。但无论如何我想使用请求范围。我不想使用视图范围或会话范围。怎么能这样呢?有可能吗?
      • 对不起,我专注于“正在调用 getter”问题,并没有考虑更广泛的问题。你确定你的 removeCustomer 方法被调用了吗?无论如何,看起来您需要更多 listener 而不是操作方法 (stackoverflow.com/questions/12222687/…)
      猜你喜欢
      • 2020-08-13
      • 2013-04-08
      • 2012-11-27
      • 2012-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多