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
Employee Mapping
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
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 newEMPLOYEEID
column 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 useKey-BSON
format which is similar to a map in structure, soMAPPED
value is used.
MongoDB – Persistence Context
For connecting NoSQL persistence store, a persistence.xml
file should be defined.
persistence.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<persistence xmlns="https://java.sun.com/xml/ns/persistence" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://java.sun.com/xml/ns/persistence https://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
1 2 3 4 5 6 7 8 9 10 11 12 |
<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 libkvstore.jar kvlite for getting Oracle NoSQL database started. As a result of execution last command, you should notice
Created new kvlite store with args:
entries.
-root ./kvroot -store kvstore -host mohammad-amr-lt -port 5000 -admin 5001 - Notice using of
kvstore
that’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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:tx="https://www.springframework.org/schema/tx" xmlns:context="https://www.springframework.org/schema/context" xmlns:aop="https://www.springframework.org/schema/aop" xmlns:util="https://www.springframework.org/schema/util" xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-3.2.xsd https://www.springframework.org/schema/tx https://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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xmlns:web="https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://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
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="UTF-8"?> <faces-config xmlns="https://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<html xmlns="https://www.w3.org/1999/xhtml" xmlns:ui="https://java.sun.com/jsf/facelets" xmlns:h="https://java.sun.com/jsf/html" xmlns:f="https://java.sun.com/jsf/core" xmlns:p="https://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.
- 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
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 libkvstore.jar kvlite for starting the database.
- Configuring Apache Tomcat 8 by adding -Djava.net.preferIPv4Stack=true into its VM arguments.
Maven Dependencies File
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://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>https://maven.apache.org</url> <repositories> <repository> <id>prime-repo</id> <name>PrimeFaces Maven Repository</name> <url>https://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.