2

我在我的演示应用程序中使用 JSF2+Spring3.1+Hibernate4,我想使用注释来创建会话工厂,但是我的 DAO 类没有在 Jsf Managed Bea 类中初始化,所以我得到空指针异常。我的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 对象为空,我得到空指针异常

警告:#{userMB.addUser}:java.lang.NullPointerException javax.faces.FacesException:#{userMB.addUser}:com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118) 处的 java.lang.NullPointerException ) 在 javax.faces.component.UICommand.broadcast(UICommand.java:315) 在 javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794) 在 javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:第1259章org.apache.catalina.core.ApplicationFilterChain 的 javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) 的 .execute(LifecycleImpl.java:118)。internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225) at 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.AccessLogValve.invoke(AccessLogValve.java:927) 在 org.apache.catalina.core 的 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)。 StandardEngineValve.invoke(StandardEngineValve.java:118) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) 在 org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585) 在 org.apache.tomcat.util.net 的 org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001) .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 在 javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102) 在com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) ... 23 更多原因:java。lang.NullPointerException 在 com.otv.managed.bean.UserManagedBean.addUser(UserManagedBean.java:57) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.el.parser.AstValue.invoke(AstValue.java:264)在 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 更多addUser(UserManagedBean.java:57) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)在 java.lang.reflect.Method.invoke(Method.java:597) 在 org.apache.el.parser.AstValue.invoke(AstValue.java:264) 在 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) ... 24 更多addUser(UserManagedBean.java:57) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)在 java.lang.reflect.Method.invoke(Method.java:597) 在 org.apache.el.parser.AstValue.invoke(AstValue.java:264) 在 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) ... 24 更多invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.el.parser.AstValue .invoke(AstValue.java:264) 在 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 更多invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.el.parser.AstValue .invoke(AstValue.java:264) 在 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 更多在 com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) 处调用(MethodExpressionImpl.java:278) 在 javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88) ... 24更多的在 com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) 处调用(MethodExpressionImpl.java:278) 在 javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88) ... 24更多的

4

3 回答 3

20

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

这一点有很多证据。只需在此处和/或网络上查找“JSF + spring integartion”即可。

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

许多 Web 应用程序由多个“层”组成,也称为应用程序的“层”:用于查看应用程序页面的 Web 层或表示层、用于执行应用程序和数据层的逻辑和业务规则的业务层或中间层,或持久层,用于向/从数据库传输数据。这些层可能具有以下配置:

  1. Entity将保存从您的数据库派生的数据的类,并且最合理地被诸如 Hibernate 之类的 ORM 框架使用;
  2. DAO将用于访问数据库并至少在数据库上执行 CRUD 操作的类,最重要的是为您的 Web 部件返回 Web 层的实体类;
  3. Service将反映您的应用程序提供的业务操作的类;
  4. Bean将支持您的视图的类,并且很可能包含在您的网页中使用的数据、操作方法、转换等。

下一步是为您的 Web 应用程序选择框架。

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

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

这两种选择都有其拥护者和反对者。有人说为什么要选择不是Sun 的Oracle 解决方案的原生解决方案,其他人则说它太复杂和令人困惑并且缺乏可供学习的资源。

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

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

  1. 实体类要么是 JPA/Hibernate 注释类,要么是由 xml 配置的简单 POJO。
  2. DAO 将@Repository实现基本接口以避免紧密耦合。它们将由 Spring 框架管理。
  3. 服务也将@Service实现基本接口。它们也将由 Spring 框架管理。请注意,如果您使用@Transactional.
  4. 因此,如果您想将 Bean 用作依赖注入框架,那么Bean 必须@Component并且@Scope("value")必须由 Spring 管理,从而允许通过@Autowired.

因此,NPE 源于对您的 bean 作为视图的逻辑部分应该由 JSF 管理的误解(请注意,这@ManagedProperty也不起作用)。bean 由 JSF 实例化,但您的服务驻留在 JSF 知道的 Spring 上下文中,因此无法进行注入。另一方面,如果 bean 保留在 Spring 上下文中,它的生命周期和依赖项将由 Spring 注入。

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

@Component
@Scope("request")
public class SpringManagedBeanToBeUsedByJSF {

    ...

    @Autowired
    private SpringService springService;

    ...

}

并做好将 Spring 与 JSF 结合使用的所有先决条件。如果您迷失方向,请参阅这个出色的设置示例。这样,所有 bean 都将由 Spring 管理,并且当您在 faces-config.xml 中附加 EL-resolver(允许 JSF '看到' Spring beans)和 web.xml 中的必要侦听器时,它们将在 JSF 视图中可见。当您这样做时,所有 Spring bean 都可以在 .xhtml 文件中引用,如果您需要将 JSF 操作放在 bean 中,只需将它们放在(Spring)托管 bean 中或使它们实现至关重要到JSF接口等。只有这样才能实现集成。当然,您也可以使用 JSF 托管 bean,@FacesConverter并且@FacesValidator应用程序中的类也是如此,只是不要相互干扰,但是在一个应用程序中使用两个依赖注入框架至少会令人困惑。

希望这可以帮助您更好地了解情况。

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

于 2013-02-08T17:16:49.647 回答
3

您可以尝试 UserDAO 的 ManagedProperty 注释吗

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

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

您可能还需要更改 dao 注释

@Repository("userDAO")
@Transactional
public class UserDAO
于 2013-02-08T17:15:44.233 回答
0

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

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

于 2013-02-08T06:02:16.317 回答