Getting Started with Contexts and Dependency Injection and JSF 2.0

Contributed by Andy Gibson

Contexts and Dependency Injection

  1. Getting Started with CDI and JSF 2.0
  2. Working with Injection and Qualifiers in CDI
  3. Applying @Alternative Beans and Lifecycle Annotations
  4. Working with Events in CDI

Content on this page applies to NetBeans IDE 7.0, 7.1, 7.2 and 7.3

Contexts and Dependency Injection (CDI), specified by JSR-299, is an integral part of Java EE 6 and provides an architecture that allows Java EE components such as servlets, enterprise beans, and JavaBeans to exist within the lifecycle of an application with well-defined scopes. In addition, CDI services allow Java EE components such as EJB session beans and JavaServer Faces (JSF) managed beans to be injected and to interact in a loosely coupled way by firing and observing events.

This tutorial is based on the blog post by Andy Gibson, entitled Getting Started with JSF 2.0 and CDI in JEE 6. It demonstrates how you can use the IDE to set up a Java web project with support for JSF 2.0 and CDI. It continues by showing how to wire CDI managed beans with Facelets pages, and concludes with a brief example of CDI integration with EJB technology.

NetBeans IDE provides built-in support for Contexts and Dependency Injection, including the option of generating the beans.xml CDI configuration file upon project creation, editor and navigation support for annotations, as well as various wizards for creating commonly used CDI artifacts.


To complete this tutorial, you need the following software and resources.

Software or Resource Version Required
NetBeans IDE 7.0, 7.1, 7.2, 7.3, Java EE bundle
Java Development Kit (JDK) version 6 or 7
GlassFish server Open Source Edition 3.x

Notes:


Creating a Java Web Project with CDI Support

In this exercise you create a JSF 2.0-enabled Java web project with CDI support.

  1. Click the New Project ( New Project button ) button in the IDE's main toolbar (Ctrl-Shift-N; ⌘-Shift-N on Mac).
  2. In the New Project wizard, select the Java Web category, then select Web Application. Click Next.
  3. Type cdiDemo for the project name and set the project location. Click Next.
  4. Set the server to GlassFish 3.x and set the Java EE Version to Java EE 6 Web. Confirm that the 'Enable Contexts and Dependency Injection' option is selected.
    Enable CDI option provided in New Web Application wizard
    The 'Enable Contexts and Dependency Injection' option, when selected, generates a beans.xml file in the project's WEB-INF folder when the project template is created. The beans.xml file is used by CDI to instruct the Java EE-compliant server that the project is a module containing CDI beans.
  5. Click Next.
  6. In the Frameworks panel, select the JavaServer Faces option.
  7. Click the Configuration tab and confirm that Facelets is selected as the Preferred Page Language. Click Finish.

    When you click Finish, the IDE generates the web application project and opens the index.xhtml welcome page in the editor.

  8. In the Projects window, expand the Web Pages > WEB-INF folder nodes and note that the beans.xml file is displayed. This file is currently empty, but can be used to specify bean related information in XML as an alternative to annotations.
    New project displayed in Projects window

    If you expand the Libraries > GlassFish Server node you can see that the weld-osgi-bundle.jar library was automatically added. The GlassFish Server includes Weld, which is JBoss' implementation of the JSR-299 CDI specification.

Accessing Beans from JSF's Expression Language

This exercise demonstrates how you can wire CDI managed beans to Facelets pages using EL syntax.

  1. In the Projects window, right-click the Source Packages node and choose New > Java Class.
  2. In the New Java Class wizard, name the class MessageServerBean, and type in exercise1 as the Package. (The new package is created upon completing the wizard.)
    New Java Class wizard
  3. Click Finish. The new package and class are generated, and the class opens in the editor.
  4. Annotate the class with the javax.inject.Named annotation, and create a single method to return a string.
    package exercise1;
    
    import javax.inject.Named;
    
    @Named
    public class MessageServerBean {
    
        public String getMessage() {
            return "Hello World!";
        }
    }
    As you type the @Named annotation, press Ctrl-Space to invoke the editor's code completion support, as well as Javadoc documentation. If you apply the annotation using the editor's code completion facilities (i.e., select the appropriate annotation and press Enter), the import statement is automatically added to the file.

    In the Javadoc pop-up, you can also click the 'Show documentation in external web browser' ( Show documentation in external web browser button ) button to display the full-sized Javadoc in a separate window.
  5. Save the file (Ctrl-S; ⌘-S on Mac). By adding the @Named annotation, the MessageServerBean class becomes a managed bean, as defined by CDI.
  6. Switch to the index.xhtml Facelets page (press Ctrl-Tab) in the editor, and add the following content to the <h:body> tags.
    <h:body>
        Hello from Facelets
        <br/>
        Message is: #{messageServerBean.message}
        <br/>
        Message Server Bean is: #{messageServerBean}
    </h:body>
    You can press Ctrl-Space in EL expressions to take advantage of code completion suggestions. The editor's code completion lists managed beans and their properties. Because the @Named annotation transforms the MessageServerBean class into a CDI managed bean, it becomes accessible within EL syntax, just as though it were a JSF managed bean.
    New Java Class wizard
  7. Click the Run Project ( Run Project button ) button in the IDE's main toolbar. The project is compiled and deployed to GlassFish, and the application welcome page (index.xhtml) opens in the browser. You can see the "Hello World!" message from the MessageServerBean displayed on the page.
    Welcome page displayed in browser
  8. Go back into the message bean and change the message to something else (e.g., "Hello Weld!"). Save the file (Ctrl-S; ⌘-S on Mac), then refresh the browser. The new message automatically appears. Thanks to the IDE's Deploy on Save feature, any changes you save result in automatic compilation and redeployment to the server.

    From the third line in the page you can see that the class name is exercise1.MessageServerBean. Note that the bean is just a POJO (Plain Old Java Object). Even though you are developing in Java EE, there is no complex class hierarchy wrapped in layers of transactions, interceptors and all that "heavy" stuff you keep hearing about.

What's Going On?

When the application is deployed, the presence of a beans.xml file signals that the module contains CDI managed beans, so the classes on the path are scanned for CDI annotations. In a CDI module, all beans are registered with Weld, and the @Named annotation is used to match beans to injection points. When the index.xhtml page was rendered, JSF tried to resolve the value of messageServerBean in the page using the registered expression resolvers in JSF. One of these is the Weld EL Resolver which has the MessageServerBean class registered under the name messageServerBean. We could have specified a different name with the @Named annotation, but since we did not it was registered under the default name, being the class name with a lower-case first letter. The Weld resolver returns an instance of this bean in response to the request from JSF. Bean naming is only needed when using EL expressions and should not be used as a mechanism for injection since CDI provides type-safe injection by class type and qualifier annotations.


Upgrading to an EJB

As we are using a Java EE stack, we can easily deploy our bean as an EJB with some small changes thanks to EJB 3.1.

  1. Open the MessageServerBean and add the javax.ejb.Stateless annotation at the class level and change the string to 'Hello EJB!'.
    package exercise1;
    
    import javax.ejb.Stateless;
    import javax.inject.Named;
    
    /**
     *
     * @author nbuser
     */
    @Named
    @Stateless
    public class MessageServerBean {
    
        public String getMessage() {
            return "Hello EJB!";
        }
    }
  2. Save the file (Ctrl-S; ⌘-S on Mac), then go to your browser and refresh. You will see output similar to the following:
    EJB details displayed in browser
    Amazingly, we turned our POJO into a fully-featured EJB with just one annotation. We saved changes then refreshed the page, and our changes appeared. In doing so it wasn't necessary to create any weird project configurations, local interfaces or arcane deployment descriptors.

Different EJB types

You can also try using the @Stateful annotation. Alternatively, you could try the new @Singleton annotation for singleton instances. If you do, you may notice that there is are two annotations: javax.ejb.Singleton and javax.inject.Singleton. Why two singletons? The CDI singleton (javax.inject.Singleton) lets you define a singleton instance outside of EJB in case you are using CDI in a non-EJB environment. The EJB singleton (javax.ejb.Singleton) provides all the features of an EJB such as transaction management. Therefore, you have the choice depending on your needs and whether you are working in an EJB environment.

Send Feedback on This Tutorial

See Also

The next installment of this series focuses on CDI injection, and provides a closer look at using CDI for managing dependencies in a Java EE 6 environment.

For more information about CDI and JSF 2.0, see the following resources.

Contexts and Dependency Injection

JavaServer Faces 2.0