Spring DAO不是在JSF托管bean中注入的

时间:2013-02-08 05:36:35

标签: spring hibernate jsf-2

我在我的演示应用程序中使用JSF2 + Spring3.1 + Hibernate4,我想使用注释来创建会话工厂,但是我的DAO类没有在Jsf Managed Bea类中初始化,所以我得到Null指针异常。 我的 applicationContext.xml

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

<context:annotation-config></context:annotation-config>

    <context:component-scan base-package="com.otv"></context:component-scan>


    <!-- Data Source Declaration -->
    <bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"  >
        <property name="driverClass" value="org.postgresql.Driver" />   
        <property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/postgres" />   
        <property name="user" value="postgres" />   
        <property name="password" value="hariom" /> 
        <property name="maxPoolSize" value="10" />
        <property name="maxStatements" value="0" />
        <property name="minPoolSize" value="5" /> 
    </bean>

    <!-- Session Factory Declaration -->
    <bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean ">
        <property name="dataSource" ref="DataSource" />
        <property name="annotatedClasses">
            <list>
                <value>com.otv.model.User</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
          <property name="packagesToScan" value="com.otv.user"></property>
    </bean>


    <!-- Transaction Manager is defined -->
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager" >
       <property name="sessionFactory" ref="SessionFactory"/>
    </bean>


  <!-- Enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="txManager"/>

</beans>

UserDAO.java类

package com.otv.user.dao;

import java.util.List;

import com.otv.model.User;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * 
 * User DAO
 * 
 * @author onlinetechvision.com
 * @since 25 Mar 2012
 * @version 1.0.0
 *
 */

@Repository
@Transactional
public class UserDAO   {

    @Autowired
    private SessionFactory sessionFactory;

    /**
     * Get Hibernate Session Factory
     * 
     * @return SessionFactory - Hibernate Session Factory
     */
/*  public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    *//**
     * Set Hibernate Session Factory
     * 
     * @param SessionFactory - Hibernate Session Factory
     *//*
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }*/



    /**
     * Add User
     * 
     * @param  User user
     */
    public void addUser(User user) {
        sessionFactory.getCurrentSession().save(user);
    }

    /**
     * Delete User
     * 
     * @param  User user
     */
    public void deleteUser(User user) {
        sessionFactory.getCurrentSession().delete(user);
    }

    /**
     * Update User
     * 
     * @param  User user
     */
    public void updateUser(User user) {
        sessionFactory.getCurrentSession().update(user);
    }

    /**
     * Get User
     * 
     * @param  int User Id
     * @return User 
     */
    public User getUserById(int id) {
        List list = sessionFactory.getCurrentSession()
                                            .createQuery("from User where id=?")
                                            .setParameter(0, id).list();
        return (User)list.get(0);
    }

    /**
     * Get User List
     * 
     * @return List - User list
     */
    public List<User> getUsers() {
        List list = sessionFactory.getCurrentSession().createQuery("from User").list();
        return list;
    }

}

和我的managedBean类

package com.otv.managed.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;

import com.otv.model.User;
import com.otv.user.dao.UserDAO;
import com.otv.user.service.IUserService;

/**
 * 
 * User Managed Bean
 * 
 * @author onlinetechvision.com
 * @since 25 Mar 2012
 * @version 1.0.0
 *
 */
@ManagedBean(name="userMB")
@RequestScoped
public class UserManagedBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final String SUCCESS = "success";
    private static final String ERROR   = "error";

    //Spring User Service is injected...


    List<User> userList;

    private int id;
    private String name;
    private String surname;

      @Autowired
      private UserDAO userDAO;
    /**
     * Add User
     * 
     * @return String - Response Message
     */
    public String addUser() {
        try {
            User user = new User();
            user.setId(getId());
            user.setName(getName());
            user.setSurname(getSurname());
            userDAO.addUser(user);
            return SUCCESS;
        } catch (DataAccessException e) {
            e.printStackTrace();
        }   

        return ERROR;
    }

    /**
     * Reset Fields
     * 
     */
    public void reset() {
        this.setId(0);
        this.setName("");
        this.setSurname("");
    }

    /**
     * Get User List
     * 
     * @return List - User List
     */
    public List<User> getUserList() {
        userList = new ArrayList<User>();
        userList.addAll(userDAO.getUsers());
        return userList;
    }

    /**
     * Get User Service
     * 
     * @return IUserService - User Service
     */

    /**
     * Set User List
     * 
     * @param List - User List
     */
    public void setUserList(List<User> userList) {
        this.userList = userList;
    }

    /**
     * Get User Id
     * 
     * @return int - User Id
     */
    public int getId() {
        return id;
    }

    /**
     * Set User Id
     * 
     * @param int - User Id
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     * Get User Name
     * 
     * @return String - User Name
     */
    public String getName() {
        return name;
    }

    /**
     * Set User Name
     * 
     * @param String - User Name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Get User Surname
     * 
     * @return String - User Surname
     */
    public String getSurname() {
        return surname;
    }

    /**
     * Set User Surname
     * 
     * @param String - User Surname
     */
    public void setSurname(String surname) {
        this.surname = surname;
    }

}

现在在Managedbean方法中,DAO对象为null,我得到空指针异常

  

警告:#{userMB.addUser}:java.lang.NullPointerException   javax.faces.FacesException:#{userMB.addUser}:   java.lang.NullPointerException at   com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)     在javax.faces.component.UICommand.broadcast(UICommand.java:315)at   javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)     在   javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)     在   com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)     在com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)at   com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)     在javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)at   org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)     在   org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)     在   org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)     在   org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)     在   org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)     在   org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)     在   org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)     在   org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)     在   org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)     在   org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)     在   org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)     在   org.apache.coyote.AbstractProtocol $ AbstractConnectionHandler.process(AbstractProtocol.java:585)     在   org.apache.tomcat.util.net.JIoEndpoint $ SocketProcessor.run(JIoEndpoint.java:312)     在   java.util.concurrent.ThreadPoolExecutor中的$ Worker.runTask(ThreadPoolExecutor.java:886)     在   java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:908)     在java.lang.Thread.run(Thread.java:662)引起:   javax.faces.el.E​​valuationException:java.lang.NullPointerException at   javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)     在   com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)     ... 23更多引起:java.lang.NullPointerException at   com.otv.managed.bean.UserManagedBean.addUser(UserManagedBean.java:57)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)     在java.lang.reflect.Method.invoke(Method.java:597)at   org.apache.el.parser.AstValue.invoke(AstValue.java:264)at at   org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)     在   com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)     在   javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)     ......还有24个

3 个答案:

答案 0 :(得分:20)

简而言之,您的bean应该由JSF或Spring完全管理。

这方面有很多证据。只需寻找&#34; JSF + spring integartion&#34;在这里和/或在网上。

现在让我考虑一下这个问题,以加强你的理解。

许多网络应用程序包含多个层次&#39;也被称为&#39;等级&#39;应用程序:用于查看应用程序,业务层或中间层页面的Web层或表示层,用于执行应用程序和数据层的逻辑和业务规则,或者用于将数据传输到数据库或从数据库传输数据的持久层。这些层可能具有以下配置:

  1. Entity类将保存从您的数据库派生的数据,并且最常见的是由Hibernate等ORM框架使用;
  2. DAO类将用于访问数据库并至少对数据库执行CRUD操作,最重要的是为您的Web部件返回Web层的实体类;
  3. Service将反映您的应用程序提供的业务操作的类;
  4. Bean类将备份您的视图,并且很可能包含您网页中使用的数据,操作方法,转换等。
  5. 下一步是为您的Web应用程序选择框架。

    1. 您为所有图层选择Spring,这意味着您的DAO将是@Repository个类,您的服务将是@Service个类,而您的Bean将是@Component个类。您很可能会使用像Hibernate这样的ORM框架来处理数据库,因此您的实体将是以Hibernate风格正确配置的JPA @Entity类。你的视图技术很可能是Spring MVC,它被精心设计用于Spring核心。例如,Mkyong有很多关于使用Spring的简单教程。

    2. 您为所有图层选择原生JSF + EJB框架,这意味着您的DAO和服务将是@EJB个类,您的bean将成为@ManagedBean个类。您很可能还将Hibernate用作ORM解决方案和JPA提供程序,并将通过EntityManager进行数据库访问。您的视图技术将是JSF,因为它自然地旨在与上述技术一起使用。例如,BalusC有很多关于使用JSF的启发性教程。

    3. 这两种选择都有其拥护者和反对者。有人说,为什么选择一些不是本土的东西<打击>太阳的甲骨文的解决方案,其他人说它过于复杂和混乱,缺乏可供学习的资源。

      由于这不是技术选择上的争议,我不会在这里详细讨论,但会指出Spring是一个轻量级容器,可以运行在像Tomcat这样的简单servlet容器上,而EJB需要像Glassfish这样的应用服务器来运行。我认为这是将JSF作为基于组件的Web框架和Spring作为轻量级依赖注入和业务层框架相结合的主要推动力。

      当我们决定将两个框架集成在一起时,我将解释集成如何工作以及NPE发生的原因。

      1. 实体类将是JPA / Hibernate注释类或xml配置的简单POJO。
      2. DAO将@Repository实现基接口以避免紧密耦合。它们将由Spring框架管理。
      3. 服务将@Service也实现基接口。它们也将由Spring框架管理。请注意,如果使用@Transactional标记服务方法,Spring框架将为您提供开箱即用的事务管理。
      4. 因此,Bean必须是@Component@Scope("value"),如果您想将其用作依赖注入框架,则必须由Spring管理,允许通过@Autowired访问您的服务和其他bean 。
      5. 因此,NPE源于误解,您的bean作为视图的逻辑部分应该由JSF管理(请注意@ManagedProperty也不会起作用)。 bean由JSF实例化,但是你的服务驻留在JSF知道的Spring上下文中,使得注入不可能。另一方面,如果bean保留在Spring上下文中,它的生命周期和依赖关系将由Spring注入。

        因此,要使其工作,请将bean标记为

        @Component
        @Scope("request")
        public class SpringManagedBeanToBeUsedByJSF {
        
            ...
        
            @Autowired
            private SpringService springService;
        
            ...
        
        }
        

        并制定使用Spring和JSF的所有先决条件。如果您失去跟踪,请咨询this excellent example以获取设置。这样,所有bean都将由Spring管理,并且当您在faces-config.xml中附加EL-resolver时允许在JSF视图中显示(允许JSF访问&#39;查看&#39; Spring bean)和必要的侦听器web.xml中。当你这样做时,所有的Spring bean都可以在.xhtml文件中引用,如果你需要将JSF操作放在bean中,只需将它们放在(Spring)托管bean中,或者让它们实现至关重要到JSF接口等。只能通过这种方式实现集成。当然,您也可以在应用程序中使用JSF托管bean,@FacesConverter@FacesValidator类,只是不要相互干扰它们,但是使用两个依赖注入框架和一个应用程序至少是混乱。

        希望这有助于您更好地了解情况。

        您的代码也存在一些问题,我不会在这个一般性答案中强调。

答案 1 :(得分:3)

您可以尝试使用UserDAO的ManagedProperty注释

@ManagedProperty("#{userDAO}")
private UserDAO userDAO;

private void setUserDAO(UserDAO userDAO){
this.userDAO=userDAO;
}

您可能还需要更改dao注释

@Repository("userDAO")
@Transactional
public class UserDAO

答案 2 :(得分:0)

从applicationContext.xml中删除bean声明。当您使用@Repository注释UserDao时,spring容器将从中创建一个单独的bean。这应该可以解决你的问题。

从applicationContext.xml中删除它:<bean id="UserDAO" class="com.otv.user.dao.UserDAO"> </bean>