4

I want to use my Spring Beans in my JSF application, letting Spring inject my services/repositories in my JSF Managed Beans.

I found a lot of solutions in the Internet, but the only one that worked was the following lines of code:

ApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
albumRepository = (AlbumRepository) ctx.getBean("albumRepository");

albumRepository is the Spring Bean I'm trying to inject.

The problem is that it's really lame, I don't wanna do this in every class, for every injection. I'd like to use anotations, like "@Inject".

Searching an answer in Google, I found that I should integrate JSF and Spring using the following config in faces-config.xml:

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

Then, I should be able to use my Spring Beans with the annotation "@ManagedProperty(value="#{albumRepository}")". I tried it, but I aways get the error "The property albumRepository for the managed bean does not exist".

Searching again in Google I found out that I could use the Spring annotations to do my injections, the only thing i'd need would be to register the package where my managed beans are located in the applicationContext.xml. I've done it, but Spring just ignores my annotations (@Inject and @Autowired, I tried both).

After all these failures I tried to stop using the JSF annotations (@ManagedBean and @ViewScoped), instead, I used Spring ones (@Controller and @Scope). Now JSF doesn't even recognize the beans.

What am I doing wrong?

Edit: My ApplicationContext.xml

<context:annotation-config/>
        <jpa:repositories base-package="com.ae.repository" />
        <context:component-scan base-package="com.ae.client.web, com.ae.service" />

        <!-- Data Source -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
            <property name="url"><value>jdbc:mysql://localhost:3306/academia</value></property>
            <property name="username"><value>root</value></property>
            <property name="password"><value>root</value></property>
        </bean>

        <bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="database" value="MYSQL" />
            <property name="showSql" value="true" />
        </bean>

        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="jpaVendorAdapter" ref="jpaAdapter" />
            <property name="persistenceXmlLocation" value="/META-INF/persistence-web.xml"/>
        </bean>

        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory" />
        </bean>

Edit: My web.xml

<!-- Spring -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

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

    <!-- JSF -->
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>

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

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>

    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>

    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>server</param-value>
    </context-param>

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

    <!-- Primefaces -->
    <filter>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>
Tiago Peres França
  • 3,056
  • 2
  • 21
  • 23

2 Answers2

1

In your web.xml has context param like this ?

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/*Context.xml</param-value>
    </context-param> 

Also can you send listener about spring in your web.xml

mstzn
  • 2,881
  • 3
  • 25
  • 37
  • Thank you for the answer. In my web.xml I have: contextConfigLocation /WEB-INF/applicationContext.xml . It works as intended, it loads the application context. I don't think that's the problem. Anyway, I edited the original question to include my web.xml. – Tiago Peres França Sep 20 '12 at 16:50
  • 1
    did you check that.http://www.mkyong.com/jsf2/jsf-2-0-managed-bean-x-does-not-exist-check-that-appropriate-getter-andor-setter-methods-exist/ – mstzn Sep 20 '12 at 18:06
  • Thank you mstzn, great link! That was exactly the problem, I didn't have a setter for my "albumRepository", I thought it worked like Spring, where an "@inject" is enough, but I was wrong. I still don't know why Spring annotations don't work, but JSF's "@ManagedProperty" is good to me. I'm marking as correct answer because of the comments. – Tiago Peres França Sep 20 '12 at 20:38
0

If you want Spring IOC container to manage all your beans. Use one of @Component, @Named or javax.annotation.ManagedBean annotation and you can inject them using @Autowired or @Inject. Don't forget to use Spring's @Scope for any of those.

See Documentation

If you want to use JSF IOC container as well along with Spring IOC container, you can inject Spring beans into a JSF bean using @ManagedProperty.

See Also:

Community
  • 1
  • 1
Ravi Kadaboina
  • 8,494
  • 3
  • 30
  • 42
  • 1
    Thank you for the answer Ravi. I'd really like Spring IOC container to manage all my beans, but I tried everything and it doesn't work. I tried every annotation I could. I don't know why but I think Spring is ignoring the package containing my JSF Managed Beans (com.ae.client.web). I'm going to use JSF to manage my Spring beans, my problem was happening because I wasn't defining a setter for the injected property, it works fine now that I have a "setAlbumRepository". – Tiago Peres França Sep 20 '12 at 20:52