dcsimg
September 28, 2016
Hot Topics:

Using MongoDB in a Java EE7 Framework

  • March 30, 2016
  • By Manoj Debnath
  • Send Email »
  • More Articles »

The central point of creating an application to perform in an enterprise environment is that the application must be secure, portable, and highly available. It also must be able to interact with diverse systems, yet manageable from a prime location. JEE7 is an important merger framework for all the features; It works pretty seamlessly with MongoDB. The article goes hands on in creating a Web application using MongoDB as the storage.

The Arrangement Is...

It's a simple, lean CRUD application, or rather a part of it, using some of the stalwarts of JEE7 such as EJB and JSF. The idea is to reposit a Candidate in MongoDB, search required Candidates according to the skill one has, and also will be able to remove a particular Candidate from the database altogether.

What You Need...

A JEE application runs in a container that provides the norms of the enterprise application along with all necessary components. This container, in our case, is the application server WildFly. So, apart from the Netbeans IDE, and JDK, we need a WildFly Application Server. Also:

  • MongoDB: The document database.
  • MongoDB JDBC: The database driver for Java connectivity to MongoDB.
  • Google-Gson: This is an external Java Library useful for converting Java Objects into their JSON representation and vice-versa. This peripheral library is optional, but convenient on occasional circumstances.

Note that any IDE and Application Server can be used, provided it is JEE7 compatible.

Once downloaded/installed, a Web Application project in Netbeans can be created as follows.

Open NetBeans, File, New Project...

Mongo1
Figure 1: Opening a new project

Give a name of the Project.

Mongo2
Figure 2: Naming the project

Apply proper Server settings.

Mongo3
Figure 3: Applying the proper Server settings

Apply the JavaServer Faces framework. Finish.

Mongo4
Figure 4: Applying the JavaServer Faces framework

Once the project has been created, include gson-x.x.x.jar and mongo-java-driver-3.2.1.jar as an external library to the project.

Candidate.java

This class represents the schema for the database. This structure shall be used to create MongoDB storage, as follows:

{
   "_id" : ObjectId("56c810f9a7986c1b455f7fda"),
   "id" : 1,
   "skillSet" : "SQL Java C++",
   "name" : "Richard Stallman",
   "email" : "richard@somemail.com",
   "phone" : "9876525435",
   "gender" : "Male",
   "lastDegree" : "MS",
   "lastDesig" : "Programmer",
   "expInYearMonth" : 9.6
}

_id is auto generated and is used to uniquely identify a document. If we want to use this auto generated ID in Java class, we may write the Candidate class as follows.

public class Candidate {

   private int _id;   //instead of private int id;
   ...

But here, we have used our own custom ID, although MongoDB is still supplying an autogenerated _id. It's our choice to not use it for now.

package org.mano.example;

public class Candidate {
   private int id;
   private String skillSet;
   private String name;
   private String email;
   private String phone;
   private String gender;
   private String lastDegree;
   private String lastDesig;
   private float expInYearMonth;

   public Candidate() {
   }

   public Candidate(int id, String skillSet, String name,
         String email, String phone, String gender,
         String lastDegree, String lastDesig,
         float expInYearMonth) {
      this.id = id;
      this.skillSet = skillSet;
      this.name = name;
      this.email = email;
      this.phone = phone;
      this.gender = gender;
      this.lastDegree = lastDegree;
      this.lastDesig = lastDesig;
      this.expInYearMonth = expInYearMonth;
   }

   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public String getSkillSet() {
      return skillSet;
   }

   public void setSkillSet(String skillSet) {
      this.skillSet = skillSet;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getEmail() {
      return email;
   }

   public void setEmail(String email) {
      this.email = email;
   }

   public String getPhone() {
      return phone;
   }

   public void setPhone(String phone) {
      this.phone = phone;
    }

   public String getGender() {
      return gender;
   }

   public void setGender(String gender) {
      this.gender = gender;
   }

   public String getLastDegree() {
      return lastDegree;
   }

   public void setLastDegree(String lastDegree) {
      this.lastDegree = lastDegree;
   }

   public String getLastDesig() {
      return lastDesig;
   }

   public void setLastDesig(String lastDesig) {
      this.lastDesig = lastDesig;
   }

   public float getExpInYearMonth() {
      return expInYearMonth;
   }

   public void setExpInYearMonth(float expInYearMonth) {
      this.expInYearMonth = expInYearMonth;
   }
}

CandidateFacade.java

This class implements CRUD operations with the MongoDB through a JDBC Driver. This class is designated as stateless because here we do not want to perform the work represented by this class to span across multiple method invocations. Also, stateless beans are lightweight and easy to manage. However, this is just one representation. Other representations are equally possible under various circumstances.

package org.mano.example;

import com.google.gson.Gson;
import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import org.bson.BsonDocument;
import org.bson.BsonRegularExpression;
import org.bson.Document;

@Stateless
public class CandidateFacade {

   private static final Logger LOGGER =
      Logger.getLogger(CandidateFacade.class.getName());
   private final static String HOST = "localhost";
   private final static int PORT = 27017;

   public final static String DATABASE = "cvbank";
   public final static String COLLECTION = "biodata";

   public MongoClient mongoClient() {
      return new MongoClient(new ServerAddress(HOST, PORT));
   }

   public void create(Candidate c) {
      MongoClient mongoClient = new
         MongoClient(new ServerAddress(HOST, PORT));
      MongoCollection<Document> collection =
         mongoClient.getDatabase(DATABASE).getCollection(COLLECTION);
      if  (c!=null) {

         Document d = new Document().append("id", c.getId())
            .append("skillSet", c.getSkillSet())
            .append("name", c.getName())
            .append("email", c.getEmail())
            .append("phone", c.getPhone())
            .append("gender", c.getGender())
            .append("lastDegree", c.getLastDegree()
            .append("lastDesig", c.getLastDesig())
            .append("expInYearMonth", c.getExpInYearMonth());
         collection.insertOne(d);
      }


   }

   public void update(Candidate c) {
      MongoClient mongoClient = new
         MongoClient(new ServerAddress(HOST, PORT));
      MongoCollection<Document> collection =
         mongoClient.getDatabase(DATABASE).getCollection(COLLECTION);
      Document d = new Document();
      d.append("id", c.getId())
         .append("skillSet", c.getSkillSet())
         .append("name", c.getName())
         .append("email", c.getEmail())
         .append("phone", c.getPhone())
         .append("gender", c.getGender())
         .append("lastDegree", c.getLastDegree())
         .append("lastDesig", c.getLastDesig())
         .append("expInYearMonth", c.getExpInYearMonth());
      collection.updateOne(new Document("id", c.getId()),
         new Document("$set", d));
   }

   public void delete(Candidate c) {
      MongoClient mongoClient = new
         MongoClient(new ServerAddress(HOST, PORT));
      MongoCollection<Document> collection =
         mongoClient.getDatabase(DATABASE).getCollection(COLLECTION);
      collection.deleteOne(new Document("id", c.getId()));
   }

   public List<Candidate> find(String filter) {
      List<Candidate> list = new ArrayList<>();
      MongoClient mongoClient =
         new MongoClient(new ServerAddress(HOST, PORT));
      MongoCollection<Document> collection =
         mongoClient.getDatabase(DATABASE).getCollection(COLLECTION);
      FindIterable<Document> iter;
      if (filter == null || filter.trim().length() == 0) {
         iter = collection.find();
      } else {

         BsonRegularExpression bsonRegex = new
            BsonRegularExpression(filter);
         BsonDocument bsonDoc = new BsonDocument();
         bsonDoc.put("skillSet", bsonRegex);
         iter = collection.find(bsonDoc);

      }
      iter.forEach(new Block<Document>() {
         @Override
         public void apply(Document doc) {
            list.add(new Gson().fromJson(doc.toJson(), Candidate.class));
         }
      });
      return list;
   }
}

CandidateController.java

This is the managed bean class that acts as a controller to the JSF pages. The @EJB annotation declaration represents a reference in the component namespace where the container performs the injection (Context Dependency Injection, CDI). The object, once created by the container, can access the data transaction operations defined in the CandidateFacade class. The annotation @PostConstruct ensures that the dependency injected is initialized before use in the JSF pages. Observe how the Candidate list gets populated with pre-reposited data in the MongoDB database.

package org.mano.example;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named("candidateController")
@SessionScoped
public class CandidateController implements Serializable {

   private Candidate candidate = new Candidate();
   private String filter = "";

   @EJB
   private CandidateFacade candidateEJB;
   private List<Candidate> list = new ArrayList<>();

   public CandidateController() {
   }

   @PostConstruct
   private void init() {
      find();
   }

   public void create() {
      candidateEJB.create(candidate);
      find();
   }

   public void find() {
      list = candidateEJB.find(filter);
   }

   public void delete() {
      candidateEJB.delete(candidate);
      find();
   }

   public Candidate getCandidate() {
      return candidate;
   }

   public void setCandidate(Candidate candidate) {
      this.candidate = candidate;
   }

   public CandidateFacade getCandidateEJB() {
      return candidateEJB;
   }

   public void setCandidateEJB(CandidateFacade candidateEJB) {
      this.candidateEJB = candidateEJB;
   }

   public String getFilter() {
      return filter;
   }

   public void setFilter(String filter) {
      this.filter = filter;
   }

   public List<Candidate> getList() {
      return list;
   }

   public void setList(List<Candidate> list) {
      this.list = list;
   }
}

index.xhtml

Once the server side part is complete, we need a view for inserting a new document as well as displaying the Candidate details. The page also must contain a button to perform a filter on the skill set of the Candidate list and a delete button, respectively. The following is the index.xhtml page, which needs to be added to the project's web pages

<?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"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
   <h:head>
      <title>Facelet Title</title>

      <link href="styles.css" rel="stylesheet" type="text/css"/>

   </h:head>
   <h:body>
      <h3>New Candidate</h3>
      <h:form>
         <h:panelGrid columns="2" styleClass="form">
            <h:outputLabel>ID</h:outputLabel>
            <h:inputText value="#{candidateController.candidate.id}"/>
            <h:outputLabel>Skill Set</h:outputLabel>
            <h:inputText value=
               "#{candidateController.candidate.skillSet}"/>
            <h:outputLabel>Name</h:outputLabel>
            <h:inputText value=
               "#{candidateController.candidate.name}"/>
            <h:outputLabel>Email</h:outputLabel>
            <h:inputText value=
               "#{candidateController.candidate.email}"/>
            <h:outputLabel>Phone</h:outputLabel>
            <h:inputText value=
               "#{candidateController.candidate.phone}"/>
            <h:outputLabel>Gender</h:outputLabel>
            <h:inputText value=
               "#{candidateController.candidate.gender}"/>
            <h:outputLabel>Last Degree</h:outputLabel>
            <h:inputText value=
               "#{candidateController.candidate.lastDegree}"/>
            <h:outputLabel>Last Designation</h:outputLabel>
            <h:inputText value=
               "#{candidateController.candidate.lastDesig}"/>
            <h:outputLabel>Experience</h:outputLabel>
            <h:inputText value=
               "#{candidateController.candidate.expInYearMonth}"/>
         </h:panelGrid>
         <p>
            <h:commandButton actionListener=
               "#{candidateController.create()}"
               styleClass="buttons" value="Add New" />
         </p>
      </h:form>

      <h:form id="view">

         <h:outputLabel value="Search Skill "
                        style="font-weight:bold"/> &nbsp;&nbsp;
         <h:inputText value=
            "#{candidateController.filter}" /> &nbsp; &nbsp;
         <h:commandButton actionListener=
               "#{candidateController.find()}"
            styleClass="buttons" value="Search" />
         <br/>

         <h:panelGrid >
            <h:dataTable value="#{candidateController.list}"
                         var="c"
                         styleClass="table"
                         headerClass="table-header"
                         rowClasses="table-odd-row,table-even-row">
               <h:column>
                  <f:facet name="header">ID</f:facet>
                  <h:outputText value="#{c.id}" />
               </h:column>
               <h:column>
                  <f:facet name="header">Skills</f:facet>
                  <h:outputText value="#{c.skillSet}" />
               </h:column>
               <h:column>
                  <f:facet name="header">Name</f:facet>
                  <h:outputText value="#{c.name}" />
               </h:column>
               <h:column>
                  <f:facet name="header">Email</f:facet>
                  <h:outputText value="#{c.email}" />
               </h:column>
               <h:column>
                  <f:facet name="header">Phone</f:facet>
                  <h:outputText value="#{c.phone}"/>
               </h:column>

               <h:column>
                  <f:facet name="header">Gender</f:facet>
                  <h:outputText value="#{c.gender}" />
               </h:column>

               <h:column>
                  <f:facet name="header">Qualification</f:facet>
                  <h:outputText value="#{c.lastDegree}" />
               </h:column>
               <h:column>
                  <f:facet name="header">Designation</f:facet>
                  <h:outputText value="#{c.lastDesig}" />
               </h:column>
               <h:column>
                  <f:facet name="header">Experience</f:facet>
                  <h:outputText value="#{c.expInYearMonth}" />
               </h:column>
               <h:column>
                  <h:commandButton actionListener=
                     "#{candidateController.delete()}"
                     styleClass="buttons"
                     value="Delete [ID: #{c.id}]" />
               </h:column>
            </h:dataTable>
         </h:panelGrid>
      </h:form>
   </h:body>
</html>

Styles.css

Let's add a little style for an "eye candy" appearance.

.form{
   border: thin solid lightskyblue;
   font-family: Helvetica, verdana, sans-serif;
   font-size: small;
   background: powderblue;
}
.table {
   border: thin solid lightskyblue;
   font-family: Helvetica, verdana, sans-serif;
   font-size: small;
}
.table-header {
   text-align: center;
   font-style: italic;
   color: whitesmoke;
   background: darkcyan;
}
.table-odd-row {
   height: 25px;
   text-align: center;
   background: MediumTurquoise;
}
.table-even-row {
   text-align: center;
   background: PowderBlue;
}

That's it. What we get on running the application is shown in Figure 5.

Mongo5
Figure 5: Application running in a Web browser

Conclusion

This project, though, does not provide a comprehensive guide to enterprise development, and yet can be used as a template for building applications that require MongoDB with JEE capabilities. The improvements in the JEE specification make application development hassle free with minimal code and little configuration.


Tags: MongoDB, database, JDBC, web application, JSF, EJB, WildFly, CRUD, Java EE7, Context Dependency Injection




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date
Rocket Fuel