4.7. Code Notes and J2EE Tips
Prev | Chapter 4. J2EE Tutorial | Next

## 4.7. Code Notes and J2EE Tips

1. JDO 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 persistence manager, it allows the JDO implementation to free up unused resources. Since a persistence manager 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 persistence manager 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 funcationality 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. Persistence managers are allocation on a per-Transaction basis. Calling `getPersistenceManager` from the same persistence manager factory within the same EJB method call will always return the same instance.

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

Prev | Up | Next
4.6. Sample Architecture | Home | Part IV. Kodo JDO Frequently Asked Questions