Spring DAO is not injected in JSF managed bean

后端 未结 3 919
长情又很酷
长情又很酷 2020-12-24 11:29

I am using JSF2+Spring3.1+Hibernate4 in my demo application and i will want to use annotation to create session factory but my DAO class is not initialize in Jsf Managed Bea

相关标签:
3条回答
  • 2020-12-24 11:51

    Remove bean declaration from your applicationContext.xml. As you have annotated UserDao with @Repository the spring container will create a singleton bean out of it. This should solve your problem.

    Remove this from applicationContext.xml :<bean id="UserDAO" class="com.otv.user.dao.UserDAO"> </bean>

    0 讨论(0)
  • 2020-12-24 12:02

    To put it short, your beans should be completely managed either by JSF or by Spring.

    There is much evidence to this point. Just look for "JSF + spring integartion" here and/or on the web.

    Now let me contemplate on the issue to enhance your understanding.

    Many web applications consist from several 'layers' also called as 'tiers' of the application: web tier, or presentation tier for viewing pages of your application, business tier, or middle tier for executing logic and business rules of your appication and data tier, or persistece tier for tranferring data to/from your database. These tiers might have the following configuration:

    1. Entity classes that will hold data derived from your database and most plausibly used by an ORM framework like Hibernate;
    2. DAO classes that will be used to access database and at least perform CRUD operations on the database and most importantly for your web part return Entity classes for your web tier;
    3. Service classes that will reflect business operations you application provides for;
    4. Bean classes that will back up your views and will most probably contain data, action methods, transformations etc. used in your web pages.

    The next step is the choice of framework for your web application.

    1. You choose Spring for all layers which means that your DAOs will be @Repository classes, your Services will be @Service classes and your Beans will be @Component classes. You will most probably use an ORM framework like Hibernate to deal with the database, so your Entities will be JPA @Entity classes properly configurated in Hibernate style. Your view technology will most probably be Spring MVC that was elaborated to work with Spring core. For example, Mkyong has many simple tutorials on using Spring.

    2. You choose native JSF+EJB framework for all layers which means that your DAOs and Services will be @EJB classes your beans will be @ManagedBean classes. You will most probably also use Hibernate as ORM solution and JPA provider and will do database access via EntityManager. Your view technology will be JSF as it was naturally intended to be used with the abovementioned technologies. For example, BalusC has many enlightening tutorials on using JSF.

    Both choices has its advocates and opponents. Some say that why choose something not native to Sun's Oracle's solution, others say that it is too complex and confusing and lacks sources to learn from.

    As this is not a dispute on technology choice I will not go into details here, but will point out that Spring is a lightweight container that will run on simple servlet containers like Tomcat whereas EJBs need an application server like Glassfish to run on. I think that this is the major driving force for combining JSF as a component-based web framework and Spring as a lightweight dependency injection and business tier framework.

    As we decided to integrate both frameworks together, I will explain how the integration works and why NPEs occur.

    1. Entity classes will either be JPA/Hibernate annotated classes or simple POJOs configured by xml.
    2. DAOs will be @Repository implementing base interfaces to avoid tight coupling. They will be managed by the Spring framework.
    3. Services will be @Service also implementing base interfaces. They will also be managed by the Spring framework. Note that Spring framework will provide for out-of-the-box transaction management for you if you mark service methods with @Transactional.
    4. Beans therefore must be @Component and @Scope("value") and must be managed by Spring if you want to use it as a dependency injection framework, allowing to access your services and other beans via @Autowired.

    So, the NPE stems from misunderstanding that your beans, as a logical part of the view, should be managed by JSF (note that @ManagedProperty wouldn't work as well). The bean gets instantiated by JSF, but your service resides in Spring context that JSF knows noting about, making injection not possible. On the other hand, if the bean remains within Spring context, its lifecycle and dependencies will be injected by Spring.

    So, to make it work, mark the bean as

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

    and make all the prerequisites of using Spring with JSF. Consult this excellent example for settings if you lose track. This way, all of the beans will be managed by Spring and will be visible in JSF views when you attach EL-resolver in faces-config.xml (allowing JSF to 'see' Spring beans) and necessary listeners in web.xml. When you do it like this, all of the Spring beans can be referenced in .xhtml files and if you need to put the JSF action in the bean, just go ahead and place them in the (Spring) managed beans or make them implement vital to JSF interfaces, etc. The integration can be achieved only this way. Of course, you can also use JSF managed beans, @FacesConverter and @FacesValidator classes in the application as well, just do not interfere them with each other, but using two dependency injection frameworks withing one application is at least confusing.

    Hope this helps you in understanding the situation better.

    There are also some problems with your code I would not stress out in this general answer.

    0 讨论(0)
  • 2020-12-24 12:04

    Can you try ManagedProperty annotation for UserDAO

    @ManagedProperty("#{userDAO}")
    private UserDAO userDAO;
    
    private void setUserDAO(UserDAO userDAO){
    this.userDAO=userDAO;
    }
    

    You may need to change dao annotation as well

    @Repository("userDAO")
    @Transactional
    public class UserDAO
    
    0 讨论(0)
提交回复
热议问题