A CDI, EJB3 and JPA -Java EE-7 application with NetBeans 7 or 8

Introduction:

CDI is a very promising technology in Java EE. Its precursor was the open source JBoss Seam.  As pointed out in the earlier article “Context and Dependency Injection- support  in NetBeans6.9”,  the motive behind Seam was two-fold - simplification of Java EE programming by knitting together the web tier and the transactional tier and making EE more cohesive and a design-model  to work with “stateful” objects. In other words it aimed to streamline existing JEE technologies, like JSF or EJB, by tying the loose ends, rather than putting up an alternative, as Spring did. It is no surprise that JBoss Seam has been incorporated into JAVA EE from version -6, as Context and Dependency Injection (CDI). So you can make use of the earlier articles on Seam also.   Spring, to a great extent and Google Guice, to some extent, popularized “Dependency Injection”. Dependency injection is extremely useful for acquiring references to other beans.  See the figure below:

You can see an annotated POJO is available as a bean in the Spring container. But a POJO(or EJB) requires two annotations to become a Seam/CDI bean and be managed by it. Apart from affixing @Inject, you have to use one of the @Scope annotations to tell CDI the context/scope in which it should manage the bean.

 Gavin King, the creator of Hibernate was not happy with the “stateless-design” of the existing/ Spring’s Dependency injection and the consequent lazy-initialization exceptions and the various solutions to tackle them. So he added “Context” or Scope to the DI framework he created- Seam.

Supplements JEE:

Though JSF and EJB are part of Java EE specification, JSF could not directly use EJB. Much boiler-plate code was required for JSF to make use of the EJB services. But once an EJB  becomes a Seam bean, through annotations,  JSF can directly access it using Expression Language (EL).Seam did away  with the extra “JSF backing bean”. Once registered, any component, whether a POJO or EJB, becomes a Seam component and becomes accessible to JSF. This makes programming with the Java EE platform more cohesive.  Seam/CDI not only injects any registered bean but also manages its life-cycle, giving it a well-defined Context or a Scope (CDI comes with predefined scopes: request, session, application, and conversation scopes). The conversation scope was introduced to take care of certain situations. In other words   Seam/CDI container provides 1) a lifecycle for stateful objects, 2) binding of objects to well-defined contexts. Its other features include i) “type-safe” dependency injection ii)  an event notification facility, and iii) robust interceptors-  all  enable loose coupling. With these features CDI has taken DI to a new level, while making Java EE simpler and leaner.

CDI vs EJB

But the oft-repeated question is whether Seam/CDI is a replacement for EJB. The answer is big “NO”. EJB and CDI are complementary technologies that enable one another in the building of robust Java EE apps relatively easily. CDI not only simplifies JSF but also greatly simplifies the amount of work necessary to use EJBs—there’s no need to access JNDI or write a custom JNDI abstraction layer. CDI introduces dependency injection and context features as well as some extensions to POJOs. CDI isn’t a replacement for EJBs—EJBs are necessary when security, transactions, remoting,  scheduling, asynchronous support, and locking are required. As EJBs also are beans within CDI, we can approach the problem, as if everything is a CDI bean; we can upgrade a POJO-CDI bean to an EJB-CDI bean, when we require the Enterprise services provided by the EJB container. On the other hand, if we don’t require them we can use a POJO and avail the services the CDI container provides mentioned above.

Sample:

Earlier we have seen how to use the facilities in “seem-gen” or NetBeans-6 and generate a full application with the above technologies from a database table created by us. Please refer to the earlier article by the author -“SEAM WITH SEAM-GEN – A RAILS-LIKE J2EE FRAMEWORK and JSF2.0 CRUD APPLICATION WITH NETBEANS6.8”.You can see in them “facelets” have replaced “JSP” as a view technology. NetBeans has facility to generate “Facelets Template” and “Facelets Template Client” files. They are similar to the layout and the partials in other template technologies. To focus on CDI,we  will have simpler view files, without using the <ui> tag library which is used to define the template and the partials.

Create a database in MySQL , say blogDB, and create a table ‘blog’ as follows:

In MySql Console login and
execute
“CREATE DATABASE blogDB”;
“USE  blogDB”
CREATE TABLE blog (id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
content VARCHAR(50) NOT NULL);
       
Insert a few records. It is easier to use Netbeans or any other GUI tool to add a record rather than

THE mysql console client, as the id column has AUTO_INCREMENT attribute. In the Services window of the IDE expand Drivers and right click on “MySQL (Connector/JDriver)” and choose “Connect Using” .In the new connection wizard as in Figure-1, change the Database to “blogDB” and give the password (in my case default ‘mysql’) and click “Test Connection”. If you get “Connection succeeded” message, you can click “Finish”.

Figure-1

Project Creation

In the IDE choose   Fileà New Project -> Java Web -> Web Application.

Give the Project name and click Next and in the Server and Settings Wizard, as in Figure-2, ensure that Glassfish Server is selected, as it comes with reference implementations for JEE.

Figure-2

In the frameworks check Java Server faces. Click Finish. The IDE will generate a skeleton project with necessary jars added. Create a Java Package, say ‘ram’ under ‘Source Packages’. Right click on your Java package and choose New->Entity Class from Database. In the “New Entity Class From Database” Wizard, you can expand “Data Source” and choose New Data Source. In the Create Data Source wizard you can give the JNDI name as ‘jdbc/blogDB’ and in the Database Connection choose blogDB(in Figure-1 the value in JDBC URL).The New Entity Classes from Databases Wizard showing in the Available Tables “blog” . If you select it, “Add” button will be enabled. Click on the button. It will appear in the Selected Tables. Click “Next” and then “Finish”. The entity class will be generated by the IDE. Now we can right click on the package “ram” and choose Newà Session bean from Entity classes. In the New Session Bean from  Entity Classes wizard in “Available Entity Classes” you can see “ram.blog”. Select it and Add it to “Selected Entity Classes”. You will see Figure-3.

Figure-3

We need not check any Interface and Click Finish. The generic “Abstract Façade” and entity specific “BlogFacade” will be generated by the IDE. The AbstractFacade will contain generic method definitions for CRUD operations. We can add the following methods for Read and Write in BlogFacade.  

@Override
public void create(Blog entity) {
super.create(entity);
}
………
@Override
public List<Blog> findAll() {
return super.findAll();
}

CDI specific artifacts

As we have our entity and ejb ready we can focus on CDI artifacts. If you use NB-8.1 choose New -> Context and Dependency Injection -> beans.xml(CDI configuration file)  and Click Finish. The IDE will generate the file. In earlier versions, Under Source Packages  create a folder “META-INF” and under it create a xml file “beans.xml” and it may be filled up as under:

META-INF/beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans 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/beans_1_0.xsd">
</beans>

CDI takes the approach of convention over configuration. All we have to do is place a beans.xml file in our application. The beans.xml file serves two purposes:

It’s a configuration file for CDI and it’s a marker file so that CDI knows whether it needs to scan the JAR file for beans. The above shows only an empty configuration file. This file should be placed in the META-INF directory of any archive containing the beans.

Code a CDI –bean .Create a Newà Java class “BlogController” and fill up the code as under:

BlogController.java

package ram;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;

@Named            //-----1)
@RequestScoped    //----2)
public class BlogController implements Serializable{
private BlogFacade facade;    //-------3)
public BlogController(){}          //-------4)

 @Inject
public BlogController(BlogFacade facade)    //--------3)
{this.facade = facade;}

@Named                     //---------5)                                   
@Produces
@RequestScoped
private  Blog newBlog = new Blog();

private List<Blog> blogList = new ArrayList<>();

public List<Blog> getBlogList() {
blogList = facade.findAll();
return blogList;
}

public String addNewBlog() {
facade.create(newBlog);
blogList = facade.findAll();
return "List.xhtml";    

}

  • @Named does not make the class a CDI bean. It just gives it a name for the EL to access it. If you want, you can pass a string with value attribute to the annotation as @Named (value=blogContrl”). Unlike other DI frameworks, CDI doesn’t use string-based identifiers to determine what object should be injected. Instead, CDI uses type information provided by the Java object model to determine what object should be injected. When the @Named annotation is specified without providing a String-based name, a binding name will be derived from the class name, converting the first letter of the class name to lowercase. Here the EL can access the class with the name “blogController”.
  • This scope corresponds to the standard HTTP request. It begins when a request arrives and is discarded when the response is rendered. After completion and when you run the app, you can experiment by removing this annotation. If there is no annotation, scope will be taken as @Dependent and once the form is submitted the bean will be garbage collected. The result is the message “Target Unreachable, identifier 'newBlog' resolved to null”. You will get the above error message, as in dependent scope each invocation will result in a new bean being created. When the user then submits the form, a new instance will be created, and it will appear as if the user never entered anything. You can also use Conversation scope in place of request scope.
  • @Inject annotation is the heart of CDI. This annotation marks a injection-point( where an instance of a bean needs to be injected). It can be placed either on an instance variable or on a constructor or a setter. When the CDI container goes to instantiate a class containing fields etc  marked with @Inject, it checks to see if an instance already exists; if not, it creates a new instance and sets the value. Here we have preferred “constructor” injection as against the field-injection .In constructor injection parameters are passed in via the constructor and the object initializes itself like any other object. In field injection you may have to do the set-up operation on injected object through @POSTConstruct.
  • No argument constructor is provided to enable CDI to create a proxy for the bean and inject the same.
  • The producer methods are used in different situations: a) to provide runtime polymorphism where the concrete type of the bean to be injected may vary at runtime. b) the injected object may not even be a bean eg primitive types like Int. c) objects may require custom initialization. d) to inject JEE resources like FacesContext, EntityManager etc. e) when you deal with JPA. Normally the injected bean is a proxy and JPA will not accept a proxy. The Producer method keeps a reference to the original POJO and solves the problem.

View files As mentioned in the outset to keep the focus on CDI, we have tried to keep the view files as simple as possible. The generated index.xhtml may be modified as under:

index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
Hello from Facelets
<br />
<h:link outcome="/blog/List" value="Show All Blog Items"/>
        <br />
        <h:link outcome="/blog/Create" value="Create a New Blog"/>
</h:body>
</html>

// it has two links to List.xhtml and Create.xhtml using <h:link>

The code for “Create.xhtml” may be as under:

blog/Create.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
                <title>Create a new Blog</title>
    </h:head>

    <h:body>
       <h:form>
         <h:panelGrid columns="2" >
         <h:outputLabel value=" Name : "/>
  //see how the entity object “newBlog” injected in CDI bean “BlogController”  is used in EL here    
  <h:inputText value="#{newBlog.name}"/>
         <h:outputLabel value="Content :"/>
         <h:inputText value="#{newBlog.content}"/>
               
       <h:commandButton value="Add New Blog"                                 
                     action="#{blogController.addNewBlog()}"/>  //method in the CDI bean is accessed in EL
         </h:panelGrid>
         </h:form>
    </h:body>

</html>

 

blog/List.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html">

    <h:head>

        <title>Blog List</title>
    </h:head>

    <h:body>

        <h:form>
/* <h:datatable iterates through the list  */
            <h:dataTable value="#{blogController.blogList}" var="blog">
                <h:column>
                    #{blog.name},
                </h:column>

                <h:column>
                    #{blog.content}
                </h:column>
            </h:dataTable>
        </h:form>

    </h:body>

</html>

Run the project

You can deploy the project from the IDE. When you get the “successfully deployed message”  in the Output window, you can go to Services widow and choose “Servers” à Glassfish Server à Applications. You can see your app deployed. Right click on it and choose “Open in Browser”. The browser will open and appear as in Figure-3.

Figure-4
Click the link “Create a New Blog”. You will get Figure-5.If you don’t fill up name and/or content and click the button you will get some validation error as in Figure-6. If you fill up the text boxes correctly and click the button you will see the records in the database table including the newly-added one.

Conclusion 

Dependency injection is extremely useful for acquiring references to other beans. It was Spring that popularized DI. But CDI has taken DI to a new level, besides making Java EE programming simpler, leaner and more-sophisticated. With CDI the injected beans are not only type-safe but also “live in” well defined context/scopes. Custom annotations annotated with @Qualifier are used, when different instances of a bean need to be injected- eg: when more than one class implements an interface that needs to be injected. These custom annotations enable Strong typing and consequent reduction in run-time errors. The support for interceptors isn’t as powerful as AspectJ’s;  but  it’s much easier to use and with fewer complications. It has also support for decorators, another form of interceptors.  But its support for injecting events has introduced a slight twist to dependency injection and leads to highly de-coupled systems, by enabling events to be delivered to other beans without any compile-time dependencies. The conversation scope has its uses. This is one area where CDI can supplant EJB. Conversation Scoped CDI beans can replace stateful session beans. Conversation- scoped beans are much easier to use and more appropriate for most applications. In the past, most stateful session beans were being used to implement a long-running business process, now called a conversation. Conversations are only the start; CDI supports the creation of custom scopes, which are much more flexible and lend themselves to creative and elegant solutions that are much easier to maintain.

Note:
If you want to use in place of Glassfish, another open source application server -Wildfly-8.2.1.Final (open source version of Jboss Server) , you need NetBeans-8.1.Earlier versions do not seem to work with Wildfly-8.2.1 correctly. To use Glassfish see whether the mysql driver is available in [Glassfish installation folder]/glassfish/domain/domain1/lib. But for Wildfly you have to create a data-source before creating the project. For the steps to create the data-source please consult Migrating a Java EE App from GlassFish to WildFly by Hildeberto Mendonça and Efraim Gentil Posted by Arun Gupta on Wildfly site. Once you create the data-source, You need not create the data-source in the IDE. Other steps and the code are the same both for Glassfish and Wildfly.

Figure-6








}