PrimeFaces PickList选择值触发NullPointerException问题求助
问题原因及解决方案
根因分析
NullPointerException 源于 PickListView 使用了 @RequestScoped 作用域。每次AJAX请求(比如选择事件)都会创建一个新的Bean实例。在验证阶段,PickList组件会对比旧模型(新Bean实例中@PostConstruct初始化的模型)与新模型,但选择事件并不会提交完整的PickList值,导致新模型为null,触发空指针异常。
解决方案
- 将
PickListView的作用域从@RequestScoped改为@ViewScoped,确保Bean在同一个视图的所有AJAX请求中保持状态。 - 让
PickListView实现Serializable接口,这是@ViewScoped作用域的强制要求。
修改后的 PickListView 代码:
import org.primefaces.event.SelectEvent; import org.primefaces.event.TransferEvent; import org.primefaces.event.UnselectEvent; import org.primefaces.model.DualListModel; import javax.annotation.PostConstruct; import javax.enterprise.context.ViewScoped; import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext; import javax.inject.Inject; import javax.inject.Named; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @Named @ViewScoped public class PickListView implements Serializable { @Inject private CountryService service; private DualListModel<Country> countries; @PostConstruct public void init() { //Countries List<Country> countriesSource = service.getCountries().subList(0, 10); List<Country> countriesTarget = new ArrayList<>(); countries = new DualListModel<>(countriesSource, countriesTarget); } public CountryService getService() { return service; } public void setService(CountryService service) { this.service = service; } public DualListModel<Country> getCountries() { return countries; } public void setCountries(DualListModel<Country> countries) { this.countries = countries; } public void onTransfer(TransferEvent event) { StringBuilder builder = new StringBuilder(); for (Object item : event.getItems()) { builder.append(((Country) item).getName()).append("<br />"); } FacesMessage msg = new FacesMessage(); msg.setSeverity(FacesMessage.SEVERITY_INFO); msg.setSummary("Items Transferred"); msg.setDetail(builder.toString()); FacesContext.getCurrentInstance().addMessage(null, msg); } public void onSelect(SelectEvent<Country> event) { FacesContext context = FacesContext.getCurrentInstance(); context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Item Selected", event.getObject().getName())); } public void onUnselect(UnselectEvent<Country> event) { FacesContext context = FacesContext.getCurrentInstance(); context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Item Unselected", event.getObject().getName())); } public void onReorder() { FacesContext context = FacesContext.getCurrentInstance(); context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "List Reordered", null)); } }
补充说明
@ViewScoped 作用域会在用户停留在当前视图期间保持Bean的状态,非常适合处理单页面内的AJAX交互,既避免了@RequestScoped的状态丢失问题,又不会像@SessionScoped那样长期占用资源。
内容的提问来源于stack exchange,提问作者Najlae Cherkaoui
相关产品推荐
相关产品推荐

