2.4. J2EE Tutorial
Prev | Chapter 2. JDO Tutorials | Next

## 2.4. J2EE Tutorial

By deploying Kodo into a J2EE environment, you can maintain the simplicity and performance of Kodo, while leveraging J2EE technologies such as container managed transactions (JTA/JTS), enterprise objects with remote invocation (EJB), and managed deployment of multi-tiered applications via an application server. This tutorial will demonstrate how to deploy Kodo-based J2EE applications and showcase some basic enterprise JDO design techniques. The tutorial's sample application attempts to model a basic garage catalog system. While the application is relatively trivial, the code has been constructed to illustrate simple patterns and solutions to common problems when using Kodo in an enterprise environment.

### 2.4.1. Prerequisites for the Kodo J2EE Tutorial

This tutorial assumes that you have installed Kodo and setup your classpath according to the installation instructions appropriate for your platform. In addition, this tutorial requires that you have installed and configured a J2EE-compliant application server, such as JBoss, WebSphere, WebLogic, Borland Enterprise Server, JRun, or SunONE / Sun JES. If you use a different application server, this tutorial may be adaptable to your application server with small changes; refer to your application server's documentation for any specific classpath and deployment descriptor requirements.

This tutorial assumes a reasonable level of experience with Kodo and JDO. We provide a number of other tutorials for basic Kodo and JDO concepts, including enhancement, schema mapping, and configuration. This tutorial also assumes a basic level of experience with J2EE components, including EJB, JNDI, JSP, and EAR/WAR/JAR packaging. Sun and/or your application server company may provide tutorials to get familiar with these components.

In addition, this tutorial uses Ant to build the deployment archives. While this is the preferred way of building a deployment of the tutorial, one can easily build the appropriate JAR, WAR, and EAR files by hand, although that is outside the scope of this document.

### 2.4.2. J2EE Installation Types

Every application server has a different installation process for installing J2EE components. Kodo can be installed in a number of ways, each of which may or may not be appropriate to your application server. While this document focuses mainly upon using Kodo as a JCA resource, there are other ways to use Kodo in a J2EE environment.

- `JCA`: Kodo implements the JCA 1.0 spec, and the kodo-jdo.rar file that comes in the `jca` directory of the distribution can be installed as any other JCA connection resource. This is the preferred way to integrate Kodo into a J2EE environment. It allows for simple installation (usually involving uploading or copying kodo-jdo.rar into the application server), guided configuration on many appservers, as well as dynamic reloading for upgrading Kodo to a newer version. The drawback is that older application servers have flaky or non- existent JCA support as the spec is relatively new.

- `PersistenceManagerFactoryImpl`: This remains the most compatible way to integrate Kodo into a J2EE environment, though this is not seamless and can require a fair bit of custom application server code to manually bind an instance of `PersistenceManagerFactoryImpl` into the JNDI tree. This is somewhat offset by avoiding JCA configuration issues as well as being able to tailor the binding and start-up process.

### 2.4.3. Installing Kodo

Section 8.1.3.4, “Kodo JDO JCA Deployment” goes over the steps to install Kodo on your application server of choice via the Java Connector Architecture (JCA). If your application server does not support JCA, see Section 8.1.4, “Non-JCA Application Server Deployment” and Section 8.1.1, “Standalone Deployment” for other installation options.

### 2.4.4. Installing the J2EE Sample Application

Installing the sample application involves first compiling and building a deployment archive (.ear) file. This file then needs to be deployed into your application server.

#### 2.4.4.1. Compiling and Building The Sample Application

Navigate to the `samples/jdo/j2ee` directory of your Kodo installation. Compile the source files in place both in this base directory as well as the nested `ejb` directory:

    javac *.java  ejb/*.java

Enhance the Car class.

    kodoc -p jdo.properties package.jdo

Run the mapping tool; make sure that your `META-INF/jdo.properties` file includes the same connection information (e.g. Driver, URL, etc.) as your installation:

    mappingtool -p jdo.properties package.jdo

Configure options in `samples.properties` to match your JCA installation, most notably the JNDI name to which you have bound Kodo (it defaults to kodo).

| Warning
This step (editing `samples.properties`) is very important as this value can be quite different for each appserver and each configuration. Be sure that the setting you put for `pmf.jndi` matches not only your configured setting but also what your application server may prefix the configured name with. JBoss, for example, will prefix the JNDI name with `java:/` and Borland Enterprise Server looks at the `serial://` context. Refer to your JNDI tree and the documentation for your application server for further details.

Build an J2EE application archive by running Ant against the `build.xml`. This will create `samplej2ee.ear`. This ear can now be deployed to your appserver.

    ant -f build.xml

#### 2.4.4.2. Deploying Sample To JBoss

Place the ear file in the `deploy` directory of your JBoss installation. You can use the above hints to view the JNDI tree to see if `samples.jdo.j2ee.ejb.CarHome` was deployed to JNDI.

#### 2.4.4.3. Deploying Sample To WebLogic 6.1 to 7.x

Place the ear file in the `applications` directory of your WebLogic domain. Production mode (see your startWebLogic.sh/cmd file) should be set to false to enable auto-deployment. If the application was installed correctly, you should see `sample-ejb` listed in the Deployments/EJB section of the admin console. In addition you should find `CarHome` listed in the JNDI tree under `myserver->samples->j2ee->ejb` .

#### 2.4.4.4. Deploying Sample To WebLogic 8.1

Create a new directory named `samplej2ee.ear` in the `applications` directory of your WebLogic domain. Extract the EAR file (without copying the EAR file) to this new directory:

    applications> mkdir samplej2ee.ear
    applications> cd samplej2ee.ear
    samplej2ee.ear> jar -xvf /path/to/samplej2ee.ear

Deploy the application by using the admin console (Deployments -> Applications -> Deploy a new Application. Select `samplej2ee.ear` and deploy to the proper server targets. If you have installed the application correctly, you should find CarHome listed in the JNDI tree under `myserver->samples->j2ee->ejb` .

#### 2.4.4.5. Deploying Sample To SunONE / Sun JES

Browse to the admin console in your web browser. Select `Applications/ Enterprise Applications` from the left navigation panel. Select `Deploy...` and in the following screen upload the `samplej2ee.ear` file to the server. Apply your changes by selecting the link in the upper right portion of the page. You should now see `samplej2ee` listed in the Enterprise Applications folder of the navigation panel.

#### 2.4.4.6. Deploying Sample To JRun

Browse to the admin console in your web browser. Select `J2EE Components` from the left navigation panel. Select `Add` under the `Enterprise Applications` heading. Select the `samplej2ee.ear` file and hit `Deploy`. You should now see `Sample-KodoJ2EE` listed in the top-level folder of the navigation panel. Select it, and then select the `sample-ejb.jar#CarEJB` component under `Enterprise JavaBeans` section, then change the `JNDI Name` for the bean from the default value to `samples.jdo.j2ee.ejb.CarHome` and hit `Apply`.

If the Kodo resource adapter and the sample EAR are both configured correctly, you should now be able to access your sample application at JRun's deploy URL (e.g., `http://localhost:8100/sample/`).

#### 2.4.4.7. Deploying Sample To WebSphere

Browse to the admin console in your web browser. Select `Applications / Install New Application` from the left navigation panel. Select the path to your `samplej2ee.ear` file and press `Next`.

On the following screen, leave the options at the default and select `Next`. On the following screen (`Install New Application->Step 1` ), ensure that the `Deploy EJBs` option is checked. Leave other options at their defaults.

Move on to Step 2. On this screen enter `samples.jdo.j2ee.ejb.CarHome` as the JNDI name for the `Car` EJB. Continue through the remaining steps leaving options at the defaults. Select `Finish` and ensure that the application is deployed correctly.

Save the changes to the domain configuration by either selecting the `Save` link that appears after the installation is complete or by selecting `Save` from the top menu.

To verify your installation, select `Applications / Enterprise Applications` from the left navigation panel. `Sample-KodoJ2EE` should be listed in the list. If the application has not started already, select the checkbox next to `Sample-KodoJ2EE` and select `Start`.

#### 2.4.4.8. Deploying Sample To Borland Enterprise Server 5.2

Deploy the EAR file using iastool or the console. Note that you may have to include the JDO library in your stub generation process. Also be sure that you have followed the JCA instructions for BES as well as editing the samples.properties to point to `serial://kodo` JNDI location. You should be able to see the CarEJB located in JNDI located at the home classname.

### 2.4.5. Using The Sample Application

The sample application installs itself into the web layer at the context root of sample. By browsing to `http://yourserver:yourport/sample` , you should be presented with a simple list page with no cars. You can edit, add, delete car instances. In addition, you can query on the underlying `Car` `PersistenceCapable` instance by passing in a JDOQL query into the marked form (such as `model=="Some Model"`).

### 2.4.6. Sample Architecture

The garage application is a simple enterprise application that demonstrates some of the basic concepts necessary when using Kodo in the enterprise layer.

The core model wraps a stateless session bean facade around a persistence capable instance. Using a session bean provides both a remote interface for various clients as well as providing a transactional context in which to work (and thus avoiding any explicit transactional code).

This session bean uses the Data Transfer Object pattern to provide the primary communication between the application server and the (remote) client. The `Car` instance will be used as the primary object upon which the client will work.

This model can be easily adapted to using entity beans. See our sample `ejb` directory and `JDOEntityBean` for more details on how to using JDO to power your entity beans.

- `samples/jdo/j2ee/Car.java`: The core of the sample application. This is the persistence capable class that Kodo will use to persist the application data. Instances of this class will also fill the role of data transfer object (DTO) for EJB clients. To accomplish this, `Car` implements `java.io.Serializable` so that remote clients can access cars as parameters and return values from the EJB.

- `samples/jdo/j2ee/package.jdo`: The JDO metadata file for the package. Note that some appservers have a problem with the way we include an internal DTD. If you see a lot of illegal/malformed character exceptions, uncomment out the DTD declaration in this file.

- `samples/jdo/j2ee/SampleUtilities.java`: This is a simple facade to aggregate some core JDO functionality into some static methods. By placing all of the functionality into a single facade class, we can reduce code maintenance, as well as having the added advantage of being able to access Kodo from other portions of the application such as a servlet or JSP (though this functionality is not demonstrated in this sample). In addition, some simple utility functions such as JNDI helper methods are also in this class.

- `samples/jdo/j2ee/ejb/Car*.java`: The source for the `CarEJB` session bean. Clients can use the `CarHome` and `CarRemote` interfaces to find, manipulate, and persist changes to `Car` transfer object instances. By using J2EE transactional features, the implementation code in `CarBean.java` can be focused almost entirely upon business and persistence logic without worrying about transactions.

- `samples/jdo/j2ee/jsp/*.jsp`: The web presentation client. These JSPs are not aware of JDO; they simply use the `CarEJB` session bean and the `Car` transfer object to do all the work.

- `samples/jdo/j2ee/resources/*`: Files required to deploy to the various appservers, including J2EE deployment descriptors, WAR/ EJB/ EAR descriptors, as well as appserver specific files.

- `samples/jdo/j2ee/build.xml`: A simple Ant build file to help in creating a J2EE EAR file.

- `samples/jdo/j2ee/samples.properties`: A simple `.properties` file to tailor the sample application to your particular appserver and installation.

### 2.4.7. Code Notes and J2EE Tips

1. Persistence capable instances are excellent candidates for the Data Transfer Object Pattern. This pattern attempts to reduce network load, as well as group business logic into concise units. For example, `CarBean.edit` allows you to ensure that all values are correct before committing a transaction, instead of sequentially calling getters and setters on the session facade. This is especially true when using RMI such as from a Swing based application connecting to an application server.

   `CarEJB` works as a session bean facade to demarcate transactions, provide finder methods, and encapsulate complex business logic at the server level.

2. Persistent instances using datastore identity lose all identity upon serialization (which happens when they are returned from an EJB method). While there are numerous ways to solve this problem, the sample uses the `clientId` field of `Car` to store the stringified datastore id. Note that this field is not persistent. This field ensures that the client and EJB always share the same identity for a given car instance.

   | Note
   Note that this situation is slightly different for application identity. While persistent instances under application-identity still lose their id instance, recreating it from the server side is trivial as the fields on which it is based are still available.

   Other ways of solving this problem include:

   - Transmitting the object id first or otherwise storing identity with the client:

         Object oid = dogRemote.findByQuery ("// some query");
         Dog dog = dogRemote.getDogForOid (oid);
         // changes happen to dog
         dogRemote.save (oid, dog);

   - Wrapper objects that store the persistent instance, object id instance, as well as potentially other application-specific data:

         public class DogTransferObject
         {
             private Dog dog;
             private Object oid;
             private String authentication; // some application specific client data
         }

3. `PersistenceManager.close` should be called at the end of every EJB method. In addition to ensuring that your code will not attempt to access a closed `PersistenceManager`, it allows the JDO implementation to free up unused resources. Since a `PersistenceManager` is created for every transaction, this can increase the scalability of your application.

4. You should not use `PersistenceManager.currentTransaction` or any `javax.jdo.Transaction` methods. Instead, use the JTA transactional API. `SampleUtilities` includes a helper method to obtain a `UserTransaction` instance from JNDI (see your application server's documentation on the proper JNDI lookup).

5. While serialization of PC instances is relatively straightforward, there are several things to keep in mind:

   - Collections and iterators returned from `Query` instances become closed and inaccessible upon method close. If the client is receiving the results of a `Query`, such as in `CarBean.query`, the results should be transferred to another fresh collection instance before being returned from the server.

   - While "default fetch group" values will always be returned to the client upon serialization, lazily loaded fields will not as the `PersistenceManager` will have been closed before those fields attempt to serialize. One can either simply access those fields before serialization, or one can use the persistence mangaer's `retrieve` and `retrieveAll` methods to make sure object state is loaded. Note that these methods are not recursive. If you need to go through multiple relations, you must call `retrieve` at each relational depth. This is an intentional limitation in the specification to prevent the entire object graph from being serialized and/or retrieved.

6. It is not necessarily required that you use EJBs and container-managed transactions to demarcate transactions, although that is probably the most common method. In EJBs using bean managed transactions, you can control transactions through either the `javax.jdo.Transaction` or the `javax.transaction.UserTransaction`. Furthermore, outside of EJBs you can access the JDO layer with either transactional API.

7. The Kodo distribution includes source code for some convenient base classes that encapsulate much of the code that is laid out in this example for clarity. `JDOBean`, `JDOSessionBean`, and `JDOEntityBean` include most of the functionality of `SampleUtilities`, and handle common EJB interface methods such as `setEntityContext`. To use these classes, we recommend placing Kodo's jars into the system classpath and not into the ear. Ear deployment can cause classloader problems due to the multiple locations that these classes could be loaded from.

8. `PersistenceManager`s are allocated on a per-Transaction basis. Calling `getPersistenceManager` from the same `PersistenceManagerFactory` within the same EJB method call will always return the same instance.

       SamplesUtilities.getPersistenceManager ()
           == SampleUtilities.getPersistenceManager (); // will always be true

Prev | Up | Next
2.3. Reverse Mapping Tool Tutorial | Home | Part 5. Kodo Frequently Asked Questions