JSF 2.0 Bean Validation and Dependency Injection
Dependency Injection in JSF 2.0
Dependency injection (DI) is the concept of providing an external dependency to a specific resource, generally by a Java EE container. It enables you to provide a set of services to Java EE components. The main intent of using DI is to avoid looking up or creating a particular resource from the client program. Part of JSR-330, dependency injection is comprised of a set of annotations.
One of the main features of Java EE 6 is the standardization of annotations to achieve DI through context and dependency injection (CDI), which is specified by JSR-299 (formerly known as Web Beans). Classes that are "injectable" in JSR-299 are portable across frameworks, as JSR-299 includes the DI specification (JSR-330) and the managed beans specification (JSR-316).
As specified by JSR-299, CDI essentially is responsible for providing the following two services:
- Context: Allows you to bind stateful components' lifecycles and interactions to a well defined and extensible lifecycle context.
- Dependency injection: Allows you to inject these components in a type-safe manner into an application, as well as to inject a particular implementation of an interface at deployment time.
In the case of a Web application, JSR-299 allows you to use any Java EE component (Enterprise JavaBeans, or EJBs, for instance) in conjunction with JSF managed beans. EJBs are by nature transactional, while the components on the Web tier (JSF managed beans) are not transactional. JSR-299 bridges this transactional gap in a Java EE application by enabling the developer to replace the JSF managed bean with an EJB.
In the online quiz application, the SampleTest
managed bean is in the Request scope, whose responsibility is to help the user to get a feel for the questions by enabling him or her to view a sample question. Here is the code:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class SampleTest {
// Some code
}
In this tutorial, you will modify the SampleTest
managed bean class to act as a contextual class, which will include both the application code and the state.
The contextual SampleTest
class is marked with the @Named
annotation defined in the javax.inject
package. The @Named
annotation marks a class with a specific name. If no arguments are provided to the @Named
annotation, then the class name is considered to be the default bean name with the first letter being lowercase (the bean naming convention in JSF 2.0). The class is also annotated with @RequestScoped
, which is defined in the javax.enterprise.context
package (a JSR-299-specific annotation, which specifies that now the bean can be made available to all the other components in the request scope).
@Named
@RequestScoped
public class SampleTest {
@SampleTestQuestion
@Inject
private String sampleQuestion;
//Some more Code
}
The @Inject
annotation defined in the javax.inject
package is a CDI annotation applied to the sampleQuestion
property of the SampleTest
class. The @Inject
annotation identifies the point at which the dependency needs to be injected. The sampleQuestion
property is also decorated with the @SampleTestQuestion
qualifier annotation, which is the actual implementation that gets injected into the property. You can provide different implementations for the same bean type by using qualifiers. The @SampleTestQuestion
qualifier injects a sample question that the user can attempt to answer to the sampleQuestion
bean property.
The @SampleTestQuestion
qualifier is defined as follows:
@Target ({TYPE, METHOD, PARAMETER, FIELD})
@Retention (RUNTIME)
@Documented
@Qualifier
public @interface SampleTestQuestion {
}
The @Target
, @Retention
and @Documented
annotations are defined at the Java language level in the java.lang.annotation
package:
- The
@Target
annotation is required to identify all the elements of the program for which this annotation is applicable. - The
@Retention
annotation denotes the retention time for a particular annotation, and@SampleTestQuestion
will be retained completely within the runtime of the online quiz application. - The
@Documented
annotation suggests that by default the types should be documented by Javadoc or any other similar tools.
The @Qualifier
defined in the javax.inject
package is used to recognize a qualifier annotation, which is required to identify a particular implementation of a Java class or an interface that will be injected. @Interface
is the keyword used to create an Annotation type.
You now have to define the SampleTestQuestionGenerator
class, which defines a producer method that gets implicitly invoked when the injection takes place. This class has a generate()
method annotated with @Produces
(defined in javax.enterprise.inject
package) to mark the producer method of a qualifier. The generate()
method is also annotated with the qualifier for which this method acts as a producer. The generator class is defined in the application scope by annotating it with
@javax.enterprise.context.ApplicationScoped
.
@ApplicationScoped
public class SampleTestQuestionGenerator {
@Produces
@SampleTestQuestion
String generate () {
return "First Prime Minister of India";
}
}
After the user login is successful, the user chooses to check for a sample question by clicking the Try Sample link, which takes the user to the Sample Question page. The
SampleTest
class is annotated with the @javax.inject.Named
annotation, where the class gets identified by a particular name in the application in a specific scope. The sampleQuestion
property of the SampleTest
class requires a dependency to be injected via @javax.inject.Inject
and the @SampleTestQuestion
annotation. The @SampleTestQuestion
qualifier has a generator class SampleTestQuestionGenerator
which has a producer method, generate()
, identified by @javax.enterprise.inject.Produces
, the method that gets invoked when a dependency needs to be injected into a resource.
Conclusion
JSF 2 introduces new features that have simplified the process of web application development in Java. Particularly, the bean validation support in JSF 2 provides an alternative to the existing validation model, which uses special tags and attributes. Dependency injection in conjunction with JSF 2.0 allows a bean to be given a name, which can be accessed anywhere within the scope of a JSF application. Classes that can be injected are now portable across various frameworks.
Acknowledgements
The authors would like to sincerely thank Mr. Subrahmanya (SV, VP, ECOM Research Group, E&R) for his ideas, guidance, support and constant encouragement and Ms. Mahalakshmi for kindly reviewing this article and for her valuable comments.About the Authors
Sangeetha S. works as a Senior Technical Architect at the E-Commerce Research Labs at Infosys Technologies. She has over 10 years of experience in design and development of Java and Java EE applications. She has co-authored a book on 'J2EE Architecture' and also has written articles for online Java publications.
Nitin KL works at the E-Commerce Research Labs at Infosys Technologies. He is involved in design and development of Java EE applications using Hibernate, iBATIS, and JPA.
Ananya S. works at the E-Commerce Research Labs at Infosys Technologies. She is involved in design and development of Java EE applications using Hibernate, iBATIS, and JPA.
Page 2 of 2
This article was originally published on May 4, 2010