@Override public void doBegin(Object transaction, final TransactionDefinition definition) { logger.info("MultiTenantJpaTransactionManager.doBegin()"); super.doBegin(transaction, definition); EntityManagerHolder entityManagerHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(getEntityManagerFactory()); EntityManager entityManager = entityManagerHolder.getEntityManager(); String currentTenant = tenantResolver.getCurrentTenant(); logger.info("MultiTenantJpaTransactionManager.doBegin() - currentTenant: " + currentTenant); String currentTenantSet = (String) entityManager.getProperties().get(MULTITENANT_PROPERTY_DEFAULT); logger.info("MultiTenantJpaTransactionManager.doBegin() - currentTenantSet: " + currentTenantSet); if(currentTenantSet != null && !currentTenantSet.equals(currentTenant)) { throw new IllegalStateException("Resource conflict - The EntityManager is already assigned to tenant : " + currentTenant); } entityManager.setProperty(MULTITENANT_PROPERTY_DEFAULT, currentTenant); }
@Override public void preHandle(WebRequest request) throws DataAccessException { String participateAttributeName = getParticipateAttributeName(); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); if (asyncManager.hasConcurrentResult()) { if (applyCallableInterceptor(asyncManager, participateAttributeName)) { return; } } if (TransactionSynchronizationManager.hasResource(getEntityManagerFactory())) { // do not modify the EntityManager: just mark the request accordingly Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST); int newCount = (count != null ? count + 1 : 1); request.setAttribute(getParticipateAttributeName(), newCount, WebRequest.SCOPE_REQUEST); } else { logger.debug("Opening JPA EntityManager in OpenEntityManagerInViewInterceptor"); try { EntityManager em = createEntityManager(); EntityManagerHolder emHolder = new EntityManagerHolder(em); TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), emHolder); AsyncRequestInterceptor interceptor = new AsyncRequestInterceptor(getEntityManagerFactory(), emHolder); asyncManager.registerCallableInterceptor(participateAttributeName, interceptor); asyncManager.registerDeferredResultInterceptor(participateAttributeName, interceptor); } catch (PersistenceException ex) { throw new DataAccessResourceFailureException("Could not create JPA EntityManager", ex); } } }
@Override public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException { if (!decrementParticipateCount(request)) { EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager.unbindResource(getEntityManagerFactory()); logger.debug("Closing JPA EntityManager in OpenEntityManagerInViewInterceptor"); EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager()); } }
/** * close the entity manager. * Use it with caution! This is only intended for use with async request, which Spring won't * close the entity manager until the async request is finished. */ public void closeEntityManager() { EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(getEntityManagerFactory()); if (emHolder == null) { return; } logger.debug("Closing JPA EntityManager in EntityManagerUtil"); EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager()); }
@Override public void preHandle(WebRequest request) throws DataAccessException { String participateAttributeName = getParticipateAttributeName(); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); if (asyncManager.hasConcurrentResult()) { if (applyCallableInterceptor(asyncManager, participateAttributeName)) { return; } } if (TransactionSynchronizationManager.hasResource(getEntityManagerFactory())) { // Do not modify the EntityManager: just mark the request accordingly. Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST); int newCount = (count != null ? count + 1 : 1); request.setAttribute(getParticipateAttributeName(), newCount, WebRequest.SCOPE_REQUEST); } else { logger.debug("Opening JPA EntityManager in OpenEntityManagerInViewInterceptor"); try { EntityManager em = createEntityManager(); EntityManagerHolder emHolder = new EntityManagerHolder(em); TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), emHolder); AsyncRequestInterceptor interceptor = new AsyncRequestInterceptor(getEntityManagerFactory(), emHolder); asyncManager.registerCallableInterceptor(participateAttributeName, interceptor); asyncManager.registerDeferredResultInterceptor(participateAttributeName, interceptor); } catch (PersistenceException ex) { throw new DataAccessResourceFailureException("Could not create JPA EntityManager", ex); } } }
/** * Binds an EMF to the thread and tests if EM with different properties * generate new EMs or not. */ @Test public void testPropertiesForSharedEntityManager1() { Properties props = new Properties(); props.put("foo", "bar"); EntityManager em = mock(EntityManager.class); // only one call made - the first EM definition wins (in this case the one w/ the properties) given(mockEmf.createEntityManager(props)).willReturn(em); given(em.getDelegate()).willReturn(new Object()); given(em.isOpen()).willReturn(true); PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor(); DefaultPrivatePersistenceContextFieldWithProperties transactionalFieldWithProperties = new DefaultPrivatePersistenceContextFieldWithProperties(); DefaultPrivatePersistenceContextField transactionalField = new DefaultPrivatePersistenceContextField(); pabpp.postProcessPropertyValues(null, null, transactionalFieldWithProperties, "bean1"); pabpp.postProcessPropertyValues(null, null, transactionalField, "bean2"); assertNotNull(transactionalFieldWithProperties.em); assertNotNull(transactionalField.em); // the EM w/ properties will be created assertNotNull(transactionalFieldWithProperties.em.getDelegate()); // bind em to the thread now since it's created try { TransactionSynchronizationManager.bindResource(mockEmf, new EntityManagerHolder(em)); assertNotNull(transactionalField.em.getDelegate()); verify(em).close(); } finally { TransactionSynchronizationManager.unbindResource(mockEmf); } }
@Test public void testPropertiesForSharedEntityManager2() { Properties props = new Properties(); props.put("foo", "bar"); EntityManager em = mock(EntityManager.class); // only one call made - the first EM definition wins (in this case the one w/o the properties) given(mockEmf.createEntityManager()).willReturn(em); given(em.getDelegate()).willReturn(new Object(), 2); given(em.isOpen()).willReturn(true); PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor(); DefaultPrivatePersistenceContextFieldWithProperties transactionalFieldWithProperties = new DefaultPrivatePersistenceContextFieldWithProperties(); DefaultPrivatePersistenceContextField transactionalField = new DefaultPrivatePersistenceContextField(); pabpp.postProcessPropertyValues(null, null, transactionalFieldWithProperties, "bean1"); pabpp.postProcessPropertyValues(null, null, transactionalField, "bean2"); assertNotNull(transactionalFieldWithProperties.em); assertNotNull(transactionalField.em); // the EM w/o properties will be created assertNotNull(transactionalField.em.getDelegate()); // bind em to the thread now since it's created try { TransactionSynchronizationManager.bindResource(mockEmf, new EntityManagerHolder(em)); assertNotNull(transactionalFieldWithProperties.em.getDelegate()); verify(em).close(); } finally { TransactionSynchronizationManager.unbindResource(mockEmf); } }
protected EntityManager doGetActivePersistenceContext(Object testObject) { EntityManagerHolder entityManagerHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(getPersistenceUnit(testObject)); if (entityManagerHolder != null && entityManagerHolder.getEntityManager() != null && entityManagerHolder.getEntityManager().isOpen()) { return entityManagerHolder.getEntityManager(); } return null; }
@Before public void doBefore(){ this.em = emf.createEntityManager(); EntityManagerHolder emHolder = new EntityManagerHolder(em); TransactionSynchronizationManager.bindResource(emf, emHolder); }
/** * Fetches {@link javax.persistence.EntityManager} bound to the current Spring transaction or creates new manager. * * @param entityManagerFactory {@link javax.persistence.EntityManagerFactory} used either as a key for a Spring * transaction resource lookup or as a factory to create new * {@link javax.persistence.EntityManager}. * @return {@link javax.persistence.EntityManager} bound to the existing Spring transaction or new manager instance. */ public static EntityManager resolveEntityManager(EntityManagerFactory entityManagerFactory) { EntityManagerHolder entityManagerHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(entityManagerFactory); if (entityManagerHolder != null) { return entityManagerHolder.getEntityManager(); } return entityManagerFactory.createEntityManager(); }
private void cleanUpTransaction(final HttpServletRequest request) { if (noTransaction(request)) { return; } logDebug(request, "Cleaning up transaction"); // Close any open iterators DataIteratorHelper.closeOpenIterators(); // Close the session final EntityManagerHolder holder = getEntityManagerHolder(); if (holder != null) { try { final EntityManager entityManager = holder.getEntityManager(); if (entityManager.isOpen()) { entityManager.close(); } } catch (final Exception e) { LOG.error("Error closing Hibernate session", e); } TransactionSynchronizationManager.unbindResourceIfPossible(entityManagerFactory); } // Cleanup the Spring transaction data TransactionSynchronizationManager.setCurrentTransactionReadOnly(false); TransactionSynchronizationManager.setActualTransactionActive(false); // Cleanup the current transaction data CurrentTransactionData.cleanup(); request.removeAttribute(EXECUTION_RESULT_KEY); }
private void openReadOnlyConnection(final HttpServletRequest request) { if (noTransaction(request)) { return; } logDebug(request, "Opening read-only transaction for include"); final EntityManagerHolder holder = getEntityManagerHolder(); holder.getEntityManager().setFlushMode(FlushModeType.COMMIT); if (holder.getEntityManager().getTransaction().isActive()) { holder.getEntityManager().getTransaction().setRollbackOnly(); } TransactionSynchronizationManager.setCurrentTransactionReadOnly(true); }
private void rollbackReadOnlyConnection(final HttpServletRequest request) { if (noTransaction(request)) { return; } final EntityManagerHolder holder = getEntityManagerHolder(); try { logDebug(request, "Rolling back read-only transaction"); if (holder.getEntityManager().getTransaction().isActive()) { holder.getEntityManager().getTransaction().rollback(); } } catch (final PersistenceException e) { throw new IllegalStateException(e); } }
public static EntityManager retrieveBoundEntityManager() { Map<Object, Object> resources = TransactionSynchronizationManager.getResourceMap(); for (Map.Entry<Object, Object> entry : resources.entrySet()) { if (entry.getKey() instanceof EntityManagerFactory) { EntityManagerFactory emf = (EntityManagerFactory) entry.getKey(); //return the entityManager from the first found return ((EntityManagerHolder) entry.getValue()).getEntityManager(); } } throw new RuntimeException("Unable to restore skus from hydrated cache. Please make sure that the OpenEntityManagerInViewFilter is configured in web.xml for the blPU persistence unit."); }
/** * Mise en place du EntityManager */ public EntityManager openEntityManager() { if (TransactionSynchronizationManager.hasResource(entityManagerFactory)) { return ((EntityManagerHolder) TransactionSynchronizationManager.getResource(entityManagerFactory)).getEntityManager(); } else { EntityManager entityManager = entityManagerFactory.createEntityManager(); TransactionSynchronizationManager.bindResource(entityManagerFactory, new EntityManagerHolder(entityManager)); return entityManager; } }
/** * Suppression du EntityManager. */ public void closeEntityManager() { if (TransactionSynchronizationManager.hasResource(entityManagerFactory)) { EntityManagerHolder entityManagerHolder = (EntityManagerHolder) TransactionSynchronizationManager.unbindResource(entityManagerFactory); EntityManagerFactoryUtils.closeEntityManager(entityManagerHolder.getEntityManager()); } }
/** * Retourne l'EntityManager courant. * * Renvoie une exception si l'EntityManager n'est pas présent. */ public EntityManager getCurrentEntityManager() { if (TransactionSynchronizationManager.hasResource(entityManagerFactory)) { return ((EntityManagerHolder) TransactionSynchronizationManager.getResource(entityManagerFactory)).getEntityManager(); } else { throw new IllegalStateException("No EntityManager in the TransactionSynchronizationManager"); } }
@Override protected void doBegin(final Object transaction, final TransactionDefinition definition) { super.doBegin(transaction, definition); final String currentTenant = tenantAware.getCurrentTenant(); if (currentTenant != null) { final EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager .getResource(getEntityManagerFactory()); final EntityManager em = emHolder.getEntityManager(); em.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, currentTenant.toUpperCase()); } }
private static void activateSession() { Map<Object, Object> resourceMap = TransactionSynchronizationManager.getResourceMap(); for (Map.Entry<Object, Object> entry : resourceMap.entrySet()) { if (entry.getKey() instanceof EntityManagerFactory && entry.getValue() instanceof EntityManagerHolder) { ((HibernateEntityManager) ((EntityManagerHolder) entry.getValue()).getEntityManager()).getSession(); } } }
public void preHandle(WebRequest request) throws DataAccessException { String participateAttributeName = getParticipateAttributeName(); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); if (asyncManager.hasConcurrentResult()) { if (applyCallableInterceptor(asyncManager, participateAttributeName)) { return; } } if (TransactionSynchronizationManager.hasResource(getEntityManagerFactory())) { // do not modify the EntityManager: just mark the request accordingly Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST); int newCount = (count != null ? count + 1 : 1); request.setAttribute(getParticipateAttributeName(), newCount, WebRequest.SCOPE_REQUEST); } else { logger.debug("Opening JPA EntityManager in OpenEntityManagerInViewInterceptor"); try { EntityManager em = createEntityManager(); EntityManagerHolder emHolder = new EntityManagerHolder(em); TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), emHolder); AsyncRequestInterceptor interceptor = new AsyncRequestInterceptor(getEntityManagerFactory(), emHolder); asyncManager.registerCallableInterceptor(participateAttributeName, interceptor); asyncManager.registerDeferredResultInterceptor(participateAttributeName, interceptor); } catch (PersistenceException ex) { throw new DataAccessResourceFailureException("Could not create JPA EntityManager", ex); } } }
public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException { if (!decrementParticipateCount(request)) { EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager.unbindResource(getEntityManagerFactory()); logger.debug("Closing JPA EntityManager in OpenEntityManagerInViewInterceptor"); EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager()); } }
/** * Binds an EMF to the thread and tests if EM with different properties * generate new EMs or not. */ @Test public void testPropertiesForSharedEntityManager1() { Properties props = new Properties(); props.put("foo", "bar"); EntityManager em = mock(EntityManager.class); // only one call made - the first EM definition wins (in this case the one w/ the properties) given(mockEmf.createEntityManager(props)).willReturn(em); given(em.getDelegate()).willReturn(new Object()); given(em.isOpen()).willReturn(true); PersistenceAnnotationBeanPostProcessor babpp = new MockPersistenceAnnotationBeanPostProcessor(); DefaultPrivatePersistenceContextFieldWithProperties transactionalFieldWithProperties = new DefaultPrivatePersistenceContextFieldWithProperties(); DefaultPrivatePersistenceContextField transactionalField = new DefaultPrivatePersistenceContextField(); babpp.postProcessPropertyValues(null, null, transactionalFieldWithProperties, null); babpp.postProcessPropertyValues(null, null, transactionalField, null); assertNotNull(transactionalFieldWithProperties.em); assertNotNull(transactionalField.em); // the EM w/ properties will be created assertNotNull(transactionalFieldWithProperties.em.getDelegate()); // bind em to the thread now since it's created try { TransactionSynchronizationManager.bindResource(mockEmf, new EntityManagerHolder(em)); assertNotNull(transactionalField.em.getDelegate()); verify(em).close(); } finally { TransactionSynchronizationManager.unbindResource(mockEmf); } }
@Test public void testPropertiesForSharedEntityManager2() { Properties props = new Properties(); props.put("foo", "bar"); EntityManager em = mock(EntityManager.class); // only one call made - the first EM definition wins (in this case the one w/o the properties) given(mockEmf.createEntityManager()).willReturn(em); given(em.getDelegate()).willReturn(new Object(), 2); given(em.isOpen()).willReturn(true); PersistenceAnnotationBeanPostProcessor babpp = new MockPersistenceAnnotationBeanPostProcessor(); DefaultPrivatePersistenceContextFieldWithProperties transactionalFieldWithProperties = new DefaultPrivatePersistenceContextFieldWithProperties(); DefaultPrivatePersistenceContextField transactionalField = new DefaultPrivatePersistenceContextField(); babpp.postProcessPropertyValues(null, null, transactionalFieldWithProperties, null); babpp.postProcessPropertyValues(null, null, transactionalField, null); assertNotNull(transactionalFieldWithProperties.em); assertNotNull(transactionalField.em); // the EM w/o properties will be created assertNotNull(transactionalField.em.getDelegate()); // bind em to the thread now since it's created try { TransactionSynchronizationManager.bindResource(mockEmf, new EntityManagerHolder(em)); assertNotNull(transactionalFieldWithProperties.em.getDelegate()); verify(em).close(); } finally { TransactionSynchronizationManager.unbindResource(mockEmf); } }
@Override public void execute() throws Exception { EntityManager em = emf.createEntityManager(); EntityManagerHolder emHolder = new EntityManagerHolder(em); try { TransactionSynchronizationManager.bindResource(emf, emHolder); super.execute(); } finally { EntityManagerHolder emHolderB = (EntityManagerHolder) TransactionSynchronizationManager.unbindResource(emf); log.debug("Closing JPA EntityManager in OpenEntityManagerInViewFilter"); EntityManagerFactoryUtils.closeEntityManager(emHolderB.getEntityManager()); } sleep(DateTry.Second*10); }
public AsyncRequestInterceptor(EntityManagerFactory emFactory, EntityManagerHolder emHolder) { this.emFactory = emFactory; this.emHolder = emHolder; }
@Test public void testValidUsage() { Object o = new Object(); EntityManager mockEm = mock(EntityManager.class); given(mockEm.isOpen()).willReturn(true); EntityManagerFactory mockEmf = mock(EntityManagerFactory.class); given(mockEmf.createEntityManager()).willReturn(mockEm); SharedEntityManagerBean proxyFactoryBean = new SharedEntityManagerBean(); proxyFactoryBean.setEntityManagerFactory(mockEmf); proxyFactoryBean.afterPropertiesSet(); assertTrue(EntityManager.class.isAssignableFrom(proxyFactoryBean.getObjectType())); assertTrue(proxyFactoryBean.isSingleton()); EntityManager proxy = proxyFactoryBean.getObject(); assertSame(proxy, proxyFactoryBean.getObject()); assertFalse(proxy.contains(o)); assertTrue(proxy instanceof EntityManagerProxy); EntityManagerProxy emProxy = (EntityManagerProxy) proxy; try { emProxy.getTargetEntityManager(); fail("Should have thrown IllegalStateException outside of transaction"); } catch (IllegalStateException ex) { // expected } TransactionSynchronizationManager.bindResource(mockEmf, new EntityManagerHolder(mockEm)); try { assertSame(mockEm, emProxy.getTargetEntityManager()); } finally { TransactionSynchronizationManager.unbindResource(mockEmf); } assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty()); verify(mockEm).contains(o); verify(mockEm).close(); }
private void bindEntityManager() { EntityManagerHolder holder = new EntityManagerHolder(this.entityManager); TransactionSynchronizationManager.bindResource(this.entityManagerFactory, holder); }
@After public void doAfter(){ EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager .unbindResource(emf); }
private void commitOrRollbackTransaction(final HttpServletRequest request) throws IOException, ServletException { if (noTransaction(request)) { return; } final ExecutionResult result = (ExecutionResult) request.getAttribute(EXECUTION_RESULT_KEY); final EntityManagerHolder holder = getEntityManagerHolder(); // Commit or rollback the transaction boolean runCommitListeners = false; boolean lockingException = false; if (result.commit) { logDebug(request, "Committing transaction"); runCommitListeners = true; // Marked as commit - should run commit listeners try { holder.getEntityManager().getTransaction().commit(); } catch (final Throwable t) { // In case of locking exceptions, we must make sure the correct exception type is returned, so the transaction will be retried lockingException = ExceptionHelper.isLockingException(t); result.error = t; } } else { if (result.error == null && !result.hasWrite) { // Transaction was semantically a commit, so, the commit listeners should run. // However, as there where no writes the transaction will be rolled back runCommitListeners = true; logDebug(request, "Nothing written to database. Rolling-back transaction"); } else { logDebug(request, "Rolling-back transaction"); } holder.getEntityManager().getTransaction().rollback(); } if (lockingException) { // There was a locking exception - throw it now, so the transaction will be retried cleanUpTransaction(request); throw new LockingException(); } // Unbind the session holder, so that listeners which should open a new transaction on this same thread won't be messed up TransactionSynchronizationManager.unbindResourceIfPossible(entityManagerFactory); // Run the transaction listener CurrentTransactionData.detachListeners().runListeners(runCommitListeners); // Bind the session holder again TransactionSynchronizationManager.bindResource(entityManagerFactory, holder); // Log the execution if a regular user is logged in and this is not an AJAX request if (result.traceLog) { traceLog(request, result.error, result.commit); } // The resulting error was not silenced (i.e, by the BaseAction's try / catch. Log and rethrow if (result.error != null && !result.errorWasSilenced) { actionHelper.generateLog(request, servlet.getServletContext(), result.error); ActionHelper.throwException(result.error); } }
private EntityManagerHolder getEntityManagerHolder() { return (EntityManagerHolder) TransactionSynchronizationManager.getResource(entityManagerFactory); }
/** * Returns the EntityManager associated with the current transaction. * * @return */ public EntityManager getEntityManager() { EntityManagerHolder holder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(entityManagerFactory); return holder.getEntityManager(); }