Developing JPA Applications with WebSphere Application Server Community Edition

Data persistence made easy using JPA

The Java™ Persistent API (JPA) makes it easier than ever to design and develop the persistent part of JEE applications. This tutorial walks you through all the nuances of this new API, developing a sample application using Eclipse and WebSphere® Application Server Community Edition. Both WebSphere Application Server Community Edition and Eclipse are available for download at no charge, so you can get started in just a few minutes.

Share:

Phani Madgula (mabalaji@in.ibm.com), Software Developer, IBM

author imagePhani Madgula works on WebSphere Process Server Support at the India Software Labs (ISL). He has 6 years experience at IBM. He worked in various product teams, including WebSphere Application Server Community Edition, WebSphere Business Integration Adapters, and DB2. He has experience in developing JEE applications, product support, and database administration. He is an Oracle9i certified professional.



30 July 2008

Introduction

JPA is the Java API for the management of persistence and object/relational mapping. It is used in both Java EE 5 environments as well as in standalone Java SE environments. It provides an object/relational mapping facility using the Java domain model to manage relational databases. It enables a POJO-based programming model using Java annotations or XML file configurations.

JPA provides both a standard mapping definition (through annotations or XML) and a standard runtime API and object-level query language (JPQL). JPA is part of the EJB specification and Java EE 5 platform, but can be used in Java SE environments as well. The persistence API and the query language are supported under Enterprise JavaBeans 3.0. The JPA specification is being worked out as part of JSR-220 under the Java Community Process Program.

JPA significantly reduces the programming effort required to develop the persistence part of an application, because it allows a POJO based programming model with Java objects, and separates complex boiler-plate code from the application logic. The Java applications that connect to RDBMS data stores through JDBC™ APIs required you to develop a great deal of code for connection management, transaction management, queries, and the data retrieval through result sets. Usually, all this code is intertwined with application logic, making it cumbersome for application maintenance. With JPA, all this boiler-plate code is delegated to the JPA provider through annotations or XML files, leaving a clean application logic. JPA provides:

  • Standard mapping definition (through annotations or XML)
  • Standard runtime API
  • Object-level query language (JPQL)

WebSphere Application Server, Community Edition v2.1 is a lightweight application server that is based on the Apache Geronimo v2.1 release. Henceforth, the WebSphere Application Server, Community Edition v2.1 is called simply Community Edition in the tutorial. Community Edition also includes many other defect fixes, and receives world-class support from IBM. You can download the binary images of the server for no charge. It is a fully certified server for Java EE 5 Apache Geronimo v2.1, hence Community Edition, uses OpenJPA for its JPA implementation.

OpenJPA is the Java EE persistence project of the Apache Software Foundation. It is an open source implementation of the persistence part of Enterprise Java Beans 3.0 specification. It provides a feature-rich implementation of JPA that can be used as a standalone POJO persistence layer, or integrated into any EJB 3.0 compliant container. Its many custom configurations mean you can use it in many lightweight frameworks with ease.

In this tutorial

This tutorial shows you how to use JPA in Java EE 5 applications targeted to run on Community Edition. We illustrate various aspects of JPA as we go through the development of a Web application. We use the Eclipse integrated development environment (IDE) with the Community Edition plug-in for Eclipse (also called the Web Tools Platform (WTP) server adapter), to develop, deploy and run the application. This tutorial is for developers who want to quickly learn how use JPA as the persistence layer for their applications. The tutorial includes the following sections:

Prerequisites

You should know database concepts and should be fairly skilled in Java programming. Understanding Java EE 5 concepts and annotations will help you with the context of the tutorial. You should have experience using an IDE like Eclipse. Since we will manually modify the XML configuration files (we do some bare-handed programming!!), knowledge of how deployment plans are written for an application server is indispensable.

System Requirements

To develop, deploy and run the application, the following environment is required:

  • IBM Java SDK v1.5.0 SR7 or above
  • Eclipse v3.3.1 with WTP v2.0.1
  • WTP server adapter for Community Edition v2.1
  • Community Edition v2.1
  • DB2 Express v9.5

We will use two databases; the SAMPLE database running in DB2-Express v9.5 and the ACCOUNTDB running in the Derby database embedded in Community Edition. We illustrate local transactions with JPA using the SAMPLE database, but we use both the databases for illustrating JTA transactions.

Duration

2 hours


Creating JPA projects in the Eclipse IDE, and generating persistent classes

In this section, we will perform following tasks.

  • Install Community Edition v2.1
  • Set up the Eclipse development environment
  • Set up the Derby database
  • Set up the DB2 Express database
  • Set up up the Data Sources in the Eclipse IDE
  • Create the Db2AccountUnit JPA project
  • Create the DerbyAccountUnit JPA project

Install Community Edition v2.1

The Community Edition v2.1 installer is available for download from developerWorks (see Resources). Download the server into your machine and follow the instructions in the Community Edition v2.1 documentation. In this tutorial, we refer to the Community Edition installation directory as <wasce_home>. The Community Edition installer ships with the IBM Java SDK1.5.0. The JDK is used by the installer as well as the server runtime. For more information about the recommended and compatible platforms, see the support site.

Set up the Eclipse development environment

Visit the Community Edition v2.1 documentation and follow the Development link on the left-hand side to view sections on common development tasks. Set up the Eclipse development environment for Community Edition in your local machine by following the instructions given in the Using Eclipse section. You can use the Eclipse update manager to download and install the Community Edition Eclipse plug-in; or download deployable.zip and overlay the zip file contents on to the Eclipse directory.

Go through the other sections of the documentation to learn how to create a Community Edition server instance in Eclipse, deploy Java EE5 assets on to the server, etc. Create a Community Edition server instance in Eclipse pointing to the server installed at the <wasce_home> directory. At the end of this task, you should have the Community Edition server instance created in Eclipse, as Figure 1 shows:.

Figure 1. Community Edition server in Eclipse
Screen shot showing the Community Edition server in Eclipse

Set up the Derby database

In this section we create the ACCOUNTDB database in Derby. We also create the DERBYACCOUNT table with some sample rows for our application. We will use the Community Edition Web administration console to perform this task.

  1. Open a command window and submit this command to start the server: <wasce_home>/bin/startup.[bat|sh].
  2. Open a browser window and enter this url to open the administration console: http://localhost:8080/console.
  3. Enter system for the user name and manager as the password to login into the Web console.
  4. On the Console Navigation portlet, select Embedded DB => DB Manager to open the DB Viewer and Run SQL portlets.
  5. In the Create DB field enter AccountDB and click the Create button, as Figure 2 shows. This step creates the AccountDB database. The location of the database files is <wasce_home>/var/derby/AccountDB.
    Figure 2. Creating a database
    Screen shot showing how to create a database
  6. In the Use DB field, select the AccountDB database and enter the following SQL statements in the SQL Command field:
    create table DERBYACCOUNT (ACCNO integer, OWNER varchar(100), DATE_OPEN date, 
    ACCOUNT_TYPE varchar(20), BALANCE decimal(15,2));
  7. Click the Run SQL button to create the DERBYACCOUNT table.
  8. In the Use DB field, select the AccountDB database and enter the following SQL statements in the SQL Command field:
    insert into DERBYACCOUNT values (1, 'Jane', '10/10/2008', 'SAVINGS', 10000);
    insert into DERBYACCOUNT values (2, 'Monica', '10/10/2008', ‘CHECKING’, 20000);
  9. Click the Run SQL button to insert the two rows into the DERBYACCOUNT table.
  10. The final table and the inserted rows should look like Figure 3:
    Figure 3. Table with inserted rows
    Screen shot of table with inserted rows

Set up the DB2 Express database

In this section we create the DB2ACCOUNT table in the SAMPLE database running in DB2. You can either use the DB2 control-center or DB2 command prompt to perform this task. Ensure that you’ve created the DB2 user account DB2ADMIN and granted it sufficient privileges to access the database.

  1. Install DB2 Express v9.5 on your machine. By default, the installation process creates the SAMPLE database.
  2. Create the DB2ACCOUNT table with the column definitions shown in Listing 1, using either the control-center or DB2 command prompt.

    Listing 1: D2CACCOUNT table column definitions

    CREATE TABLE "DB2ADMIN"."DB2ACCOUNT" (
    "ACCNO" INTEGER NOT NULL ,  "OWNER" VARCHAR(100) NOT NULL ,  
    "DATE_OPEN" DATE NOT NULL ,  "ACCOUNT_TYPE" VARCHAR(20) NOT NULL ,
     "BALANCE" DECIMAL(15,2) NOT NULL ) ALTER TABLE "DB2ADMIN".
    "DB2ACCOUNT" ADD CONSTRAINT "DB2ACCOUNT_PRIMARYKEY"
    PRIMARY KEY ("ACCNO");

    We will be developing a Web application to perform data manipulation operations (DML) operations on the above table using JPA.
  3. The final table should look like Figure 4:
    Figure 4.Final table
    Screen shot showing the final table

Set up the data sources in the Eclipse IDE

In this section we create the WASCEDerby and DB2 data sources in Eclipse. The WASCEDerby data source connects to the ACCOUNTDB database created in the embedded Derby instance. The DB2 data source connects to the SAMPLE database in the DB2 database. You can associate these data sources to JPA projects to generate persistent classes for the underlying tables.

  1. Shutdown the Community Edition server with this command:.
    <wasce_home>/bin>shutdown.[bat|sh] –user system –password manager
  2. Click the Data Source Explorer tab in Eclipse, right-click Databases and click New, as Figure 5 shows:
    Figure 5. Creating a new data source in Eclipse
    Screen shot showing how to create a new data source
  3. On the New Connection Profile wizard, select Derby Embedded Database and click the Next button, as Figure 6 shows:
    Figure 6. New Connection Profile wizart
    Screen shot of selecting Derby Embedded Database
  4. On the Derby Embedded Database wizard, provide WASCEDerby for the Name and any description for Description (optional), as shown in Figure 7, and click the Next button.
    Figure 7. Derby Embedded Database wizard
    Screen shot of values for Derby Embedded Database wizard
  5. On the Specify a Driver and Connection Details wizard, click the button to the right of the Select a driver from the drop-down box to configure the driver (Figure 8):
    Figure 8. Driver and Connection Details wizard
    Screen shot of values for Driver and Connection Details wizard
  6. In the Driver Definitions wizard, select 10.2 and click the Add button.
    Figure 9. Driver Definitions wizard
    Screen shot of values for Driver Definition wizard
  7. In the New Driver Definition wizard; select Derby Embedded JDBC Driver and check the Edit New Driver Definition immediately box. Click the OK button.
    Figure 10. New Driver Definition wizard
    Screen shot of values for New Driver Definition wizard
  8. In the Edit Driver Details wizard, perform the following steps:
    • Remove any existing JAR files from the Driver File(s) box and add this JAR file: <wasce_home>repository/org/apache/derby/derby/10.2.2.0/derby-10.2.2.0.jar.
    • Change the Connection URL, Database Name, and User ID in the Properties box as follows (also shown in Figure 11). Note that C:\ibm\wasce-server-2.1.0.0 is the <wasce_home> on my local system. Click OK.
    Connection URL jdbc:derby:C:\ibm\wasce-server-2.1.0.0\var\derby\AccountDB
    Database Name AccountDB
    User ID APP

    Figure 11. Edit Driver Details wizard
    Screen shot of values for Edit Driver Details wizard
  9. Keep closing all the opened wizards by clicking OK, until the Specify a Driver and Connection Details wizard comes to the front. Click the Next button, and on the next screen click the Finish button, as Figure 12 shows:
    Figure 12. Specify a Driver and Connection Details wizard
    Screen shot of values for Specify a Driver and Connection Details wizard
  10. This will create the WASCEDerby data source. Similarly, we need to follow the same steps to create the DB2 sata source in Eclipse. When you create the data source for DB2, make the database name SAMPLE and select the following driver libraries (<db2_home> is the directory where DB2 v9.5 Express is installed):
    • <db2_home>/java/db2jcc.jar
    • <db2_home>/java/db2jcc_license_cu.jar
  11. Finally, enter the following DB2 data source connection details (also shown in Figure 13):
    Name DB2
    Description DB2
    Auto connect false
    Driver name IBM DB2 Universal
    User name DB2ADMIN
    URL jdbc:db2://localhost:50000/SAMPLE

    Figure 13. DB2 data source connection details
    Screen shot of DB2 data source connection details
  12. Right-click each of the created data sources, and click Connect to connect to SAMPLE and ACCOUNTDB databases (Figure 14):

    Important: When you connect to the ACCOUNTDB database from Eclipse using the embedded driver, you must shut down the Community Edition server. If the server is running and connected to this database using the embedded driver, Eclipse throws an error if you try to connect to the same database.

    Figure 14. Connecting to data sources
    Screen shot of connecting to datas sources

Create the Db2AccountUnit JPA project

A JPA project creates a persistence unit. A persistence unit is set of manageable persistent classes along with the deployment descriptor. The deployment descriptor file is persistence.xml. Eclipse lets you associate a JPA project to a data source and generate persistent entity classes from the underlying tables. It provides various options to configure persistence units through wizards.

In this section, we create the Db2AccountUnit JPA project and associate it with the DB2 data source that we created earlier. We will also generate a persistent class for the DB2ACCOUNT table.

  1. Right-click on the Project Explorer and navigate to New => Other (Figure 15):
    Figure 15. Navigating to New - Other
    Screen shot of menu selection
  2. On the next wizard, select JPA => JPAProject and click the Next button
    Figure 16. Selecting JPA project
    Screen shot of selecting JPA project
  3. In the JPA Project wizard, enter the values for various fields as in the following table (also shown in Figure 17). Click the Next button. We are creating the DB2AccountUnit JPA project that connects to the SAMPLE database running in DB2. The JPA project will be able generate Java persistent classes for tables created in the SAMPLE database.
    Project name DB2AccountUnit
    Target Runtime IBM Community Edition v2.1
    Configurations Default Configuration for IBM Community Edition v2.1

    Figure 17. JPA wizard
    Screen shot of values for JPA wizard
  4. On the Project Facets wizard, check all the Project Facets and click the Next button (Figure 18):
    Figure 18. Project Facets wizard
    Screen shot of values for Project Facets wizard
  5. On the Geronimo Deployment Plan wizard, provide the values in the following table (also shown in Figure 19) and click the Next button.
    Group Id web
    Artifact Id accountJPA-DB2
    Version 1.0
    Artifact Type car

    Figure 19. Geronimo Deployment Plan wizard
    Screen shot of values for Geronimo Deployment Plan wizard
  6. On the JPA Facet wizard, select the values in the following table (also shown in figure 20) and click the Finish button. This step creates the DB2AccountUnit JPA project. It also creates persistence.xml in the META-INF folder. We can edit this file to configure the persistence unit later.
    Platform Generic
    Connection DB2
    JPA Implementation Use implementation provided by server runtime
    Persistent class management Discover annotated classes automatically
    Create orm.xmlUncheck the checkbox
    Figure 20. JPA Facet wizard wizard
    Screen shot of values for JPA Facet wizard wizard
  7. Right-click the DB2AccountUnit project and navigate to JPA Tools => Generate Entities, as Figure 21 shows:
    Figure 21. Opening the Generate Entitites wizard
    Screen shot showing how to open the Generate Entitites wizard
  8. On the Generate Entities wizard, provide Database Settings values as DB2 and DB2ADMIN and click the Next Button (Figure 22):
    Figure 22. Generate Entitites wizard
    Screen shot showing Generate Entitites wizard
  9. On the Generate Entities from Tables wizard, select the DB2ACCOUNT table, and enter sample.jpa for the package, as Figure 23 shows. Click the Finish button. This step generates the sample.jpa.Db2account class in the DB2AccountUnit project. This class is fully annotated with JPA annotations and corresponds to the DB2ACCOUNT table in the SAMPLE database.
    Figure 23. Generate Entities from Tables wizard
    Screen shot showing Generate Entities from Tables wizard

    Figure 24 shows the Db2account.java source file:

    Figure 24. Db2account.java
    Screen shot showing Db2account.java

Create the DerbyAccountUnit JPA project

In this section we create the DerbyAccountUnit JPA project and associate it with the WASCEDerby data source that we created earlier. We will also generate a persistent class for the DERBYACCOUNT table. We’ll follow the steps from the previous section to create the project:

  1. Right click on the Project Explorer and navigate to New => Other.
    Figure 25. Navigating to the JPA project
    Screen shot showing how to navigate to the JPA project
  1. On the next wizard, select JPA => JPA Project and click on the Next button.
    Figure 26. Opening the JPA project wizard
    Screen shot showing how to open JPA project wizard
  2. This will open the JPA Project wizard. Provide the values as given the following table (shown in Figure 27) and click on the Next button. We are creating DerbyAccountUnit JPA project that connects to AccountDB database running in embedded Derby database. The JPA project will be able generate Java persistent classes for tables created in the AccountDB database.
    Project name Derby Account Unit
    Target Runtime IBM WASCE v2.1
    Configurations Default Configuration for IBM WASCE v2.1

    Figure 27. JPA project wizard
    Screen shot showing the JPA project wizard
  3. On the Project Facets wizard, check all the Project Facets and click the Next button.
    Figure 28. Project Facets wizard
    Screen shot showing the Project Facets wizard
  4. On the Geronimo Deployment Plan wizard, provide the values given in the following table (also shown in Figure 29) and click the Next button.
    Group Id web
    Artifact Id accountJPA-Derby
    Version 1.0
    Artifact Type car

    Figure 29. Geronimo Deployment Plan wizard
    Screen shot showing the Geronimo Deployment Plan wizard
  5. On the JPA Facet wizard, select the values shown in the following table and Figure 30, and click the Finish button. This step creates the DerbyAccountUnit JPA project. It also creates a persistence.xml file in the META-INF folder. We can edit this file to configure the persistence unit later.
    Platform Generic
    Connection WASCEDerby
    JPA Implementation Use implementation provided by server runtime
    Persistent class management Discover annotated classes automatically
    Create orm.xmlUncheck the checkbox

    Figure 30. JPA Facet wizard
    Screen shot showing the JPA Facet wizard
  6. Right-click the DerbyAccountUnit project and navigate to JPA Tools => Generate Entities.
    Figure 31. Opening the Generate Entities wizard
    Screen shot showing how to open the Generate Entities wizard
  7. On the Generate Entities wizard, provide the Database Settings values of WASCEDerby and APP, and click the Next button.
    Figure 32. Generate Entities wizard
    Screen shot showing the Generate Entities wizard
  8. On the Generate Entities from Tables wizard, select the DERBYACCOUNT table, provide sample.jpa for the package, and click the Finish button. This step generates the sample.jpa.Derbyaccount class in the DerbyAccountUnit project. This class is fully annotated with JPA annotations, and corresponds to the DERBYACCOUNT table in the AccountDB database.
    Figure 33. Generate Entities from Tables wizard
    Screen shot showing the Generate Entities from Tables wizard

    Figure 34 shows the Derbyaccount.java source file:

    Figure 34. Derbyaccount.java
    Screen shot showing Derbyaccount.java
  9. The JPA projects DB2AccountUnit and DerbyAccountUnit are independent persistence units. Youc an export them as JAR files and embed them into any JEE modules (WAR, EJB, EAR). You can configure each persistence unit independently via the corresponding persistence.xml file.

Configuring persistence units with persistence.xml

In this section we perform the following tasks:

  • Explore persistence contexts, entity managers and entity manager factories
  • Configure the DB2AccountUnit persistence unit
  • Deploy the DB2Datasource database connection pool in Community Edition
  • Configure the DerbyAccountUnit persistence unit

Explore persistence contexts, entity managers and entity manager factories

The persistence.xml file describes persistence units. It is the deployment descriptor file for persistence when using the JPA. You use it to declare:

  • Managed persistence classes
    The managed classes are, for example, those which are annotated using @Entity, @Embeddable or @MappedSuperclass.
  • Object/relation mapping
    JPA provides several mechanisms to map the java classes to tables in a relational database.
  • Configuration information
    For entity managers and entity manager factory classes.

Entity managers do their work in a persistence context. A persistence context is a set of managed entity instances where, for any persistent entity identity, there is a unique entity instance. The entity identity is managed using a primary key.

There are two types of entity managers, depending on how you manage the persistence context: container-managed entity managers and application-managed entity managers. The container-managed entity managers are those whose persistence context is managed by the container. You get a container-managed entity manager by using the @PersistenceContext annotation. This annotation causes the container to inject an entity manager object into the reference. It propogates the persistence context of the entity manager, 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 the same persistence context throughout the transaction. Thus, any changes made to the entities through any entity manager reference are seen through other entity manager references.

By default, the persistence scope of the container-managed entity manager is transaction. The transaction-type is always JTA. That is, the entity manager object is always registered with the transaction that is active. In summary, the container automatically manages the life cycle of the entity manager and the associated persistence context. If you invoke the entity manager object outside of the transaction scope, the container throws an error.

In an application-managed persistence context, the entity manager factory creates the entity manager object. The container injects the entity manager factory object when you use the @PersistenceUnit(unitName="<PersistentUnitName>") annotation. The persistence context of the entity manager is not propagated along with the 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.

By default, the persistence scope of the application-managed entity manager is Extended. That is, by default the persistence context spans beyond transaction boundaries. The transaction-type can be either JTA or RESOURCE_LOCAL. If the transaction-type is JTA, the entity manager can join the transaction by calling the joinTransaction() method. If the entity manager is not interested in joining the global transaction, it uses the transaction-type of RESOURCE_LOCAL. This type is typically used in non-JEE environments. In summary, the container does not manage the life cycle of the entity manager and the associated persistence context. It is the application's responsibility to explicitly close the entity manager.

Configure the DB2AccountUnit persistence unit

In this section, we configure DB2AccountUnit and the persistence unit for an entity manager connection factory, entity manager and transactions.

Open the persistence.xml file in DB2AccountUnit/src/META-INF folder and add the code in Listing 2 to the <persistent-unit> element:

Listing 2. persistence.xml changes
<persistent-unit name=”DB2AccountUnit” transaction-type=”RESOURCE_LOCAL”>
   <description>DB2 Account Management</description>
   <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
   <jta-data-source>DB2Datasource</jta-data-source>
<persistent-unit>

OpenJPA implementation of JPA: org.apache.openjpa.persistence.PersistenceProviderImpl is the JPA provider implementation class from OpenJPA. The provider element in persistence.xml specifies the name of the persistence provider's javax.persistence.spi.PersistenceProvider class. You must specify the provider element if the application depends upon the usage of a particular persistence provider. The provider class supplies entity manager objects for this persistence unit.

We configured the DB2AccountUnit persistence unit to use the DB2Datasource database connection pool deployed on the server. The procedure to deploy the connection pool is explained in the next section. It is configured to perform local transactions. We use an entity manager factory to create entity managers for DB2AccountUnit. Therefore, the entity managers are application managed, with a persistent scope of EXTENDED by default. It is the application’s responsibility to close the entity managers when not required. We will illustrate this aspect in the Web application. We use these entity managers to perform insert/update operations on the DB2ACCOUNT table.

Deploy the DB2Datasource database connection pool

  1. Start the server and open the Web administrative console in a browser window (http://localhost:8080/console.
  2. Select Console Navigation => Services => Database Pools to open the Database Pools portlet. This portlet lists all the deployed database pools. Click the Using the Geronimo database pool link, as Figure 35 shows:
    Figure 35. Database Pools portlet
    Screen shot showing Database Pools portlet
  3. On the next screen, for Name of Database Pool, enter DB2Datasource and select DB2 for the Database Type (Figure 36). Click the Next button.
    Figure 36. Specifying the Database Pool
    Screen shot showing how to specify the Database Pool
  4. Select the Driver JAR files as shown in the following table (also shown in Figure 37):
    Database Name SAMPLE
    User Name DB2ADMIN
    Server Name localhost
    Password<password>

    Figure 37. Driver JAR files
    Screen shot showing Driver JAR files to select
  5. Click the Deploy button to deploy the DB2Datasource database pool on the server.

Configure the DerbyAccountUnit persistence unit

Open the persistence.xml file in DerbyAccountUnit/src/META-INF folder and add the code from Listing 3:

Listing 3: DerbyAccountUnit persistence.xml changes
<persistence-unit name="DerbyAccountUnit" transaction-type="JTA">
   <description>Derby Account Management</description>
   <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
   <properties>
      <property name="openjpa.ConnectionURL" value="jdbc:derby:AccountDB" />
      <property name="openjpa.ConnectionDriverName"  
            value="org.apache.derby.jdbc.EmbeddedDriver" />
      <property name="ConnectionUserName" value="app" />
      <property name="openjpa.jdbc.SynchronizeMappings" value="false" />
   </properties>
</persistence-unit>

We configured the DerbyAccountUnit persistence unit to use the connection properties from persistence.xml to create entity managers. OpenJPA defines many configuration properties. Most of these properties are provided for advanced users who wish to customize OpenJPA's behavior. We use @PersistenceContext annotation in the Web application to inject the entity manager. Therefore, it is a container-managed entity manager whose life cycle is managed by the container. The scope of the persistence context is transaction. The entity manager participates in the global transaction to transfer an amount from DB2ACCOUNT table to DERBYACCOUNT table.


Packaging persistence units in the Web application

In this section, you will perform the following tasks:

  • Create the AccountManagementWEB Web application and package the JPA projects with it.
  • Develop JSPs and servlets.
  • Explore various components of the Web application.

Create the AccountManagementWEB Web application and package the JPA projects

In this section, we create the AccountManagementWEB Web application. We will configure the Web application to package the DB2AccountUnit and DerbyAccountUnit persistence units.

  1. Right-click the Project Explorer and navigate to New => Other, as Figure 38 shows:
    Figure 38. Navigating to Dynamic Web Project
    Screen shot showing how to navigate to Dynamic Web Project
  2. On the next wizard, select Dynamic Web Project and click the Next button.
    Figure 39. Opening the Dynamic Web Project wizard
    Screen shot showing how to open the Dynamic Web Projec wizardt
  3. On the New Dynamic Web Project wizard, enter AccountManagementWEB for the Project name, and select other values as shown in the following table (and in Figure 40). Click the Next Button.
    Project name AccountManagementWEB
    Target Runtime IBM WASCE v2.1
    Configurations Default Configuration for IBM WASCE v2.1

    Figure 40. Dynamic Web Project wizard
    Screen shot showing Dynamic Web Project wizard
  4. On the Project Facets wizard, check the Dynamic Web Module, Java and WASCE Deployment boxes as Figure 41 shows. Click the Next button. We will not select the Java Persistence checkbox, but instead will use the JPA projects created earlier.
    Figure 41. Project Facets wizard
    Screen shot showing Project Facets wizard
  5. On the Web Module wizard, enter the values shown in the following table (and Figure 42). Click the Next button.
    Context Root AccountManagementWEB
    Create Directory WebContent
    Java Source Directory src
    Create Deployment Descriptorcheck the checkbox

    Figure 42. Web Module wizard
    Screen shot showing Web Module wizard
  6. On the Geronimo Deployment Plan wizard, enter the values shown in the following table (and Figure 43). Click the Finish button. This step creates a new Web project called AccountManagementWEB in Project Explorer.
    Group Id Web
    Artifact Id accountJPA
    Version 1.0
    Artifact Type car

    Figure 43. Geronimo Deployment Plan wizard
    Screen shot showing Geronimo Deployment Plan wizard
  7. Right-click the Web project, and select Properties.
    Figure 44. Opening the Properties view
    Screen shot showing how to open the Properties view
  8. Click Java Build Path on the left side, and add the DB2AccountUnit and DerbyAccountUnit projects (Figure 45). Since we are going to use sample.jpa.Db2account and sample.jpa.Derbyaccount persistent classes in the Web application, the JPA projects have to be in its build.
    Figure 45. Specifying the Java build path
    Screen shot showing how to specify the Java build path
  9. Click J2EE Module Dependencies on the left side, and select the DerbyAccountUnit and DB2AccountUnit projects (Figure 46). When you export the Web application to a .WAR file, the JPA projects get packaged in the WEB-INF/lib folder as DerbyAccountUnit.jar and DB2AccountUnit.jar files.
    Figure 46. Specifying the J2EE module dependencies
    Screen shot showing how to specify the J2EE module dependencies

Develop JSPs and servlets

For this part of the tutorial, you need to download our sample code. We need to add the following JSPs, servlets and classes to the AccountManagementWEB project from the AccountManagementWEB.war file.

  • JSPs
    • folder : /
      • index.jsp
      • Create_Account.jsp
      • Retrieve_Account.jsp
      • Update_Account.jsp
      • Transfer_Amount.jsp
  • Servlets
    • Package : sample.jpa.servlet
      • CreateAccount.java
      • RetrieveAccount.java
      • UpdateAccount.java
      • TransferAmount.java
  • Classes
    • Package : sample.jpa
      • AccountException.java

Explore various components of the Web application

The JSPs provide a Web interface to the users for data input. The servlets retrieve the user input from the HttpServletRequest, and perform DB operations against underlying databases (SAMPLE and ACCOUNTDB) using JPA. When any application exception needs to be raised, the servlets create an AccountException object and throw it. The application exceptions are caught in the catch block and displayed to the user as a response.

The Index.jsp is the main page that allows navigation to other pages. The Create_Account.jsp displays an HTML form to collect account details. After entering the valid input values, clicking on the Submit button submits to CreateAccount servlet. The CreateAccount servlet retrieves the input data from the HttpServletRequest and persists account details to the DB2ACCOUNT table in the SAMPLE database. It uses the entity manager obtained from the DB2AccountUnit persistence unit, and performs database operations in the local transaction scope.

Similarly, you can retrienve and update existing accounts using Retrieve_Account.jsp/RetrieveAccount.java and Update_Account.jsp/UpdateAccount.java respectively.

The Transfer_Amount.jsp collects a debit account number in the DB2ACCOUNT table, credit account number in the DERBYACCOUNT table, amount to be transferred, and submits them to the TransferAmount.java servlet. The servlet performs a JTA transaction on the two databases to transfer the amount. It uses entity managers from DerbyAccountUnit and DB2AccountUnit_JTA persistence units, and enlists them in the global transaction. We’ll configure the DB2AccountUnit_JTA in the next section.


Configuring persistence units in the Community Edition deployment plan

In this section, you will perform just one task:

  • Configure JTA persistence unit for SAMPLE database.

Configuring and overriding persistence unit configuration in Geronimo plans You can configure persistence units in the Geronimo plans (geronimo-web.xml, openejb-jar.xml, or geronimo-application.xml) in addition to, or instead of, configuring them in persistence.xml files. A persistence-unit declaration in persistence.xml can be overridden in Geronimo plans. If you declare a persistence-unit in both persistence.xml and in a Geronimo plan, the declaration in the Geronimo plan overrides the declaration in persistence.xml.

As explained in the Configure DB2AccountUnit persistence unit section, the DB2AccountUnit is configured as a RESOURCE_LOCAL persistence unit in its persistence.xml. The entity manager created from this configuration performs only local transactions. It does not use the JTA transaction manager from the application server.

The TransferAmount.java servlet needs to update the SAMPLE database (in DB2) as well as the ACCOUNTDB database (in Derby) in a global transaction. So, it needs entity managers that can enlist themselves in the global transaction manager (JTA transaction manager). The DerbyAccountUnit is already configured as a JTA persistence unit. We need another persistence unit to provide a JTA entity manager for the SAMPLE database.

To accomplish this task, we will configure a third persistence unit DB2AccountUnit_JTA in the geronimo-web.xml file of the Web application. Please see the highlighted portion in Listing 4:

Listing 4. Changes to the geronimo-web.xml file
<web:web-app xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2" 
 xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2"
 xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2" 
 xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2" 
 xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1" 
 xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0" 
 xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" 
 xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1" 
 xmlns:pers="http://java.sun.com/xml/ns/persistence" 
 xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0">

    <dep:environment>
        <dep:moduleId>
            <dep:groupId>web</dep:groupId>
            <dep:artifactId>accountJPA</dep:artifactId>
            <dep:version>1.0</dep:version>
            <dep:type>car</dep:type>
        </dep:moduleId>
      <dependencies>
            <dependency>
                <groupId>console.dbpool</groupId>
                <artifactId>DB2Datasource</artifactId>
            </dependency>
      </dependencies>        
</dep:environment>

    <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
      <persistence-unit name="DB2AccountUnit_JTA" transaction-type="JTA">
       <description>DB2 Account Management</description>
          <provider>
            org.apache.openjpa.persistence.PersistenceProviderImpl
          </provider>
       <jta-data-source>DB2Datasource</jta-data-source>
      </persistence-unit>
    </persistence>

   <web:context-root>/AccountManagementWEB</web:context-root>
</web:web-app>

The TransferAmount.java servlet uses DB2AccountUnit_JTA and DerbyAccountUnit persistence units to perform a global transaction.

The servlets in the AccountManagementWEB application use entity managers of DB2AccountUnit and DB2AccountUnit_JTA persistence units. These persistence units connect to the SAMPLE database running in DB2, and use DB2Datasource deployed on the server. Hence, we need to declare a dependency in the geronimo-web.xml on the DB2Datasource. The moduleId of the DB2Datasource connection pool is console.dbpool/DB2Datasource/1.0/car.


Deploying the Web application.

In the section we perform the following tasks:

  • Deploy the AccountManagementWEB application
  • Explore an alternative way to deploy the AccountManagementWEB application.

Deploy the AccountManagementWEB application

  1. Right-click AccountManagementWEB and select Run As => 1 Run on Server.
    Figure 47. Running the application
    Screen shot showing how to run the application
  2. On the Run on Server wizard, select Choose an existing server radio button , IBM WASCE v2.1 Server at localhost, and check on the Always use this server when running this project. as Figure 48 shows. Click the Next button.
    Figure 48. Choosing the server
    Screen shot showing how to choose the server
  3. On the next screen, click the Finish button to deploy the application on to the server.
  4. On the Eclipse main content area, you see the index.jsp in the browser window, as Figure 49 shows:
    Figure 49. index.jsp running in a browser
    Screen shot showing index. jsp running application

Alternative way to deploy the AccountManagementWEB application.

Alternatively, you can use the following procedure to deploy the application outside the Eclipse environment.

  1. Right-click on the Web application and export it as a WAR file, as Figure 50 shows:
    Figure 50. Exporting the application as a WAR
    Screen shot showing how to export the application
  2. On the WAR Export wizard, provide the values shown in the following table (and Figure 51) and click the Finish button.
    Web Module AccountManagementWEB
    Destinationdestination directory
    Export Source filesCheck on the checkbox
    Overwrite existing fileCheck on the checkbox

    Figure 51. WAR Export wizard
    Screen shot showing WAR Export wizard
  3. Open a Command window and start the Community Edition server by entering this command: <wasce_home>/bin>startup.[sh|bat].
  4. Deploy the application using the command in Listing 5:

    Listing 5. Deployment command

    <wasce_home>\bin>deploy.bat --user system --password manager 
    deploy AccountManagementWEB.war
    
    Using GERONIMO_BASE: <wasce_home>
    Using GERONIMO_HOME: <wasce_home>
    Using GERONIMO_TMPDIR: var\tempUsing JRE_HOME: <jdk_home>\jre
    Deployed web/accountJPA/1.0/car 
    @ /AccountManagementWEB
    <jdk_home> is the location where the IBM Java SDK is installed.

Running the Web application

In this section we walk through running the application, and perform the following tasks:

  • Insert sample account details into the DB2ACCOUNT table
  • Retrieve the existing account details and update the values.
  • Transfer an amount from the DB2ACCOUNT table to DERBYACCOUNT

Insert sample account details into the DB2ACCOUNT table

  1. Open a Web browser window and open the url http://localhost:8080/AccountManagementWEB/. This step displays the main page shown in Figure 52:
    Figure 52. AccountManagement main page
    Screen shot showing AccountManagement main page
  2. Click on the Create a New Account link. This displays an HTML form to enter the account details. Enter some account details as shown in Figure 53, and click the Submit button.
    Figure 53. Create a New Account
    Screen shot showing Create a New Account
  3. You now have a new account with account number 10 in the DB2ACCOUNT table. Listing 6 shows the corresponding code snippet:

    Listing 6. sample.jpa.servlet.CreateAccount.java

    public class CreateAccount 
        extends javax.servlet.http.HttpServlet 
        implements javax.servlet.Servlet 
          {static final long serialVersionUID = 1L;
          
          @PersistenceUnit(unitName="DB2AccountUnit")
           private EntityManagerFactory emf;
    
           EntityManager em;
    
           public void init(ServletConfig config)
             { System.out.println("CreateAccount Servlet created..!"); 
             em = emf.createEntityManager(); 
             }
           
            public void destroy()
              {System.out.println("CreateAccount Servlet destroyed..!");
              em.close();
              emf.close();}
              …
              …
              .…
              protected void doPost(HttpServletRequest request, 
                HttpServletResponse response) 
              throws ServletException, IOException
     
              {try{
                 int accno = Integer.parseInt(request.getParameter("ACCNO"));
                 String ownerName = request.getParameter("OWNERNAME"); 
                 String strDate = request.getParameter("DOP"); 
                 long lgDate=new SimpleDateFormat("MM/dd/yyyy"). 
                     parse(strDate,new ParsePosition(0)).getTime(); 
    
                     java.sql.Date dbDate=new java.sql.Date(lgDate); 
                     String accType = request.getParameter("ACCOUNTTYPE"); 
                     BigDecimal balance = new BigDecimal
                       (request.getParameter("BALANCE")); 
                     em.getTransaction().begin(); 
                     Db2account account1 = em.find(Db2account.class, accno);
    
                      if(account1 != null)
                      { throw new AccountException
                           ("Error : sample.jpa.servlet.CreateAccount : 
                           Account Number already exists:"+accno); 
                      } 
                       
                      Db2account account = new Db2account(); 
                      account.setAccno(accno); 
                      account.setAccountType(accType); 
                      account.setBalance(balance); 
                      account.setDateOpen(dbDate); 
                      account.setOwner(ownerName); 
                      
                       em.persist(account); 
                       em.getTransaction().commit(); 
                       response.sendRedirect("Create_Account.jsp");}
    
              catch (AccountException ae)
                {ae.printStackTrace();
                  PrintWriter out = response.getWriter();
                  printMessage(ae,out);
                  em.getTransaction().rollback();}
    
               catch (Exception e)
                  {e.printStackTrace();
                   PrintWriter out = response.getWriter();
                   printMessage(e,out);em.getTransaction().rollback();
                  }
                  }

    We used the entity manager factory to create an entity manager. Since it is an application-managed entity manager, the servlet closes the entity manager and the entity manager factory using the destroy() method. We also used EntityTransaction to perform the local transactions. The transaction rolls back in the catch block when there is an application exception or system exception.

  4. Create another account like the one in Figure 54:
    Figure 54. Creating a new account
    Screen shot showing how to create a new account
  5. Try to create another account with the account number 10, which is already inserted in the table (Figure 55):
    Figure 55. Create another new account
    Screen shot showing another new account with account number 10

    This data throws an error stating that the account already exists (Figure 56):

    Figure 56. Error message
    Screen shot showing error message

Retrieve the existing account details and update the values.

  1. From the main page, click on the Update an Existing Account link. This will display a HTML form to input account number. Provide the value as 10 and click on the Submit button, as Figure 57 shows:
    Figure 57. Updating an existing account
    Screen shot showing Update an Existing Account form
  2. The Update Account Details form opens, filled with the details of the account number 10. To update the details, modify the values (except for account number) and click the Submit button (Figure 58):
    Figure 58. Updating account details
    Screen shot showing Update Account Details form

Transfer an amount from the DB2ACCOUNT table to DERBYACCOUNT

  1. From the main page, click the Transfer Amount link to display a form to input the debit account number, credit account number and the amount to transfer. Enter some values as in Figure 59, and click the submit button.
    Figure 59. Transferring an amount of money
    Screen shot showing Transfer Amount form

    Listing 7 shows the corresponding code snippet:

    .

    Listing 7. sample.jpa.servlet.TransferAmount

    public class TransferAmount extends javax.servlet.http.HttpServlet 
       implementsjavax.servlet.Servlet 
    {static final long serialVersionUID = 1L;
    
     @PersistenceContext(unitName="DerbyAccountUnit")
     private EntityManager derbyManager;
    
     @PersistenceContext(unitName="DB2AccountUnit_JTA")
     private EntityManager db2Manager;
      …
      …
      ....
      protected void doPost(HttpServletRequest request, 
       HttpServletResponse response) 
       throws ServletException, IOException 
    
       {UserTransaction ut;
        try{
          int debitAccno = Integer.parseInt(request.getParameter("DEBITACCNO"));
          int creditAccno = Integer.parseInt(request.getParameter("CREDITACCNO"));
          BigDecimal bigAmount = new BigDecimal(request.getParameter("AMOUNT"));
    
          double amount = bigAmount.doubleValue();
          Context ctx = new InitialContext();
          ut = (UserTransaction)ctx.lookup("java:comp/UserTransaction");
    
          ut.begin();
    
          Db2account db2Account = db2Manager.find(Db2account.class, debitAccno);
          Derbyaccount derbyAccount = derbyManager.find(Derbyaccount.class, creditAccno);
    
          db2Manager.refresh(db2Account);
          derbyManager.refresh(derbyAccount);
    
          if(db2Account == null)
          throw new AccountException
             ("Error : sample.jpa.servlet.TransferAmount : 
                Debit  Account Number does not exist:"+debitAccno);
    
          if(derbyAccount == null)
          throw new AccountException
             ("Error : sample.jpa.servlet.TransferAmount :  
                credit Account Number does not exist:"+creditAccno);
    
          if(db2Account.getBalance().doubleValue() < amount)
          throw new AccountException
              ("Error : sample.jpa.servlet.TransferAmount :  
                Insufficient funds to transfer in debitaccount:"
               +"debitAccno("+debitAccno+")"+"Amount("+amount+")"
               +"Available Balance("+db2Account.getBalance()+")");
    
          db2Account.setBalance(new bigDecimal
             (db2Account.getBalance().doubleValue()  - amount));
          derbyAccount.setBalance(new BigDecimal
             (derbyAccount.getBalance().doubleValue()  + amount));
    
         db2Manager.flush();
         derbyManager.flush();
    
          ut.commit();
    
          response.sendRedirect("Transfer_Amount.jsp");
        }
    
       catch (AccountException ae){ae.printStackTrace();
        {PrintWriter out = response.getWriter();
        printMessage(ae,out);
        }
    
       catch (Exception e)
         {e.printStackTrace();
          PrintWriter out = response.getWriter();
          printMessage(e,out);
        }
    }
  2. The TransferAmount servlet injects derbyManager and db2Manager entity managers using the @PersistenceContext annotation. Therefore, the injected objects are container-managed entity managers. The container manages the life cycle of the persistence context. Hence, there is no code to create entity managers and close them later when not needed. The servlet gets the UserTransaction object and begins the transfer amount transaction. The entity managers are automatically enlisted in the global transaction when any methods are invoked within the transaction scope.
  3. If the debit account does not have sufficient funds then application will throw an error, as you can see in Figures 60 and 61.
    Figure 60. Entering an account number with insufficient funds
    Screen shot showing tranfer of $7000.00
    Figure 61. Insufficient funds error message
    Screen shot showing Insufficient funds error message

Conclusion

You have seen how easy it is to develop persistence applications using JPA. The Eclipse IDE makes it even easier to generate the persistent classes from the underlying tables. You can develop the independent persistent units and package them into Java EE applications. Community Edition also lets you declare persistent units in deployment plans.

Most importantly, the POJO-based programming model eliminates boiler-plate code from the application components. The database connection properties, transaction configuration, and mapping information are delegated to annotations or XML files. With Community Edition, you don’t need any server specific configurations to run the JPA applications.


Download

DescriptionNameSize
Sample Web archive for this articleAccountManagementWEB.war27KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Open source
ArticleID=325646
ArticleTitle=Developing JPA Applications with WebSphere Application Server Community Edition
publish-date=07302008