001: package org.vraptor.plugin.jpa;
002:
003: import java.text.MessageFormat;
004: import java.util.HashMap;
005: import java.util.Map;
006:
007: import javax.persistence.EntityManager;
008: import javax.persistence.EntityManagerFactory;
009: import javax.persistence.EntityTransaction;
010: import javax.persistence.Persistence;
011:
012: import org.apache.log4j.Logger;
013: import org.vraptor.Interceptor;
014: import org.vraptor.LogicException;
015: import org.vraptor.LogicFlow;
016: import org.vraptor.annotations.Out;
017: import org.vraptor.component.ComponentType;
018: import org.vraptor.component.LogicMethod;
019: import org.vraptor.scope.ScopeType;
020: import org.vraptor.view.ViewException;
021:
022: /**
023: * Manages the {@link EntityManager} and transactions lifecycle, in a
024: * request-based manner
025: *
026: * @author Fabio Kung
027: * @since 2.3.2
028: */
029: public class JavaPersistenceInterceptor implements Interceptor {
030: private static final Logger LOG = Logger
031: .getLogger(JavaPersistenceInterceptor.class);
032:
033: private static final Map<String, EntityManagerFactory> FACTORIES = new HashMap<String, EntityManagerFactory>();
034:
035: private EntityManager entityManager;
036:
037: private final EntityManagerIntrospector introspector = new EntityManagerIntrospector();
038:
039: public void intercept(LogicFlow flow) throws LogicException,
040: ViewException {
041: ComponentType componentType = flow.getLogicRequest()
042: .getLogicDefinition().getComponentType();
043: LogicMethod logicMethod = flow.getLogicRequest()
044: .getLogicDefinition().getLogicMethod();
045: LOG.debug(MessageFormat.format(
046: "Preparing PersistenceContext for: {0}", componentType
047: .getName()));
048:
049: String persistenceUnitName = introspector
050: .getPersistenceUnitName(componentType);
051: LOG
052: .debug(MessageFormat
053: .format(
054: "Retrieving the EntityManagerFactory for the PersistenceUnit: {0}.",
055: persistenceUnitName));
056: EntityManagerFactory factory;
057: synchronized (FACTORIES) {
058: factory = FACTORIES.get(persistenceUnitName);
059: if (factory == null) {
060: LOG
061: .debug(MessageFormat
062: .format(
063: "EntityManagerFactory not yet built. Creating one for PersistenceUnit {0}.",
064: persistenceUnitName));
065: factory = Persistence
066: .createEntityManagerFactory(persistenceUnitName);
067: FACTORIES.put(persistenceUnitName, factory);
068: }
069: }
070:
071: LOG.info("Creating an EntityManager for the request...");
072: EntityManager original = factory.createEntityManager();
073: this .entityManager = wrap(original);
074:
075: try {
076: boolean transactionRequired = this .introspector
077: .isTransactionRequired(logicMethod);
078: if (transactionRequired) {
079: original.getTransaction().begin();
080: }
081: flow.execute();
082: if (transactionRequired
083: && original.getTransaction().isActive()
084: && !original.getTransaction().getRollbackOnly()) {
085: original.getTransaction().commit();
086: }
087: } catch (Throwable t) {
088: EntityTransaction transaction = original.getTransaction();
089: if (transaction != null && transaction.isActive()) {
090: LOG
091: .error("Problem ocurred. The transaction will be rolled back.");
092: transaction.rollback();
093: }
094: throw new LogicException(
095: "An error was ocurred. If there were a transaction, it was rolled back.",
096: t);
097: } finally {
098: LOG.info("Closing the request EntityManager");
099: original.close();
100: }
101: }
102:
103: private EntityManager wrap(EntityManager entityManager) {
104: LOG
105: .trace("Wrapping the original EntityManager in the VRaptorEntityManager (with close and joinTransaction disabled).");
106: return new VRaptorEntityManager(entityManager);
107: }
108:
109: @Out(scope=ScopeType.REQUEST,key="javax.persistence.EntityManager")
110: public EntityManager getEntityManager() {
111: return entityManager;
112: }
113: }
|