Eclipse运行JSF动态Web项目报Faces Servlet空指针异常如何解决?
问题描述
我在Eclipse中运行动态Web项目时遇到报错,具体场景如下:我在NewUserBean类中添加了@ManagedBean(name = "newUserBean")注解,在xhtml文件中调用该newUserBean,未在face-config.xml中添加任何配置。
控制台错误日志
Kas 30, 2021 11:11:06 AM com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException SEVERE: Error Rendering View[/index.xhtml] javax.el.ELException: /index.xhtml: java.lang.NullPointerException at com.sun.faces.facelets.compiler.AttributeInstruction.write(AttributeInstruction.java:94) at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82) at com.sun.faces.facelets.compiler.UILeaf.encodeAll(UILeaf.java:183) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859) at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:456) at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133) at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:543) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:688) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:609) at com.sun.faces.facelets.compiler.AttributeInstruction.write(AttributeInstruction.java:89) ... 31 more Kas 30, 2021 11:11:06 AM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet [Faces Servlet] in context with path [/Aident] threw exception [null] with root cause java.lang.NullPointerException at createBeans.NewUserBean.createUser(NewUserBean.java:159) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748)

补充说明
- 原先网页可以正常加载,在xhtml文件的注册按钮上添加
actionListener="#{newUserBean.createUser()}"属性后,网页无法正常显示,仅出现白屏。 - 附加报错信息:
Kas 30, 2021 12:03:09 PM com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException
SEVERE: Error Rendering View[/index.xhtml]
Kas 30, 2021 12:03:09 PM com.sun.faces.context.ExceptionHandlerImpl throwIt
INFO: Exception when handling error trying to reset the response.
Kas 30, 2021 12:03:09 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Faces Servlet] in context with path [/Aident] threw exception [null] with root cause
解决方案
从错误日志可以定位到根因是*NewUserBean类的createUser方法第159行出现空指针异常,可按照以下步骤排查修复:
- 首先查看NewUserBean.java第159行代码,检查该行所有调用属性/方法的对象是否完成初始化,常见空值场景包括:
- 注入的依赖对象(
@EJB/@Inject/@ManagedProperty注解修饰的属性)未成功注入 - 方法内部定义的对象未实例化直接调用方法/属性
- 前端传递的参数为空,后端未做空值校验直接调用
- 注入的依赖对象(
- 检查
actionListener写法是否规范:actionListener对应的方法需要接收ActionEvent参数,如果你不需要事件参数,应该用action属性而非actionListener,修改方式二选一:- 保留无参createUser方法,将按钮属性修改为
action="#{newUserBean.createUser()}" - 保留
actionListener属性,修改createUser方法定义为public void createUser(ActionEvent event),同时导入javax.faces.event.ActionEvent包
- 保留无参createUser方法,将按钮属性修改为
- 检查ManagedBean的作用域注解是否配置:仅添加
@ManagedBean没有加作用域注解时默认是@RequestScoped,页面渲染、提交请求过程中可能出现对象重新实例化导致属性为空,根据业务场景补充@ViewScoped/@SessionScoped等对应作用域注解即可 - 完成修改后清空浏览器缓存、清理Tomcat工作目录重启项目验证
内容的提问来源于stack exchange,提问作者Furkan Basoglu

