by Mahesh Kannan The Java Persistence Architecture, a part of the Enterprise JavaBeans 3.0 (EJB 3.0) specification, simplified the development of EJB applications using data persistence. A major simplification was the introduction of the EntityManager interface for accessing a database and creating, removing, or updating entities within a transaction. Entities are objects that represent data in a database. They are persistent in the sense that they exist even after the application that created them ends. To foster entity persistence an entity manager interacts with the persistence context, which the Java Persistence Architecture defines as: A set of managed entity instances in which for any persistent entity identity there is a unique entity instance. Within the persistence context, the entity instances and their lifecycle are managed by the entity manager. The Java Persistence Architecture also states that a container-managed persistence context, that is, a persistence context whose life cycle is managed automatically by the container, may be defined to have either a lifetime that is scoped to a single transaction or an extended lifetime that spans multiple transactions. The lifetime scope depends on the type specified in the PersistenceContextType class when an entity manager is created. In the case of a container-managed persistence context that is scoped to a single transaction, the persistence context ends when an associated transaction commits or is rolled back through the Java Transaction API (JTA). By comparison, a container-managed persistence context that has an extended lifetime begins when a stateful session bean is created and ends only when the stateful session bean is removed from the container. The extended persistence context is said to be bound to the stateful session bean. Note that only stateful session beans can have a container-managed, extended entity manager. One of the important distinctions between a transaction-scoped persistence context and that of an extended persistence context is the state of the entities after a transaction completes. In the case of a transaction-scoped persistence context, the entities become detached, that is, they are no longer managed. In the case of an extended persistence context, the entities remain managed. In other words, all operations, such as persist, that are done outside of a transaction are queued and committed when the persistence context is attached to a transaction (and when it commits). This makes an extended persistence context ideal for modeling a conversation with a user that spans many interactions. You can accomplish the same thing with a bean-managed transaction that spans the entire user conversation. You start this transaction with the UserTransaction.begin() method. However, this alternate approach is more complicated than taking advantage of an extended persistence context. This Tech Tip illustrates an application that uses a stateful session bean and an entity manager with an extended persistence context. The application handles travel reservations — it allows a user to book airplane flight and rental car reservations for a trip. A sample package accompanies the tip. The code examples in the tip are taken from the source code of the sample (which is included in the package). A Trip Reservation Application The application for this tip presents a simple web page that allows a user to make trip reservations. A trip reservation involves booking airline or car reservations for the trip. A user makes a trip reservation by specifying a departure and destination location, selecting the dates for the trip, and then choosing an airline or a car. The user then selects the Book It button to confirm the booking of a rental car or airplane flight, respectively. The user can make multiple bookings for the trip. The user then confirms his or her selections by clicking the Confirm button. If you examine the source code for the application, you’ll notice that a servlet, ControllerServlet, presents the reservation web page. The servlet uses a stateful session bean, BookingControllerLocalBean, to maintain the conversational state of the application. The stateful session bean uses a container-managed extended persistence context to manage the entities. Note that the default transaction attribute for all methods other than confirmBooking() in the application is NOT_SUPPORTED. The following code in BookingControllerLocalBean injects a container-managed extended persistence scope: @PersistenceContext(type=PersistenceContextType.EXTENDED) private EntityManager em; Beginning a Trip Reservation The servlet begins the trip reservation process by calling the startBooking() method in BookingControllerLocalBean. Here’s the call in the servlet to the method: bookingController = (BookingControllerLocal) (new InitialContext()).lookup("java:comp/env/ejb/BookingController"); session.setAttribute("bc", bookingController); tripId = bookingController.startBooking(); And here is the startBooking() method in BookingControllerLocalBean: public Trip startBooking() { this.trip = new Trip(); // Create a new Trip em.persist(trip); return trip(); //Return the Trip which is an Entity } Again note that because this application uses an extended persistence context, the entity Trip remains managed even though the methods are called without a transaction. Handling Flight and Car Reservations When the user requests a flight or a car reservation, the servlet calls the doBooking(Booking b) method in BookingControllerLocalBean. This method calls the em.persist method to make the entity persistent. The method then adds the Booking entity to the Trip entity as follows: trip.getBookings().add(b); b.setTrip(trip); Note that the doBooking() method is not called within a transaction. Because of that, the entities are not flushed to the database, but rather remain managed by the entity manager. This makes it possible to modify the Booking object even after the doBooking() method is called. By comparison, if this application used a transaction-scoped entity manager , it would have to call em.merge() at the beginning of the next transaction to again have the entity manager manage the entity. However, because the application uses an entity manager with extended persistence scope the entities remain managed even after a transaction commits. Here is the complete code for the doCarBooking() method: public void doBooking(Booking b) { em.persist(b); trip.getBookings().add(b); b.setTrip(trip); } Displaying the State of a Trip Reservation The servlet displays all the Booking entities in a trip by calling the bean’s getAllBooking() method in BookingControllerLocalBean. This method does not fetch data from the database. Instead it fetches the collection of Booking entities within the Trip entity. Here is the code for the getAllBooking() method. . public List<Booking>getAllBookings() { return trip.getBookings(); } Completing the Trip Reservation When the user clicks the Confirm button, the servlet calls the confirmTrip() method in BookingControllerLocalBean. This method doesn’t do anything: @TransactionAttribute(TransactionAttributeType.REQUIRED) public void confirmTrip() { em.flush(); } However, because the method executes within a transaction, the container automatically associates the extended persistence manager with the transaction. When the method completes, the container commits the transaction and the entity manager flushes the entity’s state to the database. Running the Sample Code A sample package accompanies this tip. To install and run the sample: Download the sample package and extract its contents. You should see an enterprise archive named techtip3.ear. If you haven’t already done so, download and install GlassFish v2. Start GlassFish v2 by entering the following command on a command line: <glassfish_install_dir>/bin/asadmin start-domain Where <glassfish_install_dir> is the directory in which you installed GlassFish v2. Start the Java DB database server that is packaged with GlassFish v2 by entering the following command on a command line: <glassfish_install_dir>/bin/asadmin start-database Where <glassfish_install_dir> is the directory in which you installed GlassFish v2. Deploy techtip3.ear in GlassFish v2. You can do this various ways. One way is to enter the following command on a command line: <glassfish_install_dir>/bin/asadmin deploy techtip3.ear Open your browser to the following URL: https://localhost:8080/techtip3-war/TripController. You should see the trip reservation web page. Summary This tip showed an example that uses a container-managed entity manager with an extended persistence context to a handle a long conversation that spans multiple interactions with a user. The example also showed that intermediate user interactions do not have to be handled within a transaction, and how this type of entity manager is flushed when the transaction completes. About the Author Mahesh Kannan is member of the EJB container team. He has been involved with Java EE development for the last 7 years. —————————————————————————————————————————————————————————- Connect and Participate With GlassFish Try GlassFish for a chance to win an iPhone. This sweepstakes ends on March 23, 2008. Submit your entry today. Java