【问题标题】:Spring Injection with JSF使用 JSF 进行 Spring 注入
【发布时间】:2012-02-11 02:23:04
【问题描述】:

我在使用 JSF 项目中的 springframework 注入带有注释的 Bean 时遇到问题。
我想我基本上做了到目前为止我发现的每个教程都说我应该做的事情,但是当我将我的战争发布到 tomcat 并尝试使用 LoginBean 中的 loginService 时,我得到了 NullPointerException。有什么想法吗?

我的 Bean(缩短):

package de.homer.server.config.beans;

import java.io.Serializable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import de.homer.server.config.user.LoginService;

@Component
@Scope("session")
public class LoginBean implements Serializable {

        @Autowired
        LoginService loginService;

    public final String doLogin() {
        // try to use loginService here
        // if I set breakpoint here I can see that loginService is null
    }

}

我的服务(缩短):

package de.homer.server.config.user;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
public class LoginService {

}

我的 applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:annotation-config />
    <context:component-scan base-package="de.homer.server.config.beans" />
    <context:component-scan base-package="de.homer.server.config.user" />
</beans>

我的 web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>homeR</display-name>

    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>


    <!-- Spring context -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <!-- JSF mapping -->
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Map these files with JSF -->
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
</web-app>

我的面孔-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC
    "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
    "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
    <application>
        <variable-resolver>
            org.springframework.web.jsf.DelegatingVariableResolver
        </variable-resolver>
    </application>
</faces-config>

如果重要的话,我的 pom.xml 的摘录

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>3.1.0.RELEASE</version>
        </dependency>

日志的最后但并非最不重要的一部分:

DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner  - Identified candidate component class: file [/home/stonedsquirrel/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/homeR-server-runtime/WEB-INF/classes/de/homer/server/config/user/LoginService.class]
...
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory  - Creating shared instance of singleton bean 'loginService'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory  - Creating instance of bean 'loginService'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory  - Eagerly caching bean 'loginService' to allow for resolving potential circular references
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory  - Finished creating instance of bean 'loginService'

和堆栈跟踪:

WARNING: #{loginBean.doLogin}: java.lang.NullPointerException
javax.faces.FacesException: #{loginBean.doLogin}: java.lang.NullPointerException
at    com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
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:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at   org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.faces.el.EvaluationException: java.lang.NullPointerException
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
... 24 more
Caused by: java.lang.NullPointerException
at de.homer.server.config.beans.LoginBean.doLogin(LoginBean.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.el.parser.AstValue.invoke(AstValue.java:262)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
... 25 more

Jan 16, 2012 9:42:26 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Faces Servlet] in context with path [/homer] threw exception [java.lang.NullPointerException] with root cause
java.lang.NullPointerException
at de.homer.server.config.beans.LoginBean.doLogin(LoginBean.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.el.parser.AstValue.invoke(AstValue.java:262)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
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:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)

【问题讨论】:

  • 完成,是我忘记的一件事 ;-)
  • @stonedsquirrel 你能发布你得到空指针的语句吗?我的理解是 loginService 不是自动装配的,因此为空。我说的对吗?
  • @AravindA 你是对的。我可以调试 doLogin() 方法并看到 loginService 为空。认为这很清楚。对不起!
  • 好吧,我慢慢开始对春天生气了。使用与上面相同的代码,我得到一个不同的错误。这次连 Bean 都没有解决。错误是 JSF 中的“目标无法访问,标识符 'loginBean' 解析为空”。最后现在错误是一致的。可能是 tomcat 正确重新发布它之前部分工作的问题。我应该编辑我的问题还是这个评论足够?我是新来的 ;-) 很抱歉打扰你们!
  • 好吧,如果我将 ManagedBean 标记添加到 LoginBean,它将在 JSF 中初始化,然后我再次获得 NullPointer。有意义,因为 ManagedBean 在 Facelet 上下文中加载并忽略了 spring 上下文。这样错误才有意义。但仍然:我做错了什么?

标签: java spring jsf maven


【解决方案1】:

我终于明白了。原来这是一个不推荐使用的 faces-config.xml 版本的问题 它适用于此配置:

faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">

<application>
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>

</faces-config>

豆子:

package de.homer.server.config.beans;

import java.io.Serializable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import de.homer.server.config.user.LoginService;

@Component
@Scope("session")
@Qualifier("loginBean")
public class LoginBean implements Serializable {

    @Autowired
    LoginService loginService;

    public final String doLogin() {
    // try to use loginService here
    // if I set breakpoint here I can see that loginService is null
    }

}

服务:

package de.homer.server.config.user;

import org.springframework.stereotype.Service;

@Service
public class LoginService {

}

感谢您的所有灵感!

【讨论】:

  • @Qualifier 的导入在哪里?
【解决方案2】:

移除自动连线选项:

在此处定义您的 Service 和 DAO bean;

@Configuration
public class ApplicationConfig {

    @Bean
    public LoginService loginService() {
        return new LoginService();
    }
}

初始化 Bean,

@Configuration
@Import( { PersistenceHibernateConfig.class, SecurityConfig.class, ApplicationConfig.class } )
public class SpringMainConfig{

}

将此参数添加到 web.xml,

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>com.ecs.esr.spring.conf.SpringMainConfig</param-value>
</context-param>

添加这个来管理bean的构造函数,

WebApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
loginService = ctx.getBean(LoginService.class);

【讨论】:

  • 好的,我想这会起作用,但这是我想要避免的。许多教程和论坛建议使用自动装配是可能的。如果我必须在每个构造函数中初始化 Bean,我可以只制作 LoginService Singleton 并在没有 spring 的情况下设置它。使用弹簧的优势在这里似乎消失了。还是我错过了什么?再次感谢您的回答。
猜你喜欢
  • 2011-08-13
  • 1970-01-01
  • 2013-12-08
  • 2011-07-06
  • 1970-01-01
  • 2011-02-06
  • 2015-03-01
  • 1970-01-01
相关资源
最近更新 更多