Child pages
  • Developing bean managed persistence with JPA
Skip to end of metadata
Go to start of metadata
{scrollbar}

The Java Persistence API is a new programming model under EJB3.0 specification (JSR220) for the management of persistence and object/relational mapping with Java EE and Java SE. With JPA, developers can easily develop java applications that perform operations on relational database management systems using java objects and mapping. In that way, java applications developed using JPA are not only portable across different platforms, but also applications can be easily developed using simple yet powerful programming model provided by JPA. This greatly improves application maintainability against ever changing database world. JPA insulates applications from all the complexity and non-portable boilerplate code involved in database connectivity and operations.

Apache geronimo uses OpenJPA for providing Java Persistence API to Java EE applications deployed in the server. Even though JPA is a part of EJB3.0 spec, it is independent of it. Hence, JPA can be used in JavaSE, web and ejb applications in the same uniform way.

Below tutorial illustrates the use of application managed entity manager object. The EntityManager object is created from EntityManagerFactory. The EntityManagerFactory object is injected by the container when @PersistenceUnit(unitName="<PersistentUnitName>") annotation is used. The persistence context of the entity manager is not propagated along with any transaction that is currently active. If the transaction spans across components, all the entity manager object references that point to same persistence unit will have a different persistence context. Thus, any changes made to the entities through any entity manager reference, are not seen through other entity manager references. The persistence scope of the application managed entity manager is Extended by default. The transaction-type can be either JTA or RESOURCE_LOCAL. If the transaction-type is JTA the EntityManager can join the transaction by calling joinTransaction() method. The transaction-type of RESOURCE_LOCAL is used in when the EntityManager is not interested to join the global transaction. This is typically used in non-JEE environments. In summary, the life cycle of the entity manager and the associated persistence context is not managed the container. It is the application's responsibility to close the EntityManager object explicitly. The persistence context spans beyond transactions by default.

The tutorial creates an enterprise application that has an ejb module and a web module. The ejb module uses Account entity and Person entity. The Account entity has accountNumber, personId and balance attributes. The Person entity has personId, personName and address attributes. The personId in Account entity refers to personId in Person entity. The AccountBean injects EntityManagerFactory from which it creates EntityManager object. It is a stateful session bean which has Account entity object, corresponding Person entity object, EntityManager object and EntityManagerFactory object as state fields. The bean has updateAllValues(String address, String personName, double balance) method that updates Account and Person entity attributes. It has also deposit(double amount) and withdraw(double amount) methods for withdrawing and depositing the amounts to the account. In all the above mentioned methods, the EntityManager object joins the active transaction using joinTransaction() method as the its transaction-type is JTA and bean's transaction is managed by the container. The initialize(integer accountNumber) initializes the bean with Account and Person entity objects corresponding to the accountNumber sent as the parameter. Finally, the EntityManager object is closed in the destroy() method.

The web module allows user to update the Account entity and Person entity attributes and transfer amount from one account to another using AccountBean. The RetrieveAccount.jsp performs update and the TransferAmount.jsp performs transfer of amount in a JTA transaction.

In order to develop, deploy and run the application, the following environment is required.

  • Sun JDK 5.0+ (J2SE 1.5)
  • Eclipse 3.3.1.1 (Eclipse Classic package of Europa distribution), which is platform specific
  • Web Tools Platform (WTP) 2.0.1
  • Data Tools Platform (DTP) 1.5.1
  • Eclipse Modeling Framework (EMF) 2.3.1
  • Graphical Editing Framework (GEF) 3.3.1

The tutorial is divided into the following sections.

  • Setting the Eclipse environment
  • Creating ejb application with entities
  • Creating web application
  • Setting up the database tables and the Datasource.
  • Deploying the (ear) application
  • Running the application

The entire application can be downloaded from this link.

Setting the Eclipse environment

1. Download Apache Geronimo2.1 and install it on the server. Look into the geronimo documentation for
instructions.

2. Install the eclipse IDE and download geronimo eclipse plugin and install it on top of eclipse. Look into the
geronimo eclipse plugin documentation for instructions.

3. Create a runtime environment for Apache Geronimo2.1 in the eclipse. Look into the geronimo eclipse plugin
documentation for instructions to install a runtime for Apache Geronimo2.1.

Creating ejb application with entities

1. Open the eclipse tool and change the perspective to Java EE by clicking on
Windows => Open Perspective => Other. It will open up Open Perspective wizard. Select Java EE from the
list and click OK button.

2. Right click on the Package Explorer and select EJB Project.

3. This will open up the New EJB Project wizard. Provide the values for Project Name, Target Runtime as given in the screen shot below. Click on Next button.

If target runtime is not setup, create a new target runtime pointing to geronimo installation directory. For more information, look at the geronimo documentation that explains setting up eclipse plugin for geronimo and setting up runtime environment. This setup is required to resolve class dependencies during compilation.

4. Select the check boxes as given in the screen shot below and click on the Next button.

5. Select the checkboxes as given in the below screen shot and click on the Next button.

6. Provide the following values in textboxes and click on the Finish button.

7. Right click on the BeanManagedJPA-EJB project and navigate to New => Class option. Provide the
following values in the New Java Class wizard and click on Finish button.

8. Copy the following contents into Account.java.

JAVAsolidAccount.java package sample.jpa; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.PostLoad; import javax.persistence.PostUpdate; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.Table; @Entity @Table(name = "ACCOUNTBME") public class Account implements Serializable { @Id public int accountNumber; public int personId; public double balance; public Account() { } public int getAccountNumber() { return accountNumber; } public void setAccountNumber(int accountNumber) { this.accountNumber = accountNumber; } public int getPersonId() { return personId; } public void setPersonId(int personId) { this.personId = personId; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } }

9. Similarly, as given in the previous step, create Person.java and add the following contents to it.

JAVAsolidPerson.java package sample.jpa; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "PERSONBME") public class Person implements Serializable { @Id public int personId; public String personName; public String address; public Person() { } public int getPersonId() { return personId; } public void setPersonId(int personId) { this.personId = personId; } public String getPersonName() { return personName; } public void setPersonName(String personName) { this.personName = personName; } public String getAddress() { return address; } public void setAddress(String address) { System.out.println("Address="+address); this.address = address; } }

9. Similarly, create AccountInterface.java and copy the following contents.

JAVAsolidAccountInterface.java package sample.jpa; import java.util.Collection; public interface AccountInterface { public void initialize(int accountNumber); public String getPersonName(); public void setPersonName(String personName); public String getAddress(); public void setAddress(String address); public double getBalance(); public void setBalance(double balance); public void updateAllValues(String address, String personName, double balance); public void withdraw(double amount); public void deposit(double amount); }

10. Similarly, create AccountBean.java.java and copy the following contents. Note that several lines have been truncated for display.

JAVAsolidAccountBean.java package sample.jpa; import javax.annotation.PostConstruct; import javax.ejb.Local; import javax.ejb.Remove; import javax.ejb.Stateful; import javax.ejb.TransactionManagement; import javax.ejb.TransactionManagementType; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.PersistenceUnit; @Stateful @TransactionManagement(TransactionManagementType.CONTAINER) @Local(AccountInterface.class) public class AccountBean implements AccountInterface{ @PersistenceUnit(unitName="AccountUnit") private EntityManagerFactory emf; private EntityManager em; Account account; Person person; @PostConstruct public void init(){ em = emf.createEntityManager(); } public void initialize(int accountNumber){ account = em.find(Account.class, accountNumber); if(account == null)throw new IllegalStateException ("Account number ("+accountNumber+") not found"); person = em.find(Person.class, account.getPersonId()); if(person == null)throw new IllegalStateException("Person Id("+account.getPersonId()+") not found. There is a descripancy in the database for account number ("+accountNumber+")"); } public String getPersonName(){ return person.getPersonName(); } public void setPersonName(String personName){ person.setPersonName(personName); } public String getAddress(){ return person.getAddress(); } public void setAddress(String address){ person.setAddress(address); } public void updateAllValues(String address, String personName, double balance){ em.joinTransaction(); setAddress(address); setPersonName(personName); setBalance(balance); } public double getBalance(){ return account.getBalance(); } public void setBalance(double balance){ account.setBalance(balance); } public void withdraw(double amount){ if(amount > getBalance())throw new IllegalStateException ("The amount("+amount+") to be withdrawn is more than the available balance("+getBalance()+")"); em.joinTransaction(); setBalance(getBalance() - amount); } public void deposit(double amount){ em.joinTransaction(); setBalance(getBalance() + amount); } @Remove public void destroy(){ em.close(); } }

11. As outlined above, right click on the META_INF directory of BeanManagedJPA-EJB project and
create persistence.xml. Copy the following contents into persistence.xml.

XMLsolidpersistence.xml <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="AccountUnit" transaction-type="JTA"> <description>ContainerManagedJPA</description> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <jta-data-source>AccountDS</jta-data-source> <class>sample.jpa.Account</class> <class>sample.jpa.Person</class> </persistence-unit> </persistence>

12. Since we are going to use EJB annotations, the META-INF/ejb-jar.xml will not have any declarations. The contents of the META-INF/openejb-jar.xml file should be as below. Otherwise, modify it accordingly.

XMLsolidopenejb-jar.xml <?xml version="1.0" encoding="UTF-8"?> <openejb-jar xmlns="http://openejb.apache.org/xml/ns/openejb-jar-2.2" xmlns:naming="http://geronimo.apache.org/xml/ns/naming-1.2" xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" xmlns:sys="http://geronimo.apache.org/xml/ns/deployment-1.2"> <sys:environment> <sys:moduleId> <sys:groupId>BeanManagedJPA</sys:groupId> <sys:artifactId>EJB</sys:artifactId> <sys:version>1.0</sys:version> <sys:type>car</sys:type> </sys:moduleId> <dependencies> <dependency> <groupId>console.dbpool</groupId> <artifactId>AccountDS</artifactId> </dependency> </dependencies> </sys:environment> <enterprise-beans/> </openejb-jar>

13. Finally the project BeanManagedJPA-EJB should like as below.

Creating web application

1. Right click on the Project Explorer and select New => Project. This will popup New Project wizard.
Select Dynamic Web Project under option Web. Click on the Next button.

2. Provide the values as given in the screen shot below on the New Dynamic Web Project wizard. Please note that Add project to an EAR checkbox is check to add this web project to BeanManagedJPA-EAR created during the creation of BeanManagedJPA-EJB project.

3. In the next screen, select the Version values as given in the below figure and click on the Next button.

4. Check on the Generate Deployment Descriptor checkbox and click on the Next button. On the next screen, configure the deployment plan as follows. After this, click on the Finish button to complete creating web project

5. Right click on the WebContent folder of the web project and navigate to New => HTML to create the index.html file as given in the screen shot. Click on the Next button and on the next screen click on the Finish button. The contents of the index.html is provided below the screen shot.

ActionScriptsolidindex.html <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Bean Managed JPA</title> </head> <body> <font size=4> <a href="/BeanManagedJPA-WEB/ViewAccount.html"> View Account Details </a> </font><br/> <font size=4> <a href="/BeanManagedJPA-WEB/TransferAmount.jsp"> Transfer Amount </a> </font> </body> </html>

6. Right click on the WebContent folder of the web project and navigate to New => HTML to create the ViewAccount.html file as given in the screen shot. Click on the Next button and on the next screen click on the Finish button. The content of the ViewAccount.html is provided below the screen shot.

ActionScriptsolidViewAccount.html <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Bean Managed JPA</title> </head> <body> <form name="input" action="/BeanManagedJPA-WEB/RetrieveAccount.jsp"method="get"> <table border="0"> <tr> <td align="right"><font color="black" size="4">Account Number</font></td> <td align="left"><input type="text" name="accountNumber"></td> </tr> <tr> <td align="right"><input type="submit" value="Submit"></td> <td></td> </tr> </table> </form> </body> </html>

9. Similarly, as illustrated in the previous steps, create RetrieveAccount.jsp. The contents of the of the jsp is as follows.

ActionScriptsolidRetrieveAccount.jsp <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ page import="sample.jpa.AccountInterface"%> <%@ page import="javax.naming.Context"%> <%@ page import="javax.naming.InitialContext"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Retrieve and Update Account</title> </head> <body> <% String update = request.getParameter("Update"); String cancel = request.getParameter("Cancel"); System.out.println("update value="+update); System.out.println("cancel value="+cancel); String submitValue = null; if(update != null) submitValue=update; if(cancel != null) submitValue=cancel; System.out.println("1 Submit value="+submitValue); if(submitValue != null) { System.out.println("2 Submit value="+submitValue); if(submitValue.equals("Cancel")){ System.out.println("3 Submit value="+submitValue); response.sendRedirect("/BeanManagedJPA-WEB/"); } else if(submitValue.equals("Update")){ System.out.println("4 Submit value="+submitValue); System.out.println("Updating the Account Entity Started"); Context ctx = new InitialContext(); System.out.println("Instantiating beans..."); AccountInterface accountBean = (AccountInterface) ctx.lookup("java:comp/env/ejb/AccountInterface"); int accountNumber = Integer.parseInt (request.getParameter("accountNumber")); accountBean.initialize(accountNumber); accountBean.updateAllValues(request.getParameter("address"), request.getParameter("personName"), Double.parseDouble (request.getParameter("balance"))); System.out.println("Updating the Account Entity Ended"); response.sendRedirect("/BeanManagedJPA-WEB/RetrieveAccount.jsp? accountNumber="+accountNumber); } } else{ Context ctx = new InitialContext(); System.out.println("Instantiating beans..."); AccountInterface accountBean = (AccountInterface)ctx.lookup("java:comp/env/ejb/AccountInterface"); int accountNumber = Integer.parseInt(request.getParameter("accountNumber")); accountBean.initialize(accountNumber); %> <form name="input" action="/BeanManagedJPA-WEB/RetrieveAccount.jsp"> <table border="0"> <tr> <td align="right"><font color="black" size="4"> Account Number :</font></td> <td align="left"><font color="red" size="4"><%=accountNumber%></font> <input type="hidden" name="accountNumber" value="<%=accountNumber%>"> </td> </tr> <tr> <td align="right"><font color="black" size="4"> Person Name : </font></td> <td align="left"><font color="red" size="4"> <%=accountBean.getPersonName()%> </font></td> </tr> <tr> <td align="right"><font color="black" size="4"> Update Person Name : </font></td> <td align="left"><input type="text" name="personName"></td> </tr> <tr> <td align="right"><font color="black" size="4"> Address : </font></td> <td align="left"><font color="red" size="4"><%=accountBean.getAddress()%> </font></td> </tr> <tr> <td align="right"><font color="black" size="4"> Update Address : </font></td> <td align="left"><input type="text" name="address"></td> </tr> <tr> <td align="right"><font color="black" size="4"> Balance : </font></td> <td align="left"><font color="red" size="4"><%=accountBean.getBalance()%> </font></td> </tr> <tr> <td align="right"><font color="black" size="4"> Update Balance : </font></td> <td align="left"><input type="text" name="balance"></td> </tr> <tr> <td align="right"><input type="submit" name="Update" value="Update"></td> <td align="left"><input type="submit" name="Cancel" value="Cancel"></td> </tr> </table> </form> <%} %> </body> </html>

10. Similarly, as illustrated in the previous steps, create TransferAmount.jsp. The contents of the jsp is as follows.

ActionScriptsolidTransferAmount.jsp <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ page import="sample.jpa.AccountInterface"%> <%@ page import="javax.naming.Context"%> <%@ page import="javax.naming.InitialContext"%> <%@ page import="javax.transaction.UserTransaction"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Transfer Amount</title> </head> <body> <% String submitValue = request.getParameter("Transfer"); if(submitValue!=null){ int debitAccount = Integer.parseInt (request.getParameter("accountNumber1")); int creditAccount = Integer.parseInt (request.getParameter("accountNumber2")); double amount = Double.parseDouble (request.getParameter("amount")); Context ctx = new InitialContext(); AccountInterface debitAccountBean = (AccountInterface)ctx.lookup("java:comp/env/ejb/AccountInterface"); debitAccountBean.initialize(debitAccount); AccountInterface creditAccountBean = (AccountInterface)ctx.lookup("java:comp/env/ejb/AccountInterface"); creditAccountBean.initialize(creditAccount); UserTransaction ut = (UserTransaction)ctx.lookup("java:comp/UserTransaction"); ut.begin(); debitAccountBean.withdraw(amount); creditAccountBean.deposit(amount); ut.commit(); response.sendRedirect("/BeanManagedJPA-WEB/"); } else{ %> <form name="input" action="/BeanManagedJPA-WEB/TransferAmount.jsp" method="get"> <table border="0"> <tr> <td align="right"><font color="black" size="4"> Debit Account Number :</font></td> <td align="left"><input type="text" name="accountNumber1"> </td> </tr> <tr> <td align="right"><font color="black" size="4"> Credit Account Number:</font></td> <td align="left"><input type="text" name="accountNumber2"></td> </tr> <tr> <td align="right"><font color="black" size="4"> Amount to be Transfered :</font></td> <td align="left"><input type="text" name="amount"></td> </tr> <tr> <td align="right"><input type="submit" name="Transfer" value="Transfer"></td> <td></td> </tr> </table> </form> <%} %> </body> </html>

11. Right click on the BeanManagedJPA-WEB project and click on Properties to open Properties for BeanManagedJPA-WEB wizard. Click on the Java Build Path and Projects tab. Click on the Add button and add BeanManagedJPA-EJB project. Finally, click on the OK button on Properties for BeanManagedJPA-WEB wizard. This is required because, BeanManagedJPA-WEB projects looks up AccountInterface ejb in the BeanManagedJPA-EJB project. To resolve the dependency during compilation, the EJB project has to be added to the build path of the WEB project.

Setting up the database tables and the Datasource

1. Start the geronimo server and open the admin console on a browser window with the url
http://localhost:8080/console.

2. Click on the Embedded DB => DB Manager on the Console Navigation portlet.

3. On the Run SQL portlet on the right side, enter AccountDB in the Create DB textbox and click on the
Create button.

4. The above step will create AccountDB database. On the same screen, enter the below SQL command on the SQL Command/s textarea and select AccountDB in the Use DB combo box and click on the Run SQL button. This will create ACCOUNTCME table in the AccountDB database.

SQLsolid create table ACCOUNTBME (ACCOUNTNUMBER integer, PERSONID integer, balance decimal(15,2));

5. Similarly, enter the below SQL command on the SQL Command/s textarea and select AccountDB in the Use DB combo box and click on the Run SQL button. This will create PERSONBME table in the AccountDB database.

SQLsolid create table PERSONBME (PERSONID integer, PERSONNAME varchar(255), ADDRESS varchar(255));

6. Insert the two rows using the below SQL command.

SQLsolid insert into PERSONBME values (1, 'Shane Gibson', 'XXXX'); insert into PERSONBME values (2, 'Rameez Raza', 'YYYY'); insert into ACCOUNTBME values (10,1,6500); insert into ACCOUNTBME values (11,2,9000);

After inserting the rows, table will look like the below screen shot.

7. We need to deploy datasource over AccountDB database for JPA. This datasource will be used by JPA to connect to database and perform DML operations. Admin console can be used to deploy a datasource over AccountDB. Click on the services => Database Pools in the Console => Navigation portlet. This will display the list of database pools currently running in the server.

8. Click on the Using the Geronimo database pool wizard link. This will open up the Database pools portlet as follows. Provide the value for Name of the Database pool as AccountDS and select Derby embedded as below and click on the Next button.

9. On the next screen, select the JAR file listed in the Driver JAR select box and provide AccountDB as the value for Database Name and click on the Deploy button at the bottom. This will deploy the data source and display the list of datasources currently deployed on the server.

10. In the eclipse, open the openejb-jar.xml and provide the dependency to the AccountDS. Finally, the openejb-jar.xml should be as below. This configuration is already done in the step 12 of Creating ejb application with entities above.

Deploying the (ear) application

1. Deploy the EAR file as follows
#000000solid C:\Geronimo-2.1\bin>deploy.bat --user system --password manager deploy c:\temp\BeanManagedJPA-EAR.ear Using GERONIMO_BASE: C:\Geronimo-2.1 Using GERONIMO_HOME: C:\Geronimo-2.1 Using GERONIMO_TMPDIR: var\temp Using JRE_HOME: C:\SDK-May-31-2007\jre Deployed default/BeanManagedJPA-EAR/1.0/car `-> BeanManagedJPA-WEB.war @ /BeanManagedJPA-WEB `-> BeanManagedJPA-EJB.jar

Running the application

1. Open a browser window and hit the URL as http://localhost:8080/BeanManagedJPA-WEB/. This brings upthe screen shot below. Click on the View Account Details link.

2. On this page, enter 10 in the Account Number text box as below and click on the button

3. This will bring up the screen shot below. You can update the Person Name, Address and Balance values.

4. Enter the values given in the screen shot below and click on the Update button.

5. Once the Update button is pressed, the below screen shot is displayed with the updated values. Click on the Cancel button to go back to the main page.

6. Click on the Transfer Amount link on the main page. This will bring up the page as given in the screen shot below. Enter the values for Debit Account Number, Credit Account Number and Amount to be Transferred as given in the screen shot and click on the Transfer button. This will transfer the specified amount from debit account to the credit account. You can verify this either in the database or use the View Account Details link shown earlier.

  • No labels