Contexts and Dependency Injection (referred to as CDI) is a new specification feature introduced in Java EE 6 Platform. This was earlier referred to as Web Beans and in due course, the name has been changed to Contexts and Dependency Injection. The primary objective of CDI specification is to bring together the Web tier and the transactional services of the Java EE platform (i.e., the idea are to bring the entire transactional services to the Web tier). CDI services facilitate the usage of Enterprise Beans in the JavaServer Faces technology. CDI provides the power of dependency injection and flexibility.
Enterprise JavaBeans 3.1 (EJB 3.1), the latest release as part of Java EE 6 Platform specification, makes the development much simpler and easier. EJB 3.1 specification has simplified a number of features and provides a good declarative support for transactions and security.
CDI and EJB 3.1 both are part of the Java EE 6 platform, act as complementary technologies. In this article, let’s try to understand the synergy between both the technologies by starting with an introduction to CDI and EJB 3.1 and let’s see how they complement each other in building powerful Web applications.
Contexts and Dependency Injection (CDI): An Introduction
CDI (JSR 299) is a specification that defines a powerful set of services for the Java EE environment that helps in developing Web applications easily. CDI helps to develop Java EE components that exist within the life cycle of an application with well defined scopes. In the Java EE Platform, there is a strong support for transactions in the business tier and persistence tier through the technologies like Enterprise JavaBeans and Java Persistence API. However, there is less/no support for transactions from the Web tier. They are more focused on displaying the presentation content and have limited access to transactional resources. CDI services help in unifying Enterprise JavaBeans (EJB) and JavaServer Faces (JSF) programming models. CDI services allow Enterprise JavaBeans to be used as the Managed Beans in JavaServer Faces framework. CDI also provides a good support for accessing transactional resources which facilitates in easy creation of Web applications using Java Persistence API.
The services defined by this specification allow objects to be bound to lifecycle contexts, to be injected, to be associated with interceptors and decorators and to interact in a loosely coupled fashion by initiating and observing events. Primary objective of introducing CDI is to bring together different types of beans available in Java EE Platform like JSF Managed Beans, Enterprise Java Beans, etc. CDI helps in defining “bean” object which can be used in any of the tiers of the Java EE platform. In simple terms, a bean object defines applications state or logic within a context. Any Java EE component can be considered as a bean provided the life cycle of the component is managed by the container. Bean in CDI like any other beans is a POJO and the beauty is that it can take the shape of any other component with the help of annotations. Any class can be used as a managed-bean provided it meets all the requirements of a bean. Annotations are used to mark the bean to be of a specific type, @Model
annotation is used on the bean to mark the class as a Model in the MVC architecture, @Named
annotation is used on the bean to mark the class as a Managed Bean in the Java Server Faces application, @Stateful
annotation can be added to mark the class as a Stateful Enterprise Bean.
@Model
public class Login {
private String uname;
private String pwd;
public void setUname(String uname) {
this.uname = uname;
}
public String getUname() {
return this.uname;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getPwd() {
return this.pwd;
}
}
@Named
@SessionScoped
public class LoginBean implements Serializable {
…
}
@Model
@Stateful
@SessionScoped
public class Login {
….
}
Apart from these annotations there are qualifier annotations and scoped annotations. CDI services are provided to the components through the transaction and security annotations.
Qualifier Annotations
A qualifier helps in identifying a specific implementation of Java Class or Interface to be injected. A qualifier is an annotation applied to a bean. In order to define the qualifier annotation, the type should be defined as a qualifier: @Qualifier
. A qualifier type is a Java annotation, custom annotation defined using @Target({METHOD, FIELD, PARAMETER, TYPE}) and @Retention(RUNTIME)
annotations.
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface ValidUser {
…
}
The qualifier defined in the above example can be used as follows:
….
@ValidUser
@Inject
private String username;
….
Scoped Annotations
Scope is an important factor in Web applications. Scope defines the state of the object that is being held by the bean in a Web application. While the Web applications have well defined scope, there is no well-defined scope for the enterprise beans. When enterprise bean components are used within the Web applications, the components are not aware of the contexts of the Web applications and have no state associated with those contexts. It is meaningless to add the scope of the enterprise bean to the web-tier context. The following are the scopes used in the CDI beans:
- Request Scope –
@RequestScoped
– Single HTTP request (Defined in Servlet Specification) - Session Scope –
@SessionScoped
– Across HTTP requests – a single user sequential requests (Defined in Servlet Specification) - Application Scope –
@ApplicationScoped
– Across all users within an application (Defined in Servlet Specification) - Dependent Scope –
@Dependent
– For a Single client and the lifecycle is same as that the client (Defined in CDI Specification) - Conversation Scope –
@ConversationScoped
– Scope between multiple invocations of JSF life cycle within the session boundaries (Defined in CDI Specification)
CDI objects are scoped, have a well defined lifecycle context in the Java EE container. They are automatically created and destroyed when the context in which they created ends.
Injecting Beans
CDI services allow beans to be generally injected into another application using JSR 330, Dependency Injection for Java specification. The annotation @Inject
part of JSR 330 allows beans to be injected. This annotation helps to inject any object for which the container provides the required resource.
@Named
@Stateful
public class Login {
@Inject
private String uname;
@Inject
private String pwd;
….
}
CDI services come with other interesting features like events, interceptors, decorators etc. Since the discussion on these are beyond the scope of this article, readers are requested to learn more about CDI services from the JSR 299 and other articles which focus completely on the CDI services.
Enterprise JavaBeans EJB 3.1: A Brief Overview
EJB 3.0 specification, the version currently in use, has seen higher adoption rate and was very well received by the community because of its simplicity and ease of development. The new specification that was released in November 2009, EJB 3.1, makes development even simpler.
EJB 3.0 made the developer life easier by removing home interface and introducing annotations. The next release makes life even easier by making the business interfaces also optional. This makes the EJBs look very similar to a normal POJO.
Addition of a new type of bean, Singleton bean is introduced in this release. The primary goal of introducing singleton beans is to share the application wide shared data and to support concurrent access. With this, the EJB specification has provided a flexible concurrent option.
Until now, EJB components are placed in a separate JAR file and the file will be packaged along with WAR file in an EAR file. One of the major requirements of the new specification is providing an option to package EJBs in the WAR file itself, thus making EJBs to be available as part of the Web application with all required support for transactions and security. The new specification allows EJBs to be placed in the same folder where the Web component classes (Servlets) are placed, under WEB-INFclasses
directory of a WAR file.
@Stateless
public class Stock {
public double getStockPrice(String symbol) {
if (symbol.equals("PQRS")) {
return 234.98;
}
if (symbol.equals("OPLK")) {
return 64.45;
}
return 0.0;
}
}
Apart from these, the new release of the specification introduces several other interesting features like asynchronous session bean, running EJBs in Java SE environment and the concept of EJB Lite.
EJB provides a powerful support for transactions. Transactional attributes can be defined using annotations thanks to the “Configuration by Exception” model adopted from Java EE 5 Platform. Annotations play a major role in simplifying and making the entire suite of specifications light.
CDI and EJB: Complementary Technologies
EJBs are really simple and powerful after adopting the POJO model. Even though it provided a good support for transactions and security, one particular place where it lacked was the direct usage of it with the JavaServer Faces application. In JSF application, there was a need to create managed beans separately in spite of EJB being so powerful. On the other hand, simply beans are not powerful. They have to be executed under some contexts. CDI services really help in bridging the gap between the two; it helps in EJB getting directly exposed to JSF applications. In this scenario, CDI becomes the complementary technology for EJB 3.1 specification in the Java EE 6 platform.
In enterprise applications using EJBs, CDI services allow enterprise beans to be injected as Managed Beans with the @Inject
annotation by removing @EJB
annotation. The replacement of @Inject
annotation provides all the benefits of CDI for the enterprise beans like dependency injection, events, interceptors, stereotypes. Thus using @Inject
annotations, enterprise beans can be easily transformed to managed beans.
An enterprise bean represented like the one mentioned below:
@Stateless
public class SQBean {
@EJB
private StockBean stockBean;
@EJB
private Stock stockPrice;
public void getStockPrice() {
String symbol= stockBean.getStockSymbol();
double price = stockPrice.getStockPrice(symbol);
}
}
Can be easily transformed into a Managed Bean like this:
@Named
@Stateless
public class SQBean {
@Inject
private StockBean stockBean;
@Inject
private Stock stockPrice;
public void getStockPrice() {
String symbol= stockBean.getStockSymbol();
double price = stockPrice.getStockPrice(symbol);
…
}
}
This transformation of enterprise bean to a managed bean provides lot of benefits for the Web tier components and applications. The beans are now visible to the Java Server Pages; they can be accessed using the Expression Language (EL). The class SQBean is now visible to JSP, JSF expressions. The @Named
annotation is used for associating a name with the managed bean, if none specified, by default the name will be the name of the bean with the first letter in the lowercase. This facilitates the SQBean to be accessed directly by the EL in JSF pages without any additional configuration.
….
<h:inputText id="stockSymbol" value="#{stockBean.symbol}" />
<h:commandButton value="Get Stock Price" action="#{sQBean.getStockPrice}" />
….
As mentioned earlier, CDI also believes in convention over configuration, and hence doesn’t require any additional XML files for configuration; annotations are sufficient. CDI helps to inject any kind of object be it a class or an interface, only the type of the object being injected is checked. This is complement to the EJB model where the object to be injected is identified by a “String” name as against the type of the object being injected. CDI also to some extent supports identifying the injection object with string name, this time it is through its @Qualifier
annotation.
@Qualifier
@Retention(RUNTIME)
@Target({FIELD,TYPE})
public @interface CheckUser {
enum User{
VALID, INVALID
}
User details();
}
At the time of specifying the injection point, qualifier helps in identifying the type of object being injected.
@Named
@Stateless
public class Login {
…
@Inject
@CheckUser(CheckUser.details.VALID)
private String username;
…
}
Annotations support makes convention over configuration more beneficial. XML configuration is not completely ruled out; it is still available as an “optional” feature through “beans.xml” configuration file. The injection object can be activated from the XML file. @Alternative annotation plays a major role in activation and deactivation of the injection points. Another feature which is interesting in CDI is event firing and observation which is again achieved through the methods and annotations.
Conclusion
CDI and EJB 3.1 make the perfect complementary technologies as EJB comes with good support for transactions, security and exiting features like interceptors and aspects. CDI provides additional power of dependency injection. The combination of the two provides a perfect synergy in the Web platform. CDI with EJB 3.1 makes the code lighter because they are simple POJO classes, when compared with plain POJOs or any other additional frameworks, the number of code written using CDI and EJB 3.1 is less. Frameworks will end up in either more classes or more configuration code, XML files. Both CDI and EJB 3.1 are part of Java EE 6 Platform – Web Profile, providing a good strategy for building Web applications which also results in reduced number of classes and code as compared to its earlier versions. So in future, the JCP could be more focusing on pushing aspects of transactions, security, aspects into CDI specification rather improving it on the EJB specifications.
Acknowledgements
The author would like to sincerely thank Mr. Subrahmanya SV, VP, ECOM Research Group, E&R for the idea, guidance, support and constant encouragement and Mr. Nitin KL for quickly reviewing this article.
About the Author
Sangeetha S. works as a Senior Technical Architect at the E-Commerce Research Labs at Infosys Technologies. She has over 12 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 numerous articles for Developer.com and DevX.com. She can be reached at sangeethas@infosys.com.