JSF 2 with Spring 3 and JSR 330 - weijiguang/OA GitHub Wiki

Introduction Recently I was involved in migrating an application from JSF 1.2 to JSF 2.0 with a stated goal of refactoring removing the plethora of JSF XML configuration files that permeated the codebase. Faces configuration files are notoriously difficult to maintain due to their verbose nature and reliance on the Expression Language (EL) syntax.

Other factors motivating the migration included:

Use of annotation-based configuration for managed beans across all layers within the application stack Facelets templating for JSF views Leveraging the Spring 3.x Inversion of Control (IoC) container support for JSR-330 – Dependency Injection for Java Dependency Injection (DI) is a pattern for resolving component dependencies by having a container inject an instantiated component as opposed to explicitly instantiating a component from within an enclosing class.

Enable dependency injection within Spring The Maven dependency for JSR-330 annotations can be referenced within a project POM file as follows:

1 2 javax.inject 3 javax.inject 4 1 5 To enable Dependency Injection using JSR-330 annotations in Spring, the application context file must be updated with component scanning from the application base package as follows:

1

2 <beans xmlns:p="http://www.springframework.org/schema/p" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation=" 6

7 http://www.springframework.org/schema/context 8

9 http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 10

11 <context:component-scan base-package="net.comdynamics.myapp"/> 12

13 This configuration element triggers annotation-based autowiring with the base-package reflecting that of your application.

Services and data tier updates The application services and data tier for the system had originally been developed using the Spring 2.5 framework. In order to leverage JSR-330 in Spring 3.x, changes were made to remove the @Service annotation and replace with the @Named annotation.

The @Autowired annotation for Data Access Objects (DAO) was changed to @Inject, with combined updates illustrated below.

Before 1 package net.comdynamics.myapp; 2

3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.stereotype.Service; 5

6 @Service("reportService") 7 public class ReportServiceImpl implements ReportService { 8

9 @Autowired 10 private ReportFilterDao reportFilterDao; 11

12 // bean getters/setters… 13 } After 1 package net.comdynamics.myapp; 2

3 import javax.inject.Inject; 4 import javax.inject.Named; 5

6 @Named("reportService") 7 public class ReportServiceImpl implements ReportService { 8

9 @Inject 10 @Named("reportFilterDao") 11 private ReportFilterDao reportFilterDao; 12

13 // bean getters/setters… 14

15 } The @Named annotation is used to associate a name for the bean. If no name is specified as an argument to the annotation, the bean name will be the name of the class with the first letter set to lowercase.

The @Inject annotation is used to identify a dependency injection point for which a dependency on a Java class or interface can be set by the container.

The upshot of this change is that bean references using the @Named annotation can be removed from the Spring application context. For example, after making changes above, the following bean declaration can be commented out deleted.

1

JSF managed bean updates JSF2 introduced the @ManagedBean annotation which was intended to minimise Faces configuration in XML files. Whilst this alleviates the need to declare JSF managed beans in XML it does not promote annotation consistency across all layers in the application.

To ensure consistency in a Spring project and alignment with JEE 6, use the JSR330 @Named annotation for JSF backing beans. For example:

1 package net.comdynamics.myapp.web; 2

3 import javax.inject.Named; 4 import org.springframework.context.annotation.Scope; 5

6 /** 7

  • ReportListPage JSF backing bean. 8 */ 9 @Named("reportListPage") 10 @Scope("request") 11 public class ReportListPage extends BasePage { 12

13 @Inject 14 @Named("reportService") 15 private ReportService reportService; 16

17 public ReportListPage() { 18 } 19

20 public ReportService getReportService() { 21 return reportService; 22 } 23

24 public void setReportService(ReportService ReportService) { 25 this.reportService = reportService; 26 } 27

28 // etc… 29

30 } Failure to set the scope of the managed bean will result in Spring creating a Singleton instance for that bean. For JSF beans, specify the scope as Request or Session as either @Scope("request") or @Scope("session")

After making the above change, JSF managed bean references in the faces configuration files can be commented out deleted.

1

2 <faces-config version='1.2' xmlns="http://java.sun.com/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"> 5

6 18

19 Conclusion Use of annotation-based configuration for managed beans across all layers within the application stack can simplify configuration and enforce consistency. Spring 3.x supports JSR-330 which can be leveraged by your JSF 2 application with minimal effort.

CDI (JSR-299) scopes and JSF 2 backing beans will be discussed in a future article.

⚠️ **GitHub.com Fallback** ⚠️