How to auto wire a spring bean from a jsf managed bean in liferay portlet

There are 2 ways I know to auto-wire a spring bean into a jsf managed bean:

1.) Is through WebApplicationContext, invoke during jsf managed bean constructor:

Below are the most vital files to perform this action:

web.xml
<?xml version="1.0"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

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

 <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>*.jsf</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>Faces Servlet</servlet-name>
  <url-pattern>/faces/*</url-pattern>
 </servlet-mapping>

</web-app>
Take note of the added listener for spring. applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.0.xsd
 http://www.springframework.org/schema/jee
 http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
 http://www.springframework.org/schema/tx
 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
 default-autowire="byName">

 <context:annotation-config />
 <context:component-scan base-package="com.ipiel" />
 <tx:annotation-driven />
</beans>
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>
  <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
  <!-- <message-bundle>i18nFaces</message-bundle> -->
  <resource-bundle>
   <base-name>com.sido.resources</base-name>
   <var>msg</var>
  </resource-bundle>
  <locale-config>
   <default-locale>en</default-locale>
  </locale-config>
 </application>

</faces-config>
portlet.xml
<?xml version="1.0"?>
<portlet-app version="2.0"
 xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd">
 <portlet>
  <portlet-name>czetsuya</portlet-name>
  <display-name>czetsuya@gmail.com</display-name>
  <portlet-class>org.portletfaces.bridge.GenericFacesPortlet</portlet-class>
  <init-param>
   <name>javax.portlet.faces.defaultViewId.view</name>
   <value>/view.xhtml</value>
  </init-param>
  <init-param>
   <name>javax.portlet.faces.defaultViewId.edit</name>
   <value>/edit.xhtml</value>
  </init-param>
  <supports>
   <mime-type>text/html</mime-type>
   <portlet-mode>view</portlet-mode>
   <portlet-mode>edit</portlet-mode>
  </supports>
  <portlet-info>
   <title></title>
   <short-title></short-title>
   <keywords></keywords>
  </portlet-info>
 </portlet>
</portlet-app>

Now let's look at the spring bean and jsf managed bean classes:
The spring bean service class:
@Service
public class IpielService {
 static final Logger log = LoggerFactory.getLogger(IpielService.class);
 @PersistenceContext 
 protected EntityManager entityManager;

 public List list() {
  List result = entityManager.createQuery(
    "SELECT a FROM MyModel a").getResultList();
  return result;
 }
}
And the JSF managed bean
@RequestScoped
@ManagedBean
public class IpielAction implements Serializable { 
 private IpielService ipielService;
 
 public DeviceManagerAction() {
  WebApplicationContext ctx =  FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
  ipielService = ctx.getBean(IpielService.class);
 }
}
Noticed that we need to get the ipielService spring bean from the context to be able to inject into a jsf managed bean.
2.) Using @Autowired annotation from spring. We will use the same configuration files as above, and do some changes on IpielAction. Actually we just need to remove the constructor and add @Autowired annotation in ipielService
@RequestScoped
@Component
public class IpielAction implements Serializable { 
 @Autowired
 private IpielService ipielService; 
}
JSF should be able to locate IpielAction because of the variable resolver we've specified in faces-config.xml. Take note that we've changed @ManagedBean annotation into @Component to be able for spring to see it.
How to auto wire a spring bean from a jsf managed bean in liferay portlet How to auto wire a spring bean from a jsf managed bean in liferay portlet Reviewed by Edward Legaspi on Monday, May 21, 2012 Rating: 5

1 comment:

rkorn said...

Problem of spring letting managing beans by using @Component is, that you lose the JSF2 ViewScope.
You have to reimplement it!

Powered by Blogger.