Primefaces Spring EclipseLink NoSQL with MongoDB & Oracle NoSQL DB

Filed Under: MongoDB

We’ve explored how can we achieve integration between EclipseLink JPA and a well-known Relational Database like MySQL. EclipseLink provides you more than integrating with Relational Databases Platforms, it also has supported MongoDB and Oracle NoSQL databases.

Next coming releases will also give you the ability to use: Cassandra, Google Big Table and CouchDB as a NoSQL persistence stores. In this tutorial we would provide you a full-fledged example that help you make a JPA integration with MongoDB and Oracle NoSQL databases.

Required Tools

Final Project Structure

Primefaces - Eclipselink - JPA - Final Project Structure

Employee Mapping


package com.journaldev.jpa.data;

import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import org.eclipse.persistence.nosql.annotations.DataFormatType;
import org.eclipse.persistence.nosql.annotations.Field;
import org.eclipse.persistence.nosql.annotations.NoSql;
@Entity
@NoSql(dataFormat=DataFormatType.MAPPED)
public class Employee {
	@Id
	@GeneratedValue
	@Field(name="_id")
	private String employeeId;
	@Field
	private String employeeName;
	@Field
	private Date employeeHireDate;
	@Field
	private double employeeSalary;

	public String getEmployeeId() {
		return employeeId;
	}

	public void setEmployeeId(String employeeId) {
		this.employeeId = employeeId;
	}

	public String getEmployeeName() {
		return employeeName;
	}

	public void setEmployeeName(String employeeName) {
		this.employeeName = employeeName;
	}

	public Date getEmployeeHireDate() {
		return employeeHireDate;
	}

	public void setEmployeeHireDate(Date employeeHireDate) {
		this.employeeHireDate = employeeHireDate;
	}

	public double getEmployeeSalary() {
		return employeeSalary;
	}

	public void setEmployeeSalary(double employeeSalary) {
		this.employeeSalary = employeeSalary;
	}
}

Here’s detailed explanations for above code:

  • Employee entity must be annotated with @Entity annotation. That annotation is required by JPA specification.
  • Employee identifier must be annotated with @Id. This attribute should be mapped into defaulted _id attribute. In case you’ve eliminated such that mapping, a new EMPLOYEEIDcolumn will be added into your Employee collection. The value of _id attribute has generated automatically by both of MongoDB and Oracle NoSQL databases.
  • You have an option of annotating your Employee’s attributes using @Field annotation. In case they’re eliminated the eclipselink will do the mapping automatically. If you weren’t created an Employee collection into your own MongoDB or Oracle NoSQL, eclipselink will do the process of creation behind you and it will insert your document (i.e. employee instance) respectively.
  • Your entity must be annotated with @NoSql. This annotation will make sure the entity being persisted doesn’t represent a relational entity. DataFormat attribute specify the type that’s used for representing the data stored. MongoDB and Oracle NoSQL use Key-BSON format which is similar to a map in structure, so MAPPED value is used.

MongoDB – Persistence Context

For connecting NoSQL persistence store, a persistence.xml file should be defined.

persistence.xml


<persistence xmlns="http://java.sun.com/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
	version="2.0">
	<persistence-unit name="eclipselink.mongodb.jpa" transaction-type="RESOURCE_LOCAL">
		<class>com.journaldev.jpa.data.Employee</class>
		<properties>
			<property name="eclipselink.target-database" value="org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform"/>
            <property name="eclipselink.nosql.connection-spec" value="org.eclipse.persistence.nosql.adapters.mongo.MongoConnectionSpec"/>
            <property name="eclipselink.nosql.property.mongo.port" value="27017"/>
            <property name="eclipselink.nosql.property.mongo.host" value="localhost"/>
            <property name="eclipselink.nosql.property.mongo.db" value="JournalDev"/>
            <property name="eclipselink.logging.level" value="FINEST"/>
		</properties>
	</persistence-unit>
</persistence>

Here’s detailed explanation for the code listed above:

  • NoSQL persistence unit are configured the same as JPA persistence units, persistence.xml is used to define the persistence unit.
  • The eclipselink.nosql.connection-spec specifies name of the EISConnectionSpec class which will be used to connect the NoSQL persistence store.
  • The eclipselink.target.database specifies the NoSQL platform class.

OracleNoSQL- Persistence Context

persistence.xml


	<persistence-unit name="eclipselink.oraclenosql.jpa" transaction-type="RESOURCE_LOCAL">
		 <class>com.journaldev.jpa.data.Employee</class>
	     <properties>
	         <property name="eclipselink.target-database" value="org.eclipse.persistence.nosql.adapters.nosql.OracleNoSQLPlatform"/>
	         <property name="eclipselink.nosql.connection-spec" value="org.eclipse.persistence.nosql.adapters.nosql.OracleNoSQLConnectionSpec"/>
	         <property name="eclipselink.nosql.property.nosql.host" value="mohammad-amr-lt:5000"/>
	         <property name="eclipselink.nosql.property.nosql.store" value="kvstore"/>
	         <property name="eclipselink.logging.level" value="FINEST"/>
	     </properties>
	</persistence-unit>

Here’s below detailed explanation for listed code above:

  • Oracle NoSQL database provides you ability to create your own store at bootstrap time. If you’ve installed Oracle NoSQL database, you should execute java -Djava.net.preferIPv4Stack=true -jar lib\kvstore.jar kvlite for getting Oracle NoSQL database started. As a result of execution last command, you should notice  Created new kvlite store with args:
    -root ./kvroot -store kvstore -host mohammad-amr-lt -port 5000 -admin 5001
    entries.
  • Notice using of kvstorethat’s used in the persistence unit.

EclipseLink – Spring Context Integration

Eclipselink can be integrated seamlessy with Spring Framework. This type of integration will allow you acquiring the required entity manager easily and without any need for you to get involved.

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
 <!-- Enable Spring Annotation Configuration -->
 <context:annotation-config />
 <!-- Scan for all of Spring components such as Spring Service -->
 <context:component-scan base-package="com.journaldev.spring.service"></context:component-scan>

 <!-- Necessary to get the entity manager injected into the factory bean -->
 <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

 <!-- Entity Manager Factory -->
 <bean id="entityManagerFactory"
 class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
 <property name="persistenceUnitName" value="eclipselink.mongodb.jpa"></property>
 </bean>

 <!--
 <bean id="entityManagerFactory"
 class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
 <property name="persistenceUnitName" value="eclipselink.oraclenosql.jpa"></property>
 </bean>
 -->

 <!-- Transaction Manager -->
 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
 <property name="entityManagerFactory" ref="entityManagerFactory" />
 </bean>

 <!-- Detect @Transactional -->
 <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

Here’s detailed explanation for code listed above:

  • Spring framework will be looking for its configuration context – by default applicationContext.xml – once the server getting its listener started. The listener of Spring framework should be defined inside your application’s deployment descriptor. See Primefaces Deployment Descriptor section below.
  • MongoDB is a Transactional persistence store, therefore, it’s required to include all Transactional staffs for getting your documents retained.
  • EntityManagerFactory configured this time by passing the name of the persistence unit. Unlike Oracle and MySQL, for creating an instance of it, EclipseJPAVendor instance should be passed.
  • Use given persistence unit name that’s defined for Oracle NoSQL once you want to connect Oracle NoSQL database.

Primefaces Deployment Descriptor

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5" metadata-complete="true">
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>/faces/*</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.xhtml</url-pattern>
	</servlet-mapping>
	<context-param>
		<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
		<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
		<param-value>client</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<listener>
		<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
	</listener>
</web-app>

Here’s detailed explanation for listed code above:

  • Defining of ContextLoaderListener is mandatory for starting up Spring framework.

Primefaces – Faces Configuration

faces-config.xml


<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
	version="2.2">
<application>
	<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
</faces-config>

Here’s detailed explanation for listed code above:

  • SpringBeanFacesELResolver will help you inject your Spring beans into your own JSF ManagedBean

Spring Employee Service


package com.journaldev.spring.service;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.journaldev.jpa.data.Employee;

@Component
public class EmployeeService {
	@PersistenceContext
	private EntityManager em;

	public EntityManager getEm() {
		return em;
	}

	public void setEm(EntityManager em) {
		this.em = em;
	}

	@Transactional
	public void register(Employee emp) {
		// Save employee
		this.em.persist(emp);
	}

}

Here’s detailed explanation for the code listed above:

  • Using of @PersistenceContext will inject an instance of EntityManager. EntityManagerFactory that’s defined within Spring context is will be used for creating an instance of EntityManager

Primefaces RegisterEmployee ManagedBean


package com.journaldev.prime.faces.beans;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import com.journaldev.jpa.data.Employee;
import com.journaldev.spring.service.EmployeeService;

@ManagedBean
@SessionScoped
public class RegisterEmployee {

	@ManagedProperty("#{employeeService}")
	private EmployeeService employeeService;

	private Employee employee = new Employee();

	public EmployeeService getEmployeeService() {
		return employeeService;
	}

	public void setEmployeeService(EmployeeService employeeService) {
		this.employeeService = employeeService;
	}

	public Employee getEmployee() {
		return employee;
	}

	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	public String register() {
		// Calling Business Service
		employeeService.register(employee);
		// Add message
		FacesContext.getCurrentInstance().addMessage(null,
				new FacesMessage("The Employee "+this.employee.getEmployeeName()+" Is Registered Successfully"));
		return "";
	}
}

Primefaces Registration View

index.xhtml


	<html xmlns="http://www.w3.org/1999/xhtml"
		xmlns:ui="http://java.sun.com/jsf/facelets"
		xmlns:h="http://java.sun.com/jsf/html"
		xmlns:f="http://java.sun.com/jsf/core"
		xmlns:p="http://primefaces.org/ui">
	<h:head>
		<script name="jquery/jquery.js" library="primefaces"></script>
		<title>Register Employee</title>
	</h:head>
	<h:form>
		<p:growl id="messages"></p:growl>
		<p:panelGrid columns="2">
			<p:outputLabel value="Enter Employee Name:"></p:outputLabel>
			<p:inputText value="#{registerEmployee.employee.employeeName}"></p:inputText>
			<p:outputLabel value="Enter Employee Hire Date:"></p:outputLabel>
			<p:calendar value="#{registerEmployee.employee.employeeHireDate}"></p:calendar>
			<p:outputLabel value="Enter Employee Salary:"></p:outputLabel>
			<p:inputText value="#{registerEmployee.employee.employeeSalary}"></p:inputText>
		</p:panelGrid>
		<p:commandButton value="Register" action="#{registerEmployee.register}" update="messages"></p:commandButton>
	</h:form>
	</html>

MongoDB Demo

Here’s below, you would see all screen shots that explain you the employee while it’s registered and the persisted employee document against Mongo database.

Primefaces Employee Registered Against MongoDB

MongoDB - Persisted Employees

  • We’ve used MongoVUE Tool for displaying Mongo database collections and records.
  • As we’ve mentioned earlier, _id column is added automatically for all of your defined collections. To map your collection id and _id defaulted one, @Filed(name=”_id”) annotation should be used. In case you’ve not mapped it, a new column EMPLOYEEID will be added.

OracleNoSQL Demo

Primefaces Employee Registered Against OracleNoSQL

OracleNoSQL - Persisted Employees

Technical Help

Getting Oracle NoSQL database installed and started into your environment isn’t easy task. Following main steps you need to ensure that help you achieve that.

  • Download Oracle NoSQL binary.
  • Unzip downloaded file.
  • Execute java -Djava.net.preferIPv4Stack=true -jar lib\kvstore.jar kvlite for starting the database.
  • Configuring Apache Tomcat 8 by adding -Djava.net.preferIPv4Stack=true into its VM arguments.

Oracle NoSQL - Terminal Commands

Apache Tomcat 8 - Debug - VM Arguments

Maven Dependencies File

pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>Primefaces-EclipseLink-Spring-Mongo-Oracle-NoSQL-Sample</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>Primefaces-EclipseLink-Spring-Mongo-Oracle-NoSQL-Sample Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<repositories>
		<repository>
			<id>prime-repo</id>
			<name>PrimeFaces Maven Repository</name>
			<url>http://repository.primefaces.org</url>
			<layout>default</layout>
		</repository>
		<repository>
			<id>oss.sonatype.org</id>
			<name>OSS Sonatype Staging</name>
			<url>https://oss.sonatype.org/content/groups/staging</url>
		</repository>
	</repositories>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<!-- Faces Implementation -->
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-impl</artifactId>
			<version>2.2.4</version>
		</dependency>
		<!-- Faces Library -->
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-api</artifactId>
			<version>2.2.4</version>
		</dependency>
		<!-- Primefaces Version 5 -->
		<dependency>
			<groupId>org.primefaces</groupId>
			<artifactId>primefaces</artifactId>
			<version>5.0</version>
		</dependency>
		<!-- JSP Library -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.1</version>
		</dependency>
		<!-- JSTL Library -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.1.2</version>
		</dependency>
		<!-- MySQL driver connector library -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.31</version>
		</dependency>
		<!-- Spring ORM -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>4.0.3.RELEASE</version>
		</dependency>
		<!-- Spring Web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.0.3.RELEASE</version>
		</dependency>
		<!-- Dependencies for Eclipse JPA Persistence API -->
		<dependency>
			<groupId>org.eclipse.persistence</groupId>
			<artifactId>eclipselink</artifactId>
			<version>2.6.0-M3</version>
		</dependency>
		<!-- Dependency for EclipseLink NoSQL Persistence API -->
		<dependency>
			<groupId>org.eclipse.persistence</groupId>
			<artifactId>org.eclipse.persistence.nosql</artifactId>
			<version>2.6.0-M3</version>
		</dependency>
		<!-- MongoDB Driver -->
		<dependency>
			<groupId>org.mongodb</groupId>
			<artifactId>mongo-java-driver</artifactId>
			<version>2.12.3</version>
		</dependency>
		<!-- EclipseLink JPA for OracleNoSQL -->
		<dependency>
			<groupId>org.eclipse.persistence</groupId>
			<artifactId>org.eclipse.persistence.oracle.nosql</artifactId>
			<version>2.6.0-M3</version>
		</dependency>
		<!-- Oracle NoSQL Client Driver -->
		<dependency>
			<groupId>com.oracle.kv</groupId>
			<artifactId>kvclient_3.0.5</artifactId>
			<version>3.0.5</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Summary

Not only Relational databases can be integrated with a JPA persistence layer. EclipseLink provides you the ability to integrate seamlessly with two major popular NoSQL vendors. This tutorial has used both of Mongo and Oracle NoSQL databases for persisting an instance of employee entity. Contribute us by commenting below and find project source code to download.

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages