Identify correct and incorrect statements or examples about container-managed persistence contexts.

[Note]

When a container-managed entity manager is used, the lifecycle of the persistence context is always managed AUTOMATICALLY, transparently to the application, and the persistence context is propagated with the JTA transaction.

A container-managed persistence context may be defined to have either a lifetime that is scoped to a SINGLE transaction or an EXTENDED lifetime that spans MULTIPLE transactions, depending on the PersistenceContextType that is specified when its EntityManager is created. This specification refers to such persistence contexts as transaction-scoped persistence contexts and extended persistence contexts respectively.

The lifetime of the persistence context is declared using the PersistenceContext annotation or the persistence-context-ref deployment descriptor element. By DEFAULT, a transaction-scoped persistence context is used.

Container-managed Transaction-scoped Persistence Context

The application may obtain a container-managed entity manager with transaction-scoped persistence context bound to the JTA transaction by injection or direct lookup in the JNDI namespace. The persistence context type for the entity manager is defaulted or defined as PersistenceContextType.TRANSACTION.

A new persistence context begins when the container-managed entity manager is invoked in the scope of an active JTA transaction, and there is no current persistence context already associated with the JTA transaction. The persistence context is created and then associated with the JTA transaction.

The persistence context ends when the associated JTA transaction commits or rolls back, and all entities that were managed by the EntityManager become detached.

If the entity manager is invoked outside the scope of a transaction, any entities loaded from the database will immediately become detached at the end of the method call.

Example:

@Stateless
public class ShoppingCartImpl implements ShoppingCart {

	@PersistenceContext 
	EntityManager em;

	public Order getOrder(Long id) {
		return em.find(Order.class, id);
	}
	
	public Product getProduct(String name) {
		return (Product) em.createQuery("select p from Product p where p.name = :name")
			.setParameter("name", name)
			.getSingleResult();
	}

	public LineItem createLineItem(Order order, Product product, int quantity) {
		LineItem li = new LineItem(order, product, quantity);
		order.getLineItems().add(li);
		em.persist(li);
		return li;
	}
}
					

Under the transaction persistence context model, an EntityManager begins a new persistence context with each transaction, and ends the context when the transaction commits or rolls back. Within the transaction, entities you retrieve through the EntityManager or via Queries are managed entities. They can access datastore resources to lazy-load additional persistent state as needed, and only one entity may exist for any persistent identity.

When the transaction completes, all entities lose their association with the EntityManager and become detached. Traversing a persistent field that wasn't already loaded now has undefined results. And using the EntityManager or a Query to retrieve additional objects may now create new instances with the same persistent identities as detached instances.

If you use an EntityManager with a transaction persistence context model outside of an active transaction, each method invocation creates a new persistence context, performs the method action, and ends the persistence context. For example, consider using the EntityManager.find(...) method outside of a transaction. The EntityManager will create a temporary persistence context, perform the find(...) operation, end the persistence context, and return the detached result object to you. A second call with the same id will return a second detached object.

When the next transaction begins, the EntityManager will begin a new persistence context, and will again start returning managed entities. You can also merge the previously-detached entites back into the new persistence context.

The following code illustrates the behavior of entites under an EntityManager using a transaction persistence context:


EntityManager em; // injected
...

// outside a transaction:

// each operation occurs in a separate persistence context, and returns 
// a new detached instance
Magazine mag1 = em.find(Magazine.class, magId);
Magazine mag2 = em.find(Magazine.class, magId);
assertTrue(mag2 != mag1);
...

// transaction begins:

// within a transaction, a subsequent lookup doesn't return any of the
// detached objects.  however, two lookups within the same transaction
// return the same instance, because the persistence context spans the
// transaction
Magazine mag3 = em.find(Magazine.class, magId);
assertTrue(mag3 != mag1 && mag3 != mag2);
Magazine mag4 = em.find(Magazine.class (magId);
assertTrue(mag4 == mag3);
...

// transaction commits:

// once again, each operation returns a new instance
Magazine mag5 = em.find(Magazine.class, magId);
assertTrue(mag5 != mag3);

					

Container-managed Extended Persistence Context

A container-managed EXTENDED persistence context can ONLY be initiated within the scope of a stateful session bean. It exists from the point at which the stateful session bean that declares a dependency on an entity manager of type PersistenceContextType.EXTENDED is created, and is said to be bound to the stateful session bean. The dependency on the extended persistence context is declared by means of the PersistenceContext annotation or persistence-context-ref deployment descriptor element.

The persistence context is closed by the container when the @Remove method of the stateful session bean completes (or the stateful session bean instance is otherwise destroyed).

Example:

@Stateful
@Transaction(REQUIRES_NEW)
public class ShoppingCartImpl implements ShoppingCart {

	@PersistenceContext(type=EXTENDED)
	EntityManager em;

	private Order order;

	private Product product;

	public void initOrder(Long id) {
		order = em.find(Order.class, id);
	}
	
	public void initProduct(String name) {
		product = (Product) em.createQuery("select p from Product p where p.name = :name")
			.setParameter("name", name)
			.getSingleResult();
	}

	public LineItem createLineItem(int quantity) {
		LineItem li = new LineItem(order, product, quantity);
		order.getLineItems().add(li);
		return li;
	}
}
					

An EntityManager using an extended persistence context maintains the same persistence context for its entire lifecycle. Whether inside a transaction or not, all entities returned from the EntityManager are MANAGED, and the EntityManager never creates two entity instances to represent the same persistent identity. Entities only become detached when you finally close the EntityManager (or when they are serialized).

The following code illustrates the behavior of entites under an EntityManager using an extended persistence context:

EntityManagerFactory emf = ...
EntityManager em = emf.createEntityManager();

// persistence context active for entire life of EM, so only one entity
// for a given persistent identity
Magazine mag1 = em.find(Magazine.class, magId);
Magazine mag2 = em.find(Magazine.class, magId);
assertTrue(mag2 == mag1);

em.getTransaction().begin();

// same persistence context active within the transaction
Magazine mag3 = em.find(Magazine.class, magId);
assertTrue(mag3 == mag1);
Magazine mag4 = em.find(Magazine.class (magId);
assertTrue(mag4 == mag1);

em.getTransaction.commit ();

// when the transaction commits, instance still managed
Magazine mag5 = em.find(Magazine.class, magId);
assertTrue(mag5 == mag1);

// instance finally becomes detached when EM closes
em.close();
					

Professional hosting     Belorussian informational portal         Free SCWCD 1.4 Study Guide     Free SCDJWS 1.4 Study Guide     SCDJWS 1.4 Quiz     Free IBM Certified Associate Developer Study Guide     IBM Test 000-287. Enterprise Application Development with IBM WebSphere Studio, V5.0 Study Guide     Free Mock Exam Engine