jsf:调用managedbean中的方法给出异常

时间:2014-11-24 05:49:17

标签: spring jsf-2 primefaces

当我尝试通过以下xhtml中的代码访问托管bean的登录方法时:

<p:commandButton value="Login" update="growl"
                                actionListener="#{loginView.login}"/>

我的LoginView类看起来像这样:

@Component
@ManagedBean(name="loginView",eager=true)
@SessionScoped
public class LoginView {
@Autowired
LoginService loginServiceImpl;
Student student=loginServiceImpl.login(username, password);

 public void login(ActionEvent event) {
        RequestContext context = RequestContext.getCurrentInstance();
        FacesMessage message = null;
        boolean loggedIn = false;
if(username != null && student!=null && password != null ) {
loggedIn=True;

try {
                FacesContext.getCurrentInstance()
                .getExternalContext()
                .redirect(location);
            } catch (IOException e) {

                e.printStackTrace();
            }
}
}

当我打电话按下按钮时,它给出了以下错误:

javax.el.ELException: /login1.xhtml @105,62 actionListener="#{loginView.login}": java.lang.NullPointerException
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:111)
at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:147)
at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:818)
at javax.faces.component.UICommand.broadcast(UICommand.java:300)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1008)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at org.primefaces.showcase.view.menu.LoginView.login(LoginView.java:62)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.el.parser.AstValue.invoke(AstValue.java:278)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
... 26 more

奇怪的是,当我评论这条线时

Student student=loginServiceImpl.login(username, password);

代码运行正常。我希望我的bean都是两个,基于Spring,因为我想要自动装载loginServiceImpl和jsf,因为我想调用我的方法。如果不可能,我应该选择什么方法。

2 个答案:

答案 0 :(得分:1)

您不能通过在JSF托管bean中使用@Autowired来注入Spring bean。

你应该改为

@ManagedProperty(value="#{something}")
private LoginService loginServiceImpl; // getter and setter.

另见: Null pointer when autowiring the bean into JSF Managed bean

答案 1 :(得分:1)

感谢wittakarn花时间回答这个问题,但它部分地回答了这个问题。我研究了这个主题,并在同一here

上发现了一篇非常好的文章

我们无法在JSF托管bean中使用@Autowired注入spring bean,因为JSF bean是可序列化的,而Spring bean则不是这样。 @wittakarn采取的方法很好,除了有一个问题。在loginService的setter中,我必须创建一个新的loginService对象并给它引用&#34;这个&#34;类,松耦合的所有概念都破了!

相反,有一个好方法。 Spring希望它的bean不可连接。因此,首先我们必须使loginService成为一个非序列化的属性,使其成为瞬态,然后在init方法中调用externalContext并将自动装配的功能赋予&#34;这个&#34;类。代码如下所示:

@Autowired
    transient LoginService loginServiceImpl;
    @PostConstruct
    private void init() {
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        ServletContext servletContext = (ServletContext) externalContext.getContext();
        WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext).
        getAutowireCapableBeanFactory().
        autowireBean(this);
    }

猜猜是什么!!它正在工作:)