我有一个简单的CDI bean。问题是当我从JSF页面调用方法removeCustomer
时,方法getCustomers()
在removeCustome
r之前执行,而不是相反的方式。首先我认为生产者本身就是问题,但如果我将列表放在控制器中,我会得到相同的行为。当我得到响应页面时,表中的行不会被删除,而是从数据库中删除它。当我再次刷新页面时,我看不到删除的行。
@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版本。
答案 0 :(得分:1)
之前调用方法getCostumers
,因为在处理请求时多次评估EL表达式(#customers
)(链接中的更多详细信息)。
解决方案是让你的getter和setter“愚蠢”。只需让他们改变你班级的变量。避免使用具有副作用的逻辑(如customerService.findCustomers();
)。如果需要初始化,可以使用@PostConstruct
方法或JSF事件触发的方法执行初始化。
另外,考虑到使用@RequestScoped
bean,将为每个请求创建一个新的bean实例(呈现页面或保存对值的更改)。
答案 1 :(得分:0)
实际上很容易达到我想要的效果。 这是更新的CDI bean。
@Named @RequestScoped 公共类CustomersController {
@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);
}
}
如你所见。在ajax上删除客户生成器的请求在方法removeCustomer之前调用。从逻辑上讲,因为在恢复视图阶段,jsf正在恢复视图并评估EL表达式,这是在事件处理阶段之前发生的。所以我们在请求范围内有客户列表,我们需要将它注入到控制器bean中,这样我们就可以在removeCustomer方法中从列表中删除所选客户。我希望我很清楚。