This guide walks you through the process of connecting to Oracle databases from Java EE web applications using JPA and Apache DeltaSpike Data. The application developed in this guide consists of a web UI with a list of employees loaded from an Oracle database and a filter to allow searching employees by their names.
Prerequisites
This guide assumes you have:
- Installed Oracle Database. The syntax presented in this guide is compatible with Oracle Database Express Edition 11g Release 2 (11.2) which is a free-to-use entry-level version of Oracle Database 11g.
- Installed Java EE 7 server like Oracle WebLogic Server. This guide uses Oracle WebLogic Server 12cR2 (12.2.1.1.0).
- Installed your favorite IDE and Maven.
No previous experience with Java EE, JPA or Apache DeltaSpike is required to follow this guide.
Create the database objects
Connect to the Oracle database and create the following table:
CREATE TABLE employee( id NUMBER NOT NULL, name VARCHAR(255), email VARCHAR(255) );
Create the following sequence which is going to be used as a generator of the values in the id
column of the previous table:
CREATE SEQUENCE employee_seq INCREMENT BY 1;
Add some test data, such as the following:
INSERT INTO employee(id, name, email) VALUES(employee_seq.nextval, 'John Volga', 'john@test.com'); INSERT INTO employee(id, name, email) VALUES(employee_seq.nextval, 'Matti Tahvonen', 'matti@test.com'); INSERT INTO employee(id, name, email) VALUES(employee_seq.nextval, 'Sami Ekblad', 'sami@test.com'); INSERT INTO employee(id, name, email) VALUES(employee_seq.nextval, 'Nicolas Frankel', 'nicolas@test.com'); INSERT INTO employee(id, name, email) VALUES(employee_seq.nextval, 'Alejandro Duarte', 'alejandro@test.com');
Remember to commit the changes to the database if necessary.
Create a new DataSource
If you haven’t, create a new WebLogic domain (make sure you add an Administration Server when creating the domain and take note of the path to the created domain). Start the WebLogic server, login into the Administration Console (available at http://localhost:7001/console
by default), and add a new generic JDBC DataSource. Make sure to use the following configuration when creating the DataSource
:
-
Name: DemoDS
-
Scope: Global
-
JNDI Name: demoDS
-
Database Type: Oracle
Configure the database name, hostname, port, database user name, and password to connect to your Oracle Database Server instance. You don’t need to specify any additional connection properties.
Make sure you select a target to deploy the new DataSource
(AdminServer, for example) in the last step of the DataSource
creation wizard.
Install the WebLogic Maven Plugin
The WebLogic Maven Plugin allows you to perform several operations such as starting the WebLogic server and deploying applications to it. In order to use the plugin, you need to install it into your local Maven repository first. Execute the following commands in a terminal:
cd ORACLE_HOME/oracle_common/plugins/maven/com/oracle/maven/oracle-maven-sync/12.2.1 mvn install:install-file -DpomFile=oracle-maven-sync-12.2.1.pom -Dfile=oracle-maven-sync-12.2.1.jar mvn com.oracle.maven:oracle-maven-sync:push -DoracleHome=ORACLE_HOME
Replace ORACLE_HOME
with the full path of the directory where you installed WebLogic and HOME
with the full path of your home directory.
Create a Java EE application using Maven
An easy way to create a new Java EE application is by using the webapp-javaee7
Maven archetype. Execute the following command to create a new Java EE application:
mvn -B archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=webapp-javaee7 -DarchetypeVersion=1.1 -DgroupId=com.example -DartifactId=demo -Dversion=1.0-SNAPSHOT
You should get a Maven project you can import into your favorite IDE.
Add the following into the <build>
section of the pom.xml
file:
<finalName>demo</finalName>
This configures the name of the generated WAR file to demo.war
instead of something like demo-1.0-SNAPSHOT.war
. This makes the web application available at localhost:7001/demo
without any version information in the URI.
Add the WebLogic Maven Plugin
Add the following into the <plugins>
section of the pom.xml
file:
<plugin> <groupId>com.oracle.weblogic</groupId> <artifactId>weblogic-maven-plugin</artifactId> <version>12.2.1-1-0</version> <configuration> <domainHome>PATH_TO_YOUR_DOMAIN_DIRECTORY</domainHome> <user>YOUR_WEBLOGIC_USER</user> <password>YOUR_WEBLOGIC_PASSWORD</password> </configuration> </plugin>
Change PATH_TO_YOUR_DOMAIN_DIRECTORY
with the full path of the WebLogic domain you previously created. Also change YOUR_WEBLOGIC_USER
and YOUR_WEBLOGIC_PASSWORD
with the actual values required to connect to your WebLogic instance.
Add the required dependencies
Add the Apache DeltaSpike Data and Vaadin dependencies in the pom.xml
file:
<repositories> <repository> <id>vaadin-addons</id> <url>http://maven.vaadin.com/vaadin-addons</url> </repository> <repository> <id>vaadin-prereleases</id> <url>http://maven.vaadin.com/vaadin-prereleases</url> </repository> </repositories> <dependencyManagement> <dependencies> <dependency> <groupId>org.apache.deltaspike.distribution</groupId> <artifactId>distributions-bom</artifactId> <version>1.7.1</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.vaadin</groupId> <artifactId>vaadin-bom</artifactId> <version>8.0.0.beta1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.deltaspike.modules</groupId> <artifactId>deltaspike-data-module-api</artifactId> </dependency> <dependency> <groupId>org.apache.deltaspike.modules</groupId> <artifactId>deltaspike-data-module-impl</artifactId> </dependency> <dependency> <groupId>com.vaadin</groupId> <artifactId>vaadin-server</artifactId> </dependency> <dependency> <groupId>com.vaadin</groupId> <artifactId>vaadin-client-compiled</artifactId> </dependency> <dependency> <groupId>com.vaadin</groupId> <artifactId>vaadin-themes</artifactId> </dependency> <dependency> <groupId>com.vaadin</groupId> <artifactId>vaadin-cdi</artifactId> <version>2.0.0.beta1</version> </dependency> </dependencies>
Note that WebLogic includes the Oracle JDBC drivers and you don’t need to add the dependency in the pom.xml
file. If you are not using WebLogic, you have to download the Oracle JDBC driver from http://www.oracle.com/technetwork/database/features/jdbc/index-091264.html
and install it to your Java EE server or include it in your war package. The easiest way to do this is to install the downloaded JAR file into your local Maven repository and then include it as a standard dependency in the pom.xml
file.
Configure the database connection
This guide uses JPA as a persistence technology, thus, a persistence unit must be defined. Define the following persistence unit in a new persistence.xml
file in the resources/META-INF/
directory:
<?xml version="1.0"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="demodb"> <jta-data-source>demoDS</jta-data-source> <class>com.example.Employee</class> </persistence-unit> </persistence>
The previous persistence unit points to the DataSource
previously defined in the application server by using the jta-data-source
element.
Create the following CdiConfig
class:
package com.example; import javax.enterprise.context.Dependent; import javax.enterprise.inject.Produces; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; public class CdiConfig { @Produces @PersistenceContext(unitName = "demodb") @Dependent public EntityManager entityManager; }
In JPA, the interaction with this persistence unit is done through an EntityManager
object. In Java EE servers you typically inject an EntityManager
with the @PersistenceContext
annotation. However, this guide uses Apache DeltaSpike Data, a plain CDI library, to define queries. To make the EntityManager
and other CDI objects available to it through the @Inject
annotation, the EntityManager
must be exposed as a CDI bean as configured in the previous class.
Create an Employee class
Create the following Employee
class to encapsulate the data from the employee table:
package com.example; import javax.persistence.*; @Entity public class Employee { @Id @SequenceGenerator(name = "EmployeeSeq", sequenceName = "employee_seq") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "EmployeeSeq") private Long id; @Column private String name; @Column private String email; ... setters and getters ... }
Create a repository interface
Create the following EmployeeRepository
interface:
package com.example; import org.apache.deltaspike.data.api.EntityRepository; import org.apache.deltaspike.data.api.Repository; import javax.transaction.Transactional; import java.util.List; @Repository @Transactional public interface EmployeeRepository extends EntityRepository<Employee, Long> { List<Employee> findByNameLikeIgnoreCase(String name); }
This interface is annotated with @Repository
to allow declaring query methods. It also extends Apache DeltaSpike’s EntityRepository
which defines several ready-to-use methods such as findAll
, save
, remove
, and others. Apache DeltaSpike Data Module derives the actual queries from the methods’ names. In the previous example the "findBy
..." part indicates that a list of entities is returned, the "...byName
..." part refers to the name of the Java field used to filter the result, and the "...LikeIgnoreCase
" part makes the filter to use the like operator. For more information about Apache DeltaSpike Data Module, see the documentation at https://deltaspike.apache.org/documentation/data.html
.
Note how the repository interface is annotated with @Transactional
. This makes all the methods in the interface to be transactional. In real-life applications a service layer is typically added between the UI and the data access layers. Usually, the classes (or methods) in this service layer are Stateless EJBs or CDI beans annotated with @Transactional
and can use several repositories to modify different entity instances in the same transactional scope.
Because a JTA datasource was previously defined in the persistence.xml
file, it’s required to configure a transaction strategy. Create an apache-deltaspike.properties
file in the resources/META-INF/
directory with the following contents:
globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy=org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy
There are several strategies available. This tutorial uses ContainerManagedTransactionStrategy
which means Apache DeltaSpike won’t control transactions at all. Instead this guide uses CDI the @Transactional
annotation and the CDI container will automatically intercept the methods. You can also use Stateless EJBs which are transactional by default.
Also, create an empty beans.xml
file in the webapp/WEB-INF/
directory as it is required by CDI.
Implement the UI
Create a Vaadin UI by implementing the following VaadinUI
class:
package com.example; import com.vaadin.cdi.CDIUI; import com.vaadin.server.VaadinRequest; import com.vaadin.ui.Grid; import com.vaadin.ui.TextField; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import javax.inject.Inject; import java.util.List; @CDIUI("") public class VaadinUI extends UI { @Inject private EmployeeRepository repository; private Grid<Employee> grid = new Grid<>(); @Override protected void init(VaadinRequest vaadinRequest) { TextField filter = new TextField("Filter by name:"); filter.addValueChangeListener(e -> updateGrid(e.getValue())); grid.addColumn(Employee::getName).setCaption("Name"); grid.addColumn(Employee::getEmail).setCaption("Email"); VerticalLayout layout = new VerticalLayout(filter, grid); setContent(layout); updateGrid(""); } private void updateGrid(String filter) { List<Employee> employees = repository.findByNameLikeIgnoreCase("%" + filter + "%"); grid.setItems(employees); } }
This class creates a web UI containing a Grid
component to show all the employees in the database and a TextField
to filter the list of employees by their name. Notice how the VaadinUI
class is annotated with @CDIUI
. This allows Vaadin to use instances of this class when the application is opened in the web browser. Also notice how the @Inject
annotation is used to inject an instance of the repository class previously created.
Running the application
Execute the following command to build and run the application (WebLogic must be running before deploying the application):
mvn clean package weblogic:deploy -Dname=demo -Dsource=target/demo.war
By default, the application should be reachable at http://localhost:7001/demo
. The following is a screenshot of the running application: