Running and Deploying the Sample Code in Geronimo
OpenJPA is an open source implementation of the Java Persistence API (JPA) specification from Apache. JPA provides an agnostic Java-based API for storing and retrieving information to a backend database. It has a canonical query language named Java Persistence Query Language, or JPQL, that blends with the programming methods of Java and eliminates the need to tailor database queries for a particular database. However, JPA also supports native SQL which can be used for quick ports with a known backend database.
This tutorial is designed to walk you through the steps of setting up a simple web application to use OpenJPA in Geronimo and to transact the derby database that comes with Geronimo. The tutorial code uses a simple Java Server Page (JSP), backed up by some basic classes. It displays a table of inventory items and categories. In this tutorial, we will not dive into details regarding the JSP code. Its purpose is to be a window through which you can examine OpenJPA.
The intended audience for this tutorial is those with some knowledge and understanding of the Java programming language and who are just beginning with OpenJPA. To start, you must download the following requirements and install them on your computer. For the purposes of this tutorial, we are using Eclipse as the IDE and Microsoft Windows as the operating system of choice.
Geronimo V2.2: You can get it here. Download this file and unzip it to a permanent location. There is no installer. The server will run from the command line.
Java (J2SE) V1.6: This
tutorial was developed and tested with Java V1.6. If you don’t already have
Java V1.6 you can get the IBM JDK here or the Sun JDK here.
Eclipse V3.2 or later: This version has annotation support included.
Annotations play a large role in OpenJPA. Download
Eclipse 3.2 or later.
Apache OpenJPA library: For the purpose of implementing this
tutorial you can select OpenJPA v1.2 or greater. You can download Apache OpenJPA from the Apache
site. Note that the Milestone (openjpa-all-2.0.0-M3.jar as of this writing) is
an early release of OpenJPA 2.0 and may have some instabilities. No issues have
been noted for the usage in this tutorial.
The tutorial code files: These files are provided with this tutorial. You will add them to your Eclipse project.
Now, that you have all the prerequisites for this tutorial downloaded and installed, the following sections will walk you through the Eclipse project setup and the OpenJPA configuration. Make sure you read through and follow each part carefully.
After installing Eclipse, create a new project in a dedicated workspace for the tutorial. Complete the following setup instructions:
First, make sure your Eclipse environment is updated and has the Geronimo plugin. If you do not know how to do that, follow the instructions found at the Geronimo website.
When the New
Project settings dialog appears, use the following settings:
Geronimo has no installer and runs from the command line. Here are some quick instructions to get you started.
The sample code provided with this tutorial is working code. It is a simple inventory database program that shows items and categories. But even this simple example requires the ability to add, edit and delete entries. It requires the ability to sort and filter database queries and it requires the identification of the relationship of the items to the categories. In this example, the relationship is one to many. Knowing that relationship is important to how the code is written.
Before we analyze the code and OpenJPA, we will first deploy the sample and see it work. To deploy the sample code follow these instructions:
· Notice that the OpenJPATutorial application is now listed and that there is a clickable link under the URL heading:
11. Click on the link /OpenJPATutorial
and now you should see this:
Each of the buttons will execute OpenJPA code. The lists are filled by running
queries on the
a. Add a some categories and items
b. Make sure you test each of the buttons and see the results.
Now that everything is set up and you have seen it work, let’s look more closely at the parts of the code that use OpenJPA. The JSP code is just a prop to explore OpenJPA and we will not examine it.
The sample application source code is provided for this tutorial and you may run as-is with no customizations. However, you have the option of reproducing the code manually using the following explanations. Whichever method you choose, locate the code that corresponds to explanations as you follow along.
· Java code: This tutorial comes with the following java source files:
o index.jsp: This is the interface code only. It does call into other classes but it does not use any OpenJPA code directly.
o InventoryEntityBroker.java: This class contains methods that encapsulate the OpenJPA handling code. It is provided as a way to separate OpenJPA functionality from the web interface.
o InventoryItem.java: This is an OpenJPA Entity class file. This file is an example of a simple OpenJPA Entity with a relationship.
o InventoryCategory.java: This is an OpenJPA Entity class file. This file is an example of a simple OpenJPA Entity with a relationship.
· Persistence
code: Each entity concept that would be a database table will be its own class.
In this case, the tables are called “InventoryItem” and
“InventoryCategory”. Annotations in the Java file will associate the
properties with the database columns. The annotation, @Column, maps the property
name to the column name for synchronization with the database. If the table
corresponding tables do not exist, OpenJPA can use these annotations to create
the tables’ schema dynamically based on the property type and length.
Figure 1: InventoryCategory.java sample code
package tutorial;
import java.util.List;
import
javax.persistence.CascadeType;
import
javax.persistence.Column;
import
javax.persistence.Entity;
import
javax.persistence.GeneratedValue;
import
javax.persistence.GenerationType;
import
javax.persistence.Id;
import
javax.persistence.OneToMany;
import
javax.persistence.Version;
@Entity
public class
InventoryCategory {
private int version;
private int id;
private String categoryName;
private String categoryDescription;
List<InventoryItem> items;
public InventoryCategory(){}
@Column(name = "categoryName")
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String name) {
this.categoryName = name;
}
@Column(name = "itemDescription")
public String getCategoryDescription() {
return categoryDescription;
}
public void setCategoryDescription(String description) {
this.categoryDescription = description;
}
@Version
@Column(name = "version_field")
// not required
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
@Id
@GeneratedValue(strategy
= GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
mappedBy="category")
public List<InventoryItem> getItems()
{
return items;
}
public void setItems(List<InventoryItem> items)
{
this.items = items;
}
public void addItem(InventoryItem item)
{
this.items.add(item);
}
}
In this example, the property annotations (@Column, @Version, and @Id) are placed on the getter methods. They can alternatively be placed on the property declarations. For more information on these annotations and to see what other annotations are in OpenJPA, see the Apache OpenJPA 2.0 User’s Guide: Chapter 5
Note the following hints and tips when writing your own OpenJPA code:
·
Persistence.xml: JPA requires the use of a XML file called the
“persistence.xml” that describes how to access the data. The XML file must be
created in the META-INF directory. The META-INF directory containing the
persistence.xml must be located with the source files.
In the following example, the file only requires a few fields.
Figure
2: META-INF/persistence.xml sample code
<persistence xmlns=http://java.sun.com/xml/ns/persistence
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
version="1.0">
<persistence-unit
name="InventorySystem" transaction-type="RESOURCE_LOCAL">
<class>tutorial.InventoryItem</class>
<class>tutorial.InventoryCategory</class>
<properties>
<property
name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
<property
name="openjpa.ConnectionURL" value="jdbc:derby://localhost:1527/StoreSystem"/>
<property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.ClientDriver"/>
</properties>
</persistence-unit>
</persistence>
· Create the Entity Manager. In the provided code, the EntityManager is a property of the InventoryEntityBroker class. The Entity Manager controls the interaction with the database. You must use the Entity Manager to start or access transactions or to send queries.
· DB interface class. In this example, the InventoryEntityBroker class contains all the OpenJPA database interaction code. This is not required but it is a good idea for keeping the functionality componentized. For example, if you want to pull all of the records from the InventoryItem table, the code would look like this:
·
Also in the InventoryEntityBroker is code to add entries the database
tables. Since you did not create a table for InventoryItem in the StoreSystem
database in
·
An important aspect of relational databases is, of course, the
relationships. The basic relationship types are: one to many, many to one, and
many to many. OpenJPA provides annotations to identify the related fields.
Open the source file, InventoryCategory.java in Eclipse and find the following
@OneToMany(targetEntity=tutorial.InventoryItem.class,
cascade=CascadeType.ALL,
mappedBy="category")
public
List<InventoryItem> getItems()
{
return items;
}
...
Now open the source file, InventoryItem.java and find the following code:
@ManyToOne
@JoinColumn(name="CAT_ID", nullable=false)
public InventoryCategory getCategory()
{
return category;
}
...
o The annotation @ManyToOne identifies that:
§ This object has a many-to-one relationship with the InventoryCategory object. Meaning that there many InventoryItems can reference the same InventoryCategory
o The annotation @JoinColumn identifies that:
§ The column in the database table that holds the InventoryCategory reference by the attribute: name="CAT_ID".
Remember that these annotations contribute to the creation of the tables and the relationships. It is important to put as much thought into how these objects relate to each other as you would if you were designing the database tables because you are designing the database tables.
You can see more about the relationship annotations at the Apache OpenJPA site. The documentation is here.
This was a very basic example of how to use OpenJPA with
Geronimo and
Exercises
Using this sample code as a base, try to do some of the following:
· Add additional fields to the InventoryItem Entity
· Create a Customer Entity and establish a one-to-many relationship with the InventoryItems as one customer having purchased many items.*
· Since several customers could have purchased the same items and an item could have been purchased by many customers, use the documentation to create a many-to-many relationship using @ManyToMany*
* To make these changes you may have to delete the existing database tables so that they can recreated with the new relationship fields