15

I would like to use jsf annotations and some spring annotations to inject a spring bean/service into a jsf managed bean. (on the jsf bean i only want to use jsf annotations) I dont want to use annotations like @named / @inject.

I have tried to find a solution on the net but without any luck.

Example

@ManagedBean
@ViewScoped 
public class MyBean {

    @ManagedProperty(value = "#{mySpringBean}")
    private MySpringBean mySpringBean;

    public void setMySpringBean(MySpringBean mySpringBean) {
        this.mySpringBean = mySpringBean;
    }

    public void doSomething() {
    //do something with mySpringBean
    }
}

Is something like this possible without the use of xml. For example, I would NOT like to use something like

FacesContextUtils.getWebApplicationContext(context).getBean("MySpringBean");

or in faces-config.xml

<managed-bean>
    <managed-bean-name>myBean</managed-bean-name>
    <managed-bean-class>com.mytest.MyBean</managed-bean-class>
    <managed-bean-scope>view</managed-bean-scope>
    <managed-property>
        <property-name>mySpringBean</property-name>
        <value>#{mySpringBean}</value>
    </managed-property>
</managed-bean>

Is something like the above possible with annotations and without defining all the jsf beans/properties and the spring beans/properties for every bean in the config xml files?

Dani
  • 3,744
  • 4
  • 27
  • 35
Dimman
  • 1,186
  • 4
  • 14
  • 21
  • Funny, I use this method of injection and it works for me, but then I also include the property injection in my `applicationContext.xml` as well. The Spring EL resolver does not seem to work with ViewScoped beans that I have noticed. Try changing this to SessionScoped and see if the property becomes injected. – maple_shaft Jan 19 '12 at 14:11
  • I want to avoid the applicationContext.xml (I'm a bit stubborn! thanks) But thanks :) – Dimman Jan 19 '12 at 14:57

3 Answers3

14

If you already have Spring container why not use its @Autowired annotation. For that, Update your faces-config.xml as suggested by Boni. Then add these listeners to your web.xml after this

<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>

Then add these to your applicationContext.xml

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

Now you can use Spring annotations and your bean will be something like this:

package com.examples;
@Component
@Scope(value="request")
public class MyBean {
    @Autowired
    private MySpringBeanClass mySpringBean;
}

Annotate your MySpringBeanClass with @Service

See Also:

Community
  • 1
  • 1
Ravi Kadaboina
  • 8,494
  • 3
  • 30
  • 42
  • 1
    and if you want to use ViewScope in Spring you need to write a custom ViewScope Class that implements Scope. Follow this blog entry for that [link](http://cagataycivici.wordpress.com/2010/02/17/port-jsf-2-0s-viewscope-to-spring-3-0/) – Ravi Kadaboina Jan 19 '12 at 22:15
10

Put this code in your faces-config.xml

<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>

Then in your ManageBean Constructor call;

WebApplicationContext ctx =  FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
mySpringBean = ctx.getBean(MySpringBean.class);

MySpringBean mean your Spring Bean Class

Dani
  • 3,744
  • 4
  • 27
  • 35
Boni
  • 590
  • 1
  • 3
  • 11
  • Can it be done with annotations in the spring bean and without inserthing this in the applicationContext.xml ? Thanks – Dimman Jan 19 '12 at 11:40
  • 1
    i have it working with the WebApplicationContext ctx solution. I was just wondering if i could skip it and use @ManagedProperty(value = "#{mySpringBean}") direct :) – Dimman Jan 19 '12 at 11:43
3

Assuming you have configured Spring properly in web.xml and applicationContext.xml. Make the following entry in faces-config.xml

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

Your sample code given above seems fine. What will happen with above entry is Managed Property will be first looked in beans managed by JSF if not found will be searched in beans managed by Spring. Your spring bean should have proper annotations marked and name given in @ManagedProperty should match with default/name given to bean.

As mentioned by @Boni that is not required it is auto injected. I have used settings as you desire.

A side note: Since you are opting for view scope please have a look at this link The benefits and pitfalls of @ViewScoped

Dani
  • 3,744
  • 4
  • 27
  • 35
baba.kabira
  • 3,111
  • 2
  • 26
  • 37