Applications with a Web-based presentation layer can use JDO in at least two different ways:
The second architecture is straightforward: The business logic is in plain old Java objects (POJO) co-located to the presentation tier . The business logic and the presentation layer (Servlets and JSP) can use the JDO API directly. In a Model-View-Controller (MVC) architecture as often used in today's Web-based applications, two variations are possible with JDO:
Some of the questions that can arise in using the JDO and Servlet API together (with both MVC approaches), which are briefly addressed in the next few paragraphs, include the following:
Regarding the two different transaction types and other transaction configurations that JDO supports, one particular combination is often used and makes sense in the type of Web applications described here: Using optimistic transactions for write access and a PersistenceManager with non-transactional read for read-only access for display. This configuration allows a JDO implementation to optimally leverage the PersistenceManagerFactory (PMF) global in-memory cache and generally leads to good performance and scalability. For example, the MVC Actions can start and commit transactions, while the Views (in an MVC Pull model) can use non-transactional reads. The PersistenceManagerFactory can be initialized and looked up in two ways in Servlet applications: Either an application (or proprietary framework) specific "helper" class creates, configures and holds onto the PMF. This allows Servlets to use this helper class to obtain a new PersistenceManager when required. Or, alternatively, a Servlet application could also leverage JDO's J2EE integration and obtain a new PersistenceManager from a PMF bound into JNDI by the respective JCA adapter. This allows Servlet applications to use a shared transaction across JDO, JDBC, JMS, and so on, as described in Chapter 11. Of course, all this is no different from what has been described earlier in this book, the classical managed and unmanaged JDO scenarios. After a PersistenceManager is obtained, there are two possible architectures:
The second approach can appear to make application development somewhat easier. In this case, persistent objects (e.g., Query results) can be directly stored into the session as well, see below. However, because a PersistenceManager is not serializable (only a PersistenceManagerFactory is) this architecture actually prevents "distributable" Web applications for load-balancing and fail-over on clusters. It is recommended only for relatively simple applications with no need for session passivation and replication. A related issue is the one of storing persistent objects as attributes into the session, if the PersistenceManager is in the session. Again, persistent objects are not generally serializable for session replication; see the respective discussion in Chapter 9. It is generally preferable and possible to store only identities of persistent objects into the session using PersistenceManager.getObjectId() and then retrieve the object in the next request via PersistenceManager.getObjectById() . This is conceptually similar to what was discussed in Chapter 5 for stateful session beans. Alternatively, a similar but completely stateless architecture can be used if JDO identities are passed only via URL and hidden HTML FORM INPUT fields. In this scenario, the JDO identity is converted to and from String via PersistenceManager.getObjectId().toString() and PersistenceManager.NewObjectIdInstance() . It is worth noting that obtaining a PersistenceManager for each request and looking up objects via identities (as opposed to storing the PersistenceManager and persistent objects in the session) does not necessarily lead to less performance. A good JDO implementation reuses instances and ideally does not require underlying datastore access because of caching when looking up objects via a stored identity. |