From general-return-540-apmail-db-general-archive=db.apache.org@db.apache.org Wed Dec 19 18:21:36 2012 Return-Path: X-Original-To: apmail-db-general-archive@www.apache.org Delivered-To: apmail-db-general-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 192D1DCB7 for ; Wed, 19 Dec 2012 18:21:36 +0000 (UTC) Received: (qmail 50306 invoked by uid 500); 19 Dec 2012 18:21:35 -0000 Delivered-To: apmail-db-general-archive@db.apache.org Received: (qmail 50251 invoked by uid 500); 19 Dec 2012 18:21:35 -0000 Mailing-List: contact general-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: general@db.apache.org List-Id: Delivered-To: mailing list general@db.apache.org Received: (qmail 50108 invoked by uid 99); 19 Dec 2012 18:21:35 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Dec 2012 18:21:35 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Dec 2012 18:21:31 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 8C79C23889EC for ; Wed, 19 Dec 2012 18:20:46 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r843115 [8/44] - in /websites/production/db/content/derby: ./ binaries/ blogs/ blogs/images/ dev/ docs/ images/ integrate/ integrate/plugin_help/ integrate/plugin_help/images/ logo/ manuals/ papers/ papers/DerbyTut/ releases/ skin/ skin/css... Date: Wed, 19 Dec 2012 18:20:28 -0000 To: general@db.apache.org From: rhillegas@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20121219182046.8C79C23889EC@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: websites/production/db/content/derby/integrate/DerbyTomcat5512JPetStor.html ============================================================================== --- websites/production/db/content/derby/integrate/DerbyTomcat5512JPetStor.html (added) +++ websites/production/db/content/derby/integrate/DerbyTomcat5512JPetStor.html Wed Dec 19 18:20:21 2012 @@ -0,0 +1,771 @@ + + + + + + + +Embedding Apache Derby in Tomcat and creating an iBATIS JPetStore Demo + + + + + + + + + +
+ +
+apache > db +
+ +
+ + + + +
+Apache DB Project +
+ + + + +
+
+
+
+ +
+ + +
+ +
+ +   +
+ + + + + +
+
Font size: +   +   +   +
+

Embedding Apache Derby in Tomcat and creating an iBATIS JPetStore Demo

+ + +

This is the third in a series of articles that detail creating a demonstration web application using a Derby database running in different server environments. This article details how to create the demo on the Apache Tomcat Server. See the links in the Related Articles section below to access the other articles.

+ + +
+
Note
+
As of this writing (Oct 2005), Tomcat 5.5.12 has just been declared a "stable release" and is used for this demonstration. Version 5.5.12 bundles the DBCP libraries needed to establish the datasource connection pool used by the system. If you will be using an older version of Tomcat you will need to add this component as described on the JDBC Datasources page for your release. You may also need to address other version differences. This deployment was not tested on other Tomcat versions.
+
+ + +

+ This article shows the steps required to embed Derby in a Tomcat version 5.5.12 Server and then deploy a copy of the iBATIS JPetStore application that utilizes a Derby database. The implementation accesses the Derby database via a JNDI registered datasource and hence the same application code and Derby database can be used unchanged to create the demo in different environments. Details are provided for registering the datasource as either a Tomcat server-wide (Global) JNDI resource or a per-application (context specific) JNDI resource.

+ + +

Why Derby

+
+

+Most J2EE applications use a JDBC-compliant database to store data. Arguably, one of the more time consuming tasks when deploying such an web application is the database setup. These steps often involve compiling DBMS code (if the database system is not already installed) then creating and populating the physical database itself. Since Derby is implemented entirely in JAVA these steps can be avoided. Simply put, Derby is easy add to a Tomcat Server environment and reduces the complexity of deploying applications that use a database.

+

+Installation of the Derby DBMS is as simple as copying a 2 Mb jarfile to a known location. Like any other general use component the Derby jarfile is added to the Tomcat common shared library directory. Setup of the physical database and application data can be as easy as copying the fully initialized physical database to a location on the Server machine then configuring datasource to access it. The following instructions demonstrate the ease with which this can be accomplished using Tomcat version 5.5.12. +

+
+ + + +

The Software Components

+
+

Derby is an open source, java relational database freely available from the Apache Software Foundation (ASF). It is well suited for use with Java applications that require data persistence and is ideally suited for use in a Server environment like Tomcat. Derby can be used in one of two configurations, embedded in a java application or used with Network Server and run as a separate DBMS process. When embedded in an application like Tomcat that provides network communication services there is usually no need to run the Network Server.

+

+Tomcat is a widely used, open source web application server freely available from ASF. Initially designed as a servlet/JSP container Tomcat now bundles many additional components that provide J2EE Server capabilities to the system. Tomcat development is managed as a subproject of the Apache Jakarta project.

+

+JPetStore is a rewritten Pet Store application based on Sun's J2EE Pet Store. It was originally designed to compare the .NET and J2EE architectures. It is now the official example application for the iBATIS Data Mapper framework. iBATIS greatly simplifies the coding of Java and .NET applications that access data from a relational database like Derby. iBATIS, like the other software used in this implementation is an open source product freely available from ASF.

+
+ + +

Typographic Conventions Used

+
+

The following codes in curly braces will be used to represent installation dependant information as described below:

+
+ +
{Tomcat_Home}
+ +
The installation directory for the Tomcat server (a.k.a. CATALINA_HOME).
+ +
{machine-name}
+ +
the hostname of the machine on which the server and application are installed.
+ +
{Derby_System_Home}
+ +
the directory containing the derby.log file. This is the default output directory for Derby and should be the same as {Tomcat_Home}. The JPetStoreDB database will be located in the {Derby_System_Home}\Databases subdirectory.
+ +
{Derby_Jars}
+ +
The location of the derby jarfiles. In this installation the location will be the Tomcat common shared library directory: {Tomcat_Home}/common/lib + +
+ +
+
+ + +

Required Software / Downloads

+
+
    + +
  • If necessary, install a functional J2SE Java Developers Kit (JDK). Tomcat 5.5.12 requires JDK 5.0 by default. If you will be using an JDK please see the Tomcat documentation for setup information. The JDK 'bin' directory should be included in your PATH.
  • + +
  • If necessary, Download and install Tomcat v 5.5.12.
  • + +
  • Download the DerbyJPetStore4Tomcat.zip file (4.8 Mb) associated with this article. Move the file to the directory {Tomcat_Home}/work.
  • + +
+
+ + +

Setup of Application with the Datasource in the Global Context:

+
+

The initial steps below walk you through moving the files contained in the DerbyJPetStore4Tomcat.zip file to the locations required to support the deployment instructions that follow. Note that the zipfile contains not only the application system but also the DBMS and the initialized database. No database activity is required other than placing the files in the proper directories. Assuming you have a functioning Tomcat 5.5.12 system already everything you need to create the demo is found in the zipfile associated with this article.

+

Subsequent steps show you how to define the JPetStoreDB datasource connection pool in the Global Naming Context. When defined in this way the datasource can be utilized by any application running on the server. Once the datasource required by the application is defined the JPetStore application is deployed and you have a functioning web application. The step-by-step instructions are:

+
    + +
  • + +Stop Tomcat: Shutdown Tomcat if it is running.
  • + +
  • + +Extract the database zipfile and deployment files: Unzip the files from DerbyJPetStore4Tomcat.zip into the directory {Tomcat_Home}/work then "install" Derby as follows: +
      + +
    • + +Install the Derby DBMS system: Move the derby.jar file to the Tomcat 'common' directory {Tomcat_Home}/common/lib.
    • + +
    • + +Setup the JPetstore database: Unzip the database from the DerbyJPetStoreDB.zip file and move the Databases directory tree to {Tomcat_Home}.
    • + +
    + +
  • + +
  • + +Define the Global Datasource: A Global datasource is defined in the server XML configuration file {Tomcat_Home}/conf/server.xml. Save a copy of the current server configuration file then add the following definition to {Tomcat_Home}/conf/server.xml. The location of the definition must be in the Global Naming Resources section of the file. For simplicity locate the end of section marker </GlobalNamingResources> and add the following lines just above it:
    +         <!-- Global Datasource for Derby JPetStoreDB database -->
    +         <Resource name="jdbc/JPetStoreDB"
    +              type="javax.sql.DataSource"  auth="Container"
    +              description="Derby database for JPetStoreApp"
    +              maxActive="100" maxIdle="30" maxWait="10000"
    +              username="" password="" 
    +              driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
    +              url="jdbc:derby:Databases/JPetStoreDB"/>
    +			
    + +
  • + +
  • + +Start Tomcat and the manager console: Start Tomcat and open the Manager application in a browser (URL for default installation: http://{machine-name}:8080/manager/html). Supply a valid username and password to access the Tomcat Web Application Manager screen.
  • + +
  • + +Deploy the JPetStore application: Scroll past the application list to the section labeled: +Deploy directory or WAR file located on server (see Figure 1). Enter the following information:
    +         Context Path (optional):   /JPetStoreApp
    +      XML Configuration file URL:   work/JPetStoreAppGbl.xml
    +            WAR or Directory URL:   work/JPetStoreApp.war
    +      
    + +
    +
    Figure 1: Tomcat Manager Deployment Screen
    +
    + +TomcatDeploy +
    +
    + Click the Deploy button to deploy and start the application. Check in the message section for the confirmation of a successful deployment: OK - Deployed application at context path /JPetStoreApp. + +
  • + +
  • + +Test the application: In the Applications list section, click on the application name in the Path column or open the application from a new window with the URL: http://{machine-name}:8080/JPetStoreApp + +
  • + +
+
+ + + +

Alternate Setup: Datasource in the Application Context

+
+

The datasource connection pool used by the JPetStore application can be defined in the Global context as show above or in the Application context outlined here. Either context will support connections between iBATIS and Derby. The difference between the two setups is whether or not another application deployed to this Tomcat server will be able to access the datasource. When the datasource is defined in the Global context other applications can also connect to the pool by linking to the Global datasource using a copy of the Resource-link definition found in the JPetStoreAppGbl.xml file used in the deployment above. This is the configuration that should be used if, say, a Petstore accounting or reporting application will be deployed in a separate secured context that is available to a limited number of users. +

+

When setting up a connection pool in the application context all the information about the datasource is provided in the application XML configuration file. Compare this to the Global datasource setup where the definition is in the server XML configuration file server.xml rather than the application XML configuration file. The contents of these two files are all that differs in the following set of steps for recreating the demo using an application context datasource.

+
+
Note
+
The steps below assume you have performed the previous steps and already have the JPetStore files extracted and the derby.jar and Derby database copied to the proper locations.
+
+
    + +
  • + +Stop Tomcat: Shutdown Tomcat if it is running.
  • + +
  • + +Replace the server.xml file: Restore the copy of the original server.xml saved previously or delete the Datasource definitions lines added to the GlobalNamingResources section. No changes to the server.xml file are needed in this configuration.
  • + +
  • Extract the database zipfile and deployment files: Already done + +
      + +
    • Install the Derby DBMS system: Already done + +
    • + +
    • Setup the JPetstore database: Already done + +
    • + +
    + +
  • + +
  • + +Start Tomcat and the manager console: Start Tomcat and open the Manager application in a browser (URL for default installation: http://{machine-name}:8080/manager/html). Supply a valid username and password to access the Tomcat Web Application Manager screen.
  • + +
  • + +Undeploy the JPetStore application: The application deployed above is not functional and recorded errors to the logfile when it attempted to start. Click the Undeploy for JPetStoreApp in the application list
  • + +
  • + +Deploy the JPetStoreA application: Scroll past the application list to the section labeled: +Deploy directory or WAR file located on server (refer to Figure 1). Enter the following information:
    +         Context Path (optional):   /JPetStoreAppA
    +      XML Configuration file URL:   work/JPetStoreAppCntxt.xml
    +            WAR or Directory URL:   work/JPetStoreApp.war
    +      
    + Click the Deploy button to deploy and start the application. Check in the message section for the confirmation of a successful deployment: OK - Deployed application at context path /JPetStoreAppA. +
  • + +
  • + +Test the application: In the Applications list section, click on the application name in the Path column or open the application from a new window with the URL: http://{machine-name}:8080/JPetStoreAppA + +
  • + +
+
+ + +

Database Creation Instructions (optional)

+
+

The following steps show how to build the Derby database from scratch. This is similar to the build procedure required when deploying applications using most other DBMS system except a separate database creation step is not required. Two files (*.sql) are supplied in the zipfile to perform the schema build and data inserts. To use this procedure you will need to download a complete set of Derby jarfiles in order to obtain the IJ scripting tool used in the following commands. The IJ tool is used to process the SQL commands in the provided scripts. The IJ tool is contained in the derbytools.jar file. Place derbytools.jar in the {Derby_Jars} directory. For simplicity the examples below place all necessary files in the same directory and specify as much a possible (including the command to create the database) on the command line.

+
    + +
  • Copy the following SQL script files to the {Derby_System_Home}\Databases subdirectory where you will build the database: ,jpetstore-derby-schema.sql, jpetstore-derby-dataload.sql. Issue the following command to create the database, tables and indexes: +
    +   java -cp {Derby_Jars}/derby.jar:{Derby_Jars}/derbytools.jar \
    +   -Dderby.system.home={Derby_System_Home}\Databases  \
    +   -Dij.database=jdbc:derby:JPetStoreDB;create=true \
    +   	   org.apache.derby.tools.ij jpetstore-derby-schema.sql
    +	
    + +
  • + +
  • Now load the data into the tables using the following command: +
    +
    Note
    +
    If you are performing the build on a Windows based OS change the classpath separator between the jarfile names for a colon (:) to a semicolon (;) in the following commands: + e.g. java -cp {Derby_Jars}/derby.jar;{Derby_Jars}/derbytools.jar...
    +
    + +
    +	java -cp {Derby_Jars}/derby.jar:{Derby_Jars}/derbytools.jar   \
    +	 -Dderby.system.home={Derby_System_Home}\Databases  \
    +	 -Dij.database=jdbc:derby:JPetStoreDB  \
    +	   org.apache.derby.tools.ij jpetstore-derby-dataload.sql
    +	
    + +
  • + +
+

You now have a fully populated database to use with the JPetStore application.

+
+ + + +

General Integration Notes

+
+

+J2EE Servers use multiple classloaders (aka hierarchies) to provide the isolation necessary to run many applications at once. This Derby-JPetStore integration uses a Server defined datasource to avoid problems that can occur when Derby is used in an environment that has multiple classloaders. Derby is written in Java and all its classes must be loaded by the same classloader. When using a J2EE Server this can be assured by defining Derby datasources at the server level. This is particularly important when using Derby in it's embedded configuration. When using a database or other datasource in a J2EE environment it is also a good design practice to access them via a J2EE resource managed by the server. +

+

+ The zipfile provided contains a fully initialized database to demonstrate that a Derby database built and populated on one platform (in this case Windows) can be transferred to different platforms and work fine. Try copying the database and derby jarfiles to different platforms and you will see that the system works without modification. The text files included in the zipfile will not do well in an EBCDIC architecture but the Derby engine and supplied database will work fine. If you want to build the database from scratch you can use the SQL files supplied in the archive. See the 'Optional Database Setup Instructions' section for how to use the IJ tools to build and populate the database.

+
+ + + +

Tomcat Integration Notes

+
+

Tomcat is designed so that new java components (a.k.a. shared libraries) can be easily added to the system. This is accomplished by adding the jarfiles containing the components to the $CATALINA_HOME/common/lib directory. + Derby is designed to be used in just this manner. The Derby manuals refer to this as embedding. Embedding makes Derby just another component available to the applications deployed on Tomcat. Adding the derby.jar file to the common shared libraries directory makes the Derby engine, not just the JDBC driver, available. No separate steps are required to install, configure or start the Derby engine.

+

The default Session Manager (org.apache.catalina.session.StandardManager) created for each application context (a.k.a. web application) enables Restart persistence. This feature is disabled in the JPetStore XML configuration files to avoid the problem where the JNDI context java:comp is not accessible when the iBATIS Dao Transaction Pool is restarted. This problem is typified by startup messages in the catalina.log file containing the following error text:

+
org.apache.catalina.session.StandardManager start
+SEVERE: Exception loading sessions from persistent storage
+java.lang.ExceptionInInitializerError
+  at com.ibatis.jpetstore.service.CatalogService.<nit>(CatalogService.java:23)
+       --- rest of trace removed --
+  Caused by: java.lang.RuntimeException: 
+      Could not initialize DaoConfig.  
+  Cause: com.ibatis.dao.client.DaoException: 
+      Error while configuring DaoManager. 
+  Cause: com.ibatis.sqlmap.client.SqlMapException: 
+      There was an error while building the SqlMap instance. 
+         --  messages removed --
+  --- Cause: com.ibatis.sqlmap.client.SqlMapException: 
+      There was an error configuring JndiDataSourceDaoTransactionPool. 
+  Cause: javax.naming.NameNotFoundException: 
+      Name java:comp is not bound in this Context 
+
+
Disabling Restart Persistence
+
The following line in the application XML configuration file sets the persistence file to an empty string and disables Restart Persistence for the application: <Manager pathname=""/> +
+
+
+ + +

iBATIS Integration Notes

+
+

If you wish to build your own iBATIS JPetstore war file like the one supplied in the zipfile file you will need to download the JPetStore application source code (see the 'Related Links' section) and make the following modifications to the source files before performing a build as described in the JPetStore build instructions:

+
    + +
  • + Edit the sql-map-config.xml file and replace the existing TransactionManager definition section with the this section that specifies a JNDI lookup should be performed to obtain the datasource to use: +
    +   <transactionManager type="JDBC" >
    +      <dataSource type="JNDI">
    +         <property name="DBJndiContext" value="jdbc/JPetStoreDB"/>
    +      </dataSource>
    +   </transactionManager>
    +   
    + +
  • + +
  • Edit the web.xml file and replace the existing resource-ref definition with the following: +
    +      <resource-ref> 
    +   <description>JPetStore DataSource</description>
    +	<res-ref-name>jdbc/JPetStoreDB</res-ref-name>
    +	<res-type>javax.sql.DataSource</res-type>
    +	<res-auth>Container</res-auth>
    +	<res-sharing-scope>Shareable</res-sharing-scope>
    +   </resource-ref>
    +   
    + +
  • + +
+
+ + + +

Links Section

+
+

Required Downloads to perform this deployment:

+ +

Download links for software used in creating this deployment:

+ +

Learn more:

+ +

Related articles:

+ +

+ Stan Bradbury wrote these instructions. + Please post any questions about them + to derby-user@db.apache.org. +

+
+ +
+ +
 
+
+ + + Added: websites/production/db/content/derby/integrate/JPOX_Derby.html ============================================================================== --- websites/production/db/content/derby/integrate/JPOX_Derby.html (added) +++ websites/production/db/content/derby/integrate/JPOX_Derby.html Wed Dec 19 18:20:21 2012 @@ -0,0 +1,1317 @@ + + + + + + + +Using JPOX JDO with Derby + + + + + + + + + +
+ +
+apache > db +
+ +
+ + + + +
+Apache DB Project +
+ + + + +
+
+
+
+ +
+ + +
+ +
+ +   +
+ + + + + +
+
Font size: +   +   +   +
+

Using JPOX JDO with Derby

+ + + + +

Overview

+
+

+This paper gives a concrete example of using JPOX JDO to persist and retrieve +data to and from Apache Derby. Java Data Objects (JDO) is a specification for +persisting Java objects. JPOX JDO 1.1 is the reference implementation for the +JDO 2.0 specification. The JDO 2.0 API is provided by the Apache JDO project +and is required to run JPOX JDO 1.1. The JDO 2.0 API conforms to the JDO 2.0 +specification. +

+

Apache Derby, a subproject of the Apache DB project, is a standards compliant database, written and implemented entirely in Java.

+

The steps below show how to use the bottom-up approach to designing an +application which persists Derby data using JPOX Java Data Objects. The +bottom-up approach means the database schema has already been defined. We +will need to provide an object to relational mapping file and the Java +classes (objects) which will be made persistence capable. +(The alternate approach, called top-down, is to define the Java classes +and then generate the database schema based on the mapping file between +database and object classes.) +

+

+The section, Download sample code and configuration files, contains a +zip file which includes a populated Derby database and SQL to create the +database schema (if desired), Java source files, the JPOX JDO meta-data file +and the application classes to issue the JPOX queries. This is not a detailed +explanation of either JPOX or Derby, but should be used as a "cookbook" on how +to use the two together. +

+
+ + + +

Step 1. Prerequisites

+
+

+The following software needs to be downloaded and installed prior to using the +source files provided in the download zip file, jpox_derby.zip. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SoftwareMinimum Release Level RequiredRelease Used in this ExampleDownload Location
Java JDK or SDK1.4.21.4.2Sun or IBM
Apache Derby10.110.1.2Apache Derby
Apache JDO2.0-snapshot7.jar2.0-rc1Apache JDO, 2.0 RC1
JPOX JDO "Core"1.1.0-beta 51.1.0-rc-1JPOX "core" jpox.org
JPOX JDO Enhancer1.1.0-beta 51.1.0-rc-1JPOX Enhancer jpox.org
Apache Jakarta Byte Code Engineering Library (BCEL)5.15.1BCEL(Used by JPOX during the enhancement of the Java classes.)
Apache Log4j1.2.81.2.12Apache Log4j
+
+ + + +

Step 2. Download sample code and configuration files

+
+

+This paper will list each step required to get the sample application up and running, including partial code listings. However, to get the most +out of this paper download the file, jpox_derby.zip to follow along with each step or to view the entire source and configuration files. +

+

+After downloading the jpox_derby.zip file unzip it to a +convenient directory. The examples that follow assume it was unzipped +to the C:/ directory on a windows machine. +

+
+ + + +

Step 3. Examine/Create the Database schema

+
+

+As mentioned above, using the bottom-up approach means we need to +define our database schema first. The schema shown below consists of five tables for a simple airlines reservation system. The data directory +contained in the zip file contains the airlinesDB already populated +with these tables and data. However, if you would like to run the SQL +at a later time to create the database, the airlinesDB.sql file contained +in the zip file can be used to do so. +

+

+SQL for Derby database tables +

+

CREATE TABLE APP.CITIES +( +CITY_ID INTEGER NOT NULL CONSTRAINT cities_pk PRIMARY KEY, +CITY_NAME VARCHAR(24) NOT NULL, +COUNTRY VARCHAR(26) NOT NULL, +AIRPORT CHAR(3), +LANGUAGE VARCHAR(16), +COUNTRY_ISO_CODE CHAR(2) +); + +CREATE TABLE APP.FLIGHTS +( +FLIGHT_ID CHAR(6) NOT NULL, +SEGMENT_NUMBER INTEGER NOT NULL, +ORIG_AIRPORT CHAR(3), +DEPART_TIME TIME, +DEST_AIRPORT CHAR(3), +ARRIVE_TIME TIME, +MEAL CHAR(1) CONSTRAINT MEAL_CONSTRAINT +CHECK (meal IN ('B', 'L', 'D', 'S')), +FLYING_TIME DOUBLE PRECISION, +MILES INTEGER, +AIRCRAFT VARCHAR(6), +DEPART_DATE DATE, +CONSTRAINT FLIGHTS_PK Primary Key (FLIGHT_ID) +); + +CREATE INDEX DESTINDEX ON APP.FLIGHTS (DEST_AIRPORT) ; + +CREATE INDEX ORIGINDEX ON APP.FLIGHTS (ORIG_AIRPORT) ; + +CREATE TABLE APP.USERS +( +FIRSTNAME VARCHAR(40) NOT NULL, +LASTNAME VARCHAR (40) NOT NULL, +USERNAME VARCHAR(20) NOT NULL CONSTRAINT username_pk PRIMARY KEY, +PASSWORD VARCHAR(20) NOT NULL, +PASSWORD_VERIFY VARCHAR(20), +EMAIL VARCHAR(30) NOT NULL +); + +CREATE TABLE APP.USER_CREDIT_CARD +( +ID INT NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT user_cc_pk PRIMARY KEY, +USERNAME varchar(20) NOT NULL, +LASTNAME varchar(40), +CREDIT_CARD_TYPE varchar(15) NOT NULL, +CREDIT_CARD_NUMBER varchar(20) NOT NULL, +CREDIT_CARD_DISPLAY varchar(25) NOT NULL +); + +ALTER TABLE APP.USER_CREDIT_CARD ADD CONSTRAINT USERNAME_FK +Foreign Key (username) REFERENCES APP.USERS (username); + +CREATE TABLE APP.FLIGHTHISTORY +( +ID INT NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT user_fh_pk PRIMARY KEY, +USERNAME VARCHAR(20) NOT NULL, +FLIGHT_ID CHAR(6) NOT NULL, +ORIG_AIRPORT CHAR(3) NOT NULL, +DEST_AIRPORT CHAR(3) NOT NULL, +MILES INTEGER, +AIRCRAFT VARCHAR(6), +DEPARTURE_DATE VARCHAR(25), +CREDIT_CARD_TYPE varchar(15) NOT NULL, +CREDIT_CARD_DISPLAY varchar(25) NOT NULL +); + +ALTER TABLE APP.FLIGHTHISTORY ADD CONSTRAINT USERNAME_FH_FK +Foreign Key (username) REFERENCES APP.USERS (username); +

+
+ + + +

Step 4. Write the classes used to persist the data

+
+

+Once you have created the database schema you will need to code one class for +each corresponding database table you want to persist using JPOX. The Java +class needs to consist of setters and getters with a default constructor to +match the database table. +

+

+Here's the class that corresponds to the APP.CITIES table above. The only +constraint on the Java class to be persisted is it must have a default +constructor, which can be private if you want it to be. The source code for all five java classes that correspond to the database schema shown above is in +jpox_derby.zip. +

+

+Partial listing of CityBean.Java +

+

+public class CityBean { + + private int cityId; + + private String cityName; + + private String country; + + private String airport; + + private String language; + + private String countryCode; + + public CityBean() { + cityId = 0; + cityName = ""; + country = ""; + airport = ""; + language = ""; + countryCode = ""; + } + + public CityBean(int city_id, String city, String ctry, String air) { + cityId = city_id; + cityName = city; + country = ctry; + airport = air; + } + + public CityBean(int cityId, String cityName, String country, + String airport, String language, String countryCode) { + this.cityId = cityId; + this.cityName = cityName; + this.country = country; + this.airport = airport; + this.language = language; + this.countryCode = countryCode; + } + + public String getAirport() { + return airport; + } + + public void setAirport(String airport) { + this.airport = airport; + } + + // create getters and setters for all other member variables + + ... + +} +

+
+ + + +

Step 5. Create the JDO meta-data mapping file

+
+

+By convention this file is usually referred to as package.jdo. +Take a look at the partial listing of the package.jdo file I am using to map +the Derby database tables to the Java classes. (The full package.jdo is available in the download.) +

+

+Partial listing of package.jdo +

+

+ +<?xml version="1.0"?> +<!DOCTYPE jdo PUBLIC "-//Sun Microsystems, Inc.//DTD Java Data Objects +Metadata 2.0//EN" "http://java.sun.com/dtd/jdo_2_0.dtd"> + <jdo> + <package name="org.apache.derby.demo.beans.view"> + <class name="CityBean" identity-type="application" table="CITIES"> + <field name="cityId" primary-key="true"> + <column name="CITY_ID" jdbc-type="INTEGER"/> + </field> + <field name="cityName"> + <column name="CITY_NAME" length="24" jdbc-type="VARCHAR"/> + </field> + <field name="country"> + <column name="COUNTRY" length="26" jdbc-type="VARCHAR"></column> + </field> + <field name="airport"> + <column name="AIRPORT" length="3" jdbc-type="CHAR" allows-null=""> + </column> + </field> + <field name="language"> + <column name="LANGUAGE" length="16" jdbc-type="VARCHAR" allows-null=""> + </column> + </field> + <field name="countryCode"> + <column name="COUNTRY_ISO_CODE" length="2" jdbc-type="CHAR" allows-null=""> + </column> + </field> + </class> + <class name="FlightsBean" identity-type="application" table="FLIGHTS"> + <field name="flightId" primary-key="true"> + + ... + + <class name="FlightHistoryBean" identity-type="application" + table="FLIGHTHISTORY" detachable="true"> + <field name="id" primary-key="true" value-strategy="autoassign"> + <column name="id" jdbc-type="INTEGER"/> + </field> + + ... + + </class> + </package> + <package name="org.apache.derby.demo.beans.model"> + <class name="UserBean" identity-type="application" table="USERS" + detachable="true"> + + ... + + <class name="UserCreditCardBean" identity-type="application" + table="USER_CREDIT_CARD"> + + ... + + </class> + </package> + </jdo> +

+

+The package name refers to the package of the Java class, the class +to the Java Class and the table attribute in the class element is the +name of the database table. Some of the interesting things to note +are the use of primary keys and the autoassign attribute for the +FlightHistoryBean (FlightHistory table). Here is the section showing +the FlightHistoryBean to FlightHistory table mapping: +

+

+ <class name="FlightHistoryBean" identity-type="application" + table="FLIGHTHISTORY" detachable="true"> + <field name="id" primary-key="true" value-strategy="autoassign"> + <column name="id" jdbc-type="INTEGER"/> + </field> +

+

+Referring back to the first part of the create table statement of the FlightHistory table above: +

+

+CREATE TABLE APP.FLIGHTHISTORY +( +id int not null generated always as identity constraint user_fh_pk primary key, +USERNAME VARCHAR(20) NOT NULL, +... +

+

+notice how the id column is the primary key which is generated as an identity +column. To map this to the persistence class the value-strategy must be +autoassign. +

+

+This meta-data file, package.jdo, needs to be at a level in the +source tree that includes all classes it references. For instance, the +package.jdo below references classes in the org.apache.derby.demo.beans.view and org.apache.derby.demo.beans.model +packages, so the package.jdo file would need to be at the level +of org.apache.derby.demo.beans to ensure that it can have +access to the view and model packages below the +beans package. +

+

+For this reason I just put my package.jdo at the top level of all +of the packages I'm using. +

+
+ + + +

Step 6. Create a log4j.properties file to be used by JPOX

+
+

+JPOX uses Apache Log4j to report output and errors. Therefore a +log4j.properties file is required. A sample one is shown below which includes JPOX specific categories. The file to be used for the JPOX output is called jpox.log. Check this log for messages if you have problems during enhancement or runtime. +

+

+log4j.properties file required by JPOX +

+

+# Define the destination and format of our logging +log4j.appender.A1=org.apache.log4j.FileAppender +log4j.appender.A1.File=jpox.log +log4j.appender.A1.layout=org.apache.log4j.PatternLayout +log4j.appender.A1.layout.ConversionPattern=%d{HH:mm:ss,SSS} (%t) %-5p [%c] - %m%n + +# JPOX Categories +log4j.category.JPOX.JDO=INFO, A1 +log4j.category.JPOX.Cache=INFO, A1 +log4j.category.JPOX.MetaData=INFO, A1 +log4j.category.JPOX.General=INFO, A1 +log4j.category.JPOX.Utility=INFO, A1 +log4j.category.JPOX.Transaction=INFO, A1 +log4j.category.JPOX.RDBMS=DEBUG, A1 + +log4j.category.JPOX.Enhancer=INFO, A1 +log4j.category.JPOX.SchemaTool=INFO, A1 +

+
+ + +

Step 7. Enhancing the JPOX classes

+
+

+After all of the Java classes representating the objects corresponding +to the database tables have been written, they first need to be +compiled and then they need to be "enhanced", which makes them +persistence-capabable. JPOX provides a helper class to do this for you which is contained in the jar file jpox-enhancer-*.jar. and is called org.jpox.enhancer.JPOXEnhancer. +

+

+We'll defer the compilation and enhancement step until we are ready +to configure our environment after we've coded the business logic +class and application class. +

+
+ + + +

Step 8. Code the class which makes the JPOX JDO queries

+
+

+Here is the class that contains the business logic specific to our trivialized +airlines reservation application. Also shown is a properties file that is read upon startup to set some JPOX and JDO properties. Although these properties +are required to configure JPOX appropriately to work with Derby, they can be set +from within the application, versus using a properties file as I've done here. The complete source for this class is available in the download. +

+

+Partial listing of JPoxJDO.java containing the JPOX queries +

+

+package org.apache.derby.demo.persistence; + +import javax.jdo.JDOHelper; +import javax.jdo.PersistenceManager; +import javax.jdo.PersistenceManagerFactory; +import javax.jdo.Query; +import javax.jdo.Transaction; + +... + +public class JPoxJDO { + + private static final String JPOX_CONFIG = "jpox.properties"; + private static Properties prop; + private boolean isInitialized = false; + private PersistenceManager pm; + + public JPoxJDO() { + if (isInitialized) { + return; + } + else { + initialize(); + } + + } + + private void initialize() { + + System.out.println("JpoxJDO, initialize called"); + getDatasourceProps(); + pm = createPersistenceManager(); + isInitialized = true; + return; + } + + // load all of the various JPOX properties from a properties file + + private void getDatasourceProps() { + InputStream is = this.getClass().getResourceAsStream(JPOX_CONFIG); + + prop = new Properties(); + try { + prop.load(is); + } catch (IOException exception) { + throw new RuntimeException("jpox.properties not found.", + exception); + } + } + + // create the PersistenceManager using the JDO Helper class + // the persistencemanage is used for all JPOX transactions + + private static PersistenceManager createPersistenceManager() { + + PersistenceManagerFactory pmf = JDOHelper + .getPersistenceManagerFactory(prop); + + return pmf.getPersistenceManager(); + + } + + // close the persistence manager. + + public void shutdown() { + if (pm != null) { + pm.close(); + } + + } + + // If the username is in the APP.USERS table retrieve + // the database row, which in JPOX is the class UserBean + + public UserBean getUserPassword(String userName) { + + UserBean userBean; + + Transaction txn = pm.currentTransaction(); + try { + txn.begin(); + // this represents the equivalent of the SQL query: + // select username, password from APP.USERS where username = ? + Query query = pm.newQuery(UserBean.class, "userName == username"); + query.declareParameters("String username"); + query.setUnique(true); + userBean = (UserBean) query.execute(userName.trim()); + pm.retrieve(userBean); + if (userBean == null) { + userBean = new UserBean(); + } + txn.commit(); + } finally { + if (txn.isActive()) { + txn.rollback(); + } + } + return userBean; + } + + // Insert a row into the APP.USERS table by first creating a + // UserBean, then using JPOX to persist the UserBean to Derby. + + public int insertUser(String firstName, String lastName, String userName, + String email, String password) { + + ... + + + // insert a row into the UserCreditCard table by first + // creating a UserCreditCardBean and then using JPOX + // to persist the data + + public int insertUserCreditCard(String lastname, String userName, + String creditCardType, String creditCardNum, String creditCardDisplay) { + + int success = 0; + UserCreditCardBean userCCBean = new UserCreditCardBean(lastname.trim(), + userName.trim(), creditCardType.trim(), creditCardNum.trim(), + creditCardDisplay.trim()); + + Transaction txn = pm.currentTransaction(); + try { + txn.begin(); + pm.makePersistent(userCCBean); + txn.commit(); + success = 1; + } finally { + if (txn.isActive()) { + txn.rollback(); + success = 0; + } + } + return success; + } + + // query for the Destination Airports of a City based on + // the Origin Airport of a flight + // return the data in the form of the JPOX enhanced class, + // CityBean + + public CityBean[] destAirports(String origAirport) { + + ... + + // query for all Cities in the APP.CITIES table + // returning an Array of CityBeans + + public CityBean[] cityList() { + + ... + + // return an array of FlightsBean which include a specific + // ORIG_AIRPORT and DEST_AIRPORT + + public FlightsBean[] origDestFlightList(String origAirport, + String destAirport, Date startDate) { + + ... + + // return the rows in the FlightHistory table based on the Username + // in the form of an array of FlightHistoryBeans + + public FlightHistoryBean[] fetchFlightHistory(String userName) { + + ... + + // insert into the UserFlightHistory table by creating + // the FlightHistoryBean and persisting it to Derby + + public int insertUserFlightHistory(String userName, FlightsBean flightsBean, + String creditCardType, String creditCardDisplay) { + + ... +} +

+

+Notice the use of the javax.jdo.Query and javax.jdo.Transaction +classes to create the queries and transactions used by JPOX. +

+

+Here is the properties file, jpox.properties, used by the JPoxJDO.java +class to set properties for JDO and JPOX. The Derby JDBC Embedded Driver is used for the JDBC Driver and the Derby Connection URL points to the +relative path to the airlinesDB database under the data directory. +

+

+Properties file to set the JPOX properties +

+

+javax.jdo.PersistenceManagerFactoryClass=org.jpox.PersistenceManagerFactoryImpl +org.jpox.autoCreateSchema=false +org.jpox.validateTables=false +org.jpox.validateConstraints=false +javax.jdo.option.NontransactionalRead=true +javax.jdo.option.ConnectionDriverName=org.apache.derby.jdbc.EmbeddedDriver +javax.jdo.option.ConnectionURL=jdbc:derby:data/airlinesDB +javax.jdo.option.ConnectionUserName=APP +javax.jdo.option.ConnectionPassword=mine +

+

+Prior to running the sample application below make sure the jpox.properties file is in the directory where the JPoxJDO class is since the jpox.properties file +is read at run time to initialize the JPoxJDO class. +

+
+ + + +

Step 9. Code the application class which calls the business logic class

+
+

+The DerbyJPox.java class calls the methods of the JPoxJDO.java class as you might in a sample application. +

+

+Partial Listing of DerbyJPox.java application class +

+

+package org.apache.derby.demo.application; + +public class DerbyJPox { + + public static void main(String[] args) { + JPoxJDO jpoxJDO = new JPoxJDO(); + UserBean userBean = jpoxJDO.getUserPassword("apacheu"); + + ... + + // Note, the user table has a primary key on username ... this insert + // will only work once. + + int success = jpoxJDO.insertUser("Susan", "Cline", "slc", + "slc@mycomp.org", "mypass"); + ... + + CityBean[] cityBeans = jpoxJDO.destAirports("ATH"); + ... + + FlightsBean flightsBean = new FlightsBean("AA1134", 1, "ATH", new Time(0), "AMS", + new Time(1), "B", 12.00, "1200", "B747", new Date()); + int success2 = jpoxJDO.insertUserFlightHistory("slc", flightsBean, + "visa", "4728-xxxx-xxxx-xxxx-4567"); + ... + + FlightHistoryBean[] flightHistoryBeans = jpoxJDO.fetchFlightHistory("slc"); + ... + jpoxJDO.shutdown(); + ... + } +} + +

+
+ + + +

Step 10. Compile all classes, enhance the persistence capable ones and run the application

+
+

+The instructions below show how to compile all classes and enhance the persistence-capable classes assuming the download file, jpox_derby.zip was unzipped to the C:/ directory on a windows machine. +

+

+ +Directory structure after unzipping jpox_derby.zip +

+

+C:\JPOX_Derby +| ++ --- data +| | +| + --- airlinesDB.sql +| + --- airlinesDB +| ++ --- src (the java source files) +| | +| + --- package.jdo +| + --- log4j.properties +| + --- org +| | +| + --- apache +| | +| + --- derby +| | +| + --- demo +| | +| + --- application +| | | +| | + --- DerbyJPox.java +| | | +| + --- beans +| | | +| | + --- model +| | | | +| | | + --- UserBean.java +| | | + --- UserCreditCardBean.java +| | | +| | + --- view +| | | | +| | | + --- CityBean.java +| | | + --- FlightHistoryBean.java +| | | + --- FlightsBean.java +| | | +| + --- persistence +| | | +| | + --- JPoxJDO.java +| | + --- jpox.properties +| +| +| +

+

+To make this example more straightforward, complete the following steps before proceeding to the next step. +

+
    + +
  • Create a lib and a bin directory under the \JPOX_Derby directory.
  • + +
  • Copy these six jar files to the lib directory. +
      + +
    • bcel-5.1.jar
    • + +
    • derby.jar
    • + +
    • jdo2-api-2.0-rc1.jar
    • + +
    • jpox-1.1.0-rc-1.jar
    • + +
    • jpox-enhancer-1.1.0-rc-1.jar
    • + +
    • log4j-1.2.12.jar
    • + +
    + +
  • + +
  • +Copy the log4j.properties file that is in the \JPOX_Derby\src directory to the \JPOX_Derby\bin directory. +
  • + +
  • +Copy the package.jdo file that is in the \JPOX_Derby\src directory to the \JPOX_Derby\bin directory. +
  • + +
+

Referring to the above directory structure as an example, first compile the classes that we will later make persistence capable. The compiled +classes need to go into the bin directory you just created.

+

+Note: In all of these examples make sure there are no spaces in the value for the classpath specified by the -cp flag in the java command. The spaces have been added for readability.

+

+ +Compiling the Java Data Objects + +

+

+C:\JPOX_Derby>javac -d bin src\org\apache\derby\demo\beans\model\*.java +src\org\apache\derby\demo\beans\view\*.java +

+

+Enhancing these classes using the JPOXEnhancer class +

+

+ +C:\JPOX_Derby>java -Dlog4j.configuration=file:src\log4j.properties -cp +lib\bcel-5.1.jar;lib\jpox-enhancer-1.1.0-rc-1.jar;lib\jpox-1.1.0-rc-1.jar; +lib\jdo2-api-2.0-rc1.jar;lib\log4j-1.2.12.jar;bin +org.jpox.enhancer.JPOXEnhancer src\package.jdo + +

+

+The output from enhancing these five classes +

+

+JPOX Enhancer (version 1.1.0-rc-1) : Enhancement of classes + +ENHANCED (PersistenceCapable) : org.apache.derby.demo.beans.view.CityBean +ENHANCED (PersistenceCapable) : org.apache.derby.demo.beans.view.FlightsBean +ENHANCED (PersistenceCapable) : org.apache.derby.demo.beans.view.FlightHistoryBe +an +ENHANCED (PersistenceCapable) : org.apache.derby.demo.beans.model.UserBean +ENHANCED (PersistenceCapable) : org.apache.derby.demo.beans.model.UserCreditCard +Bean +

+

Next, we'll compile both the business logic class, org.apache.derby.demo.persistence.JPoxJDO and the application class, org.apache.derby.demo.application.DerbyJPox. When compiling these two classes do not recompile the classes you just enhanced. Doing so, will "remove" the enhancement and cause the application to fail at runtime. +

+

+ +Compiling the business logic and application class + +

+

+C:\JPOX_Derby>javac -d bin -cp lib\jdo2-api-2.0-rc1.jar;lib\jpox-1.1.0-rc-1.jar; +bin src\org\apache\derby\demo\persistence\*.java +src\org\apache\derby\demo\application\*.java +

+

+We need to do one last step prior to running the application class. +Copy the jpox.properties file from the C:\JPOX_Derby\src\org\apache\derby\demo\persistence directory +to the C:\JPOX_Derby\bin\org\apache\derby\demo\persistence directory. +

+

Now we're ready to run the sample application. Use the command below to run the DerbyJPox.java class.

+

+ +Run the application class, DerbyJPox + +

+

+C:\JPOX_Derby>java -cp lib\jdo2-api-2.0-rc1.jar;lib\jpox-1.1.0-rc-1.jar; +lib\derby.jar;lib\log4j-1.2.12.jar;bin +org.apache.derby.demo.application.DerbyJPox +

+

The output from running the application class, DerbyJPox.java is shown below.

+

+ +Output from DerbyJPox + +

+

+JpoxJDO, initialize called +Issuing JPOX queries against the Derby DB, airlinesDB +*********************************************************** +Query 1: The UserBean corresponding to the username apacheu is: +firstname: apache lastname: user email: apacheu@mycompany.com +*********************************************************** +Insert 1: Create a new user by calling JPoxJDO.insertUser( +"Susan", "Cline", "slc", "slc@mycomp.org", "mypass") +Successfully inserted the user 'slc' into the database. +*********************************************************** +Query 2: Find the destination cities of flights from Athens. +Dest City: Amsterdam +Dest City: Cairo +Dest City: Istanbul +Dest City: Lagos +Dest City: London +Dest City: Paris +*********************************************************** +Insert 2: Create a FlightsHistoryBean by calling +JPoxJDO.insertUserFlightHistory +("slc", myFlightsBean, "visa", "4728-xxxx-xxxx-xxxx-4567") +Successfully inserted a row into the FlightHistory table. +*********************************************************** +Query 3: Select the row from the FlightHistory table based on username slc +by calling JPoxJDO.fetchFlightHistory("slc") +Flight: AA1134 Orig Airport: ATH Dest: AMS Credit Crd: 4728-xxxx-xxxx-xxxx-4567 +*********************************************************** +Shutting down JPOX persistence manager. +*********************************************************** +

+
+ + + +

Resources and Acknowledgements

+
+

+The Derby web site and wiki are the best sources of information about Derby. +

+

For in-depth information about JPOX see the JPOX web site. + +Apache JDO provides the JD0 2.0 API which is available from the Apache JDO web site. JPOX JDO provides the reference implementation of the JDO 2.0 specification via the JPOX JDO 1.1 release.

+

The JPOX 1.1 Tutorial is vital to get up to speed with JPOX JDO. +

+

Many thanks to Michelle Caisse and Craig Russell of the Apache JDO project in helping me with my "newbie" questions on configuring JPOX with Derby and general JDO questions.

+

Susan Cline wrote this paper and would appreciate any feedback +in the form of suggestions, corrections or questions about it by posting to the +derby-user mailing list. +

+
+ + +

+Last updated: March 8, 2006 +

+ + +
+ +
 
+
+ + +