使用 Spring JpaTransactionManager 时,Eclipse Link 中未处理并发

Concurrency not handled in Eclipse Link when using Spring JpaTransactionManager

我们正在使用如上所述的多租户事务管理器 post 注册日期:2014 年 11 月。我们正在使用 Spring 数据,并且我们正在根据用户 ID 和密码识别租户,即我们不知道第一个租户。该应用程序工作正常。我们使用具有基本身份验证的 spring 安全性。应用程序通过 Rest API.

公开

当并发的不同租户同时使用事务管理器时会出现问题。我们使用 TenantResolver class 找到租户

我们还有其他 2 个消息流,每分钟有大约 40 条消息和 10 条消息,它使用连接管理器来查找租户并根据它执行事务。

这里的日志:

MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> ACTUAL_TENANT : vce 07:51:05,720 INFO [xxx.integration.jms.VehicleRepositoryListener] (vrMessageListenerContainer-1) [] VehicleRepositoryListener.onMessage()--> Process successfully completed in VehicleRepositoryListener 07:51:05,768 ERROR [xxx.integration.services.utils.TenantUtils] (vrMessageListenerContainer-1) [] TenantUtils.setTenantByProductClass -> Error in setting the Tenant org.springframework.orm.jpa.JpaSystemException: Exception [EclipseLink-28013] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException Exception Description: Unable to deploy PersistenceUnit [default] in invalid state [DeployFailed]. Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28019] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException Exception Description: Deployment of PersistenceUnit [default] failed. Close all factories for this PersistenceUnit. Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28009] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException Exception Description: Attempted to redeploy a session named /file:/opt/jboss64/modules/system/layers/base/org/jboss/as/ejb3/main/timers/_default without closing it.; nested exception is javax.persistence.PersistenceException: Exception [EclipseLink-28013] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException Exception Description: Unable to deploy PersistenceUnit [default] in invalid state [DeployFailed]. Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28019] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException Exception Description: Deployment of PersistenceUnit [default] failed. Close all factories for this PersistenceUnit. Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28009] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException Exception Description: Attempted to redeploy a session named /file:/opt/jboss64/modules/system/layers/base/org/jboss/as/ejb3/main/timers/_default without closing it. 07:51:05,774 INFO [xxxintegration.services.XXXUpdateRequestProcessServiceImpl] (xxxMessageListenerContainer-1) [] Returning from XXXUpdateRequestProcessServiceImpl.login() 07:51:05,775 INFO [xxx.integration.services.XXXUpdateRequestProcessServiceImpl] (xxxMessageListenerContainer-1) [] XXXUpdateRequestProcessServiceImpl.getUpdateTechToolResponseDTOs()-> Token in Service :b3b00ab6-5c36-45af-8ec2-0b6f1710e888 07:51:05,777 INFO [xxx.integration.services.VehicleRepositoryService] (vrMessageListenerContainer-1) [] VehicleRepositoryService.parseVehicleRepositoryUpdate()-> Tenant is null 07:51:05,780 INFO [xxx.integration.jms.VehicleRepositoryListener] (vrMessageListenerContainer-1) [] VehicleRepositoryListener.onMessage()--> Process successfully completed in VehicleRepositoryListener 07:51:06,138 INFO [xxx.application.VehicleActivationService] (http-/0.0.0.0:16780-71) [] Inside VehicleActivationService.checkActivation() 07:51:06,141 INFO [xxx.application.VehicleActivationService] (http-/0.0.0.0:16780-71) [] Inside VehicleActivationService.getTenant() 07:51:06,145 ERROR [xxx.integration.rest.UpdateTechTool] (http-/0.0.0.0:16780-71) [] Exception in check activation method : Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: Exception [EclipseLink-28013] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException Exception Description: Unable to deploy PersistenceUnit [default] in invalid state [DeployFailed]. Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28019] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException Exception Description: Deployment of PersistenceUnit [default] failed. Close all factories for this PersistenceUnit. Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28009] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException Exception Description: Attempted to redeploy a session named /file:/opt/jboss64/modules/system/layers/base/org/jboss/as/ejb3/main/timers/_default without closing it. 07:51:06,148 INFO [xxx.application.XXXUpdateTechToolDTOService] (http-/0.0.0.0:16780-71) [] Inside UpdateTechToolDTOService.update() 07:51:06,154 ERROR [xxx.application.XXXUpdateTechToolDTOService] (http-/0.0.0.0:16780-71) [] XXXUpdateTechToolDTOService.update() -> EXCEPTION while calling update :java.lang.NullPointerException 07:51:06,166 INFO [xxx.integration.services.UpdateRequestProcessServiceImpl] (MessageListenerContainer-1) [] Inside UpdateRequestProcessServiceImpl.createResponse() 07:51:06,883 INFO [stdout] (Finalizer) [] [EL Info]: connection: 2017-04-17 07:51:06.882--ServerSession(1485077057)--/file:/opt/jboss64/modules/system/layers/base/org/jboss/as/ejb3/main/timers/_default logout successful 07:51:06,885 INF

处理并发问题的任何帮助或方法。

类似于: EclipseLink - Error: Attempted to redeploy a session without closing it

使用的 MultiTenantJpaTransactionManager class 是:

public class MultiTenantJpaTransactionManager 扩展 JpaTransactionManager {

TenantResolver<Tenant> tenantResolver; 
SchemaProvider schemaProvider; 
@Autowired
public void setTenantResolver(TenantResolver<Tenant> tenantResolver) {
    this.tenantResolver = tenantResolver;
}

@Autowired(required = false)
public void setSchemaProvider(SchemaProvider schemaProvider) {
    this.schemaProvider = schemaProvider;
}

@Override
protected synchronized javax.persistence.EntityManager createEntityManagerForTransaction() {
    boolean refreshed = false;
    EntityManager em = super.createEntityManagerForTransaction();
    try {
        LOGGER.info("Entering createEntityManagerforTransaction()");
        if (schemaProvider != null) {
            TenantSessionCustomizer.setSchemaName(schemaProvider.getSchema());
        }
        ServerSession ss = ((EntityManagerImpl) em.getDelegate()).getServerSession();
        Map sessionProp = ss.getProperties();
        String actualTenant = (String) sessionProp.get(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT);
        LOGGER.info("MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> ACTUAL_TENANT : " + actualTenant);

        if (tenantResolver != null && tenantResolver.getCurrentTenant() != null) {
            LOGGER.info("MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> CURRENT_TENANT : " + tenantResolver.getCurrentTenant());
            if ((actualTenant == null) || (actualTenant != null && !actualTenant.equals(tenantResolver.getCurrentTenant().getHandle()))) {
                sessionProp.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenantResolver.getCurrentTenant().getHandle());
                sessionProp.put(PersistenceUnitProperties.SESSION_CUSTOMIZER, TenantSessionCustomizer.class.getName());
                MetadataRefreshListener mrl = ((EntityManagerImpl) em.getDelegate()).getServerSession().getRefreshMetadataListener();
                if (mrl != null) {
                    Map<String, Object> prop = new HashMap<String, Object>();
                    mrl.triggerMetadataRefresh(prop);
                    refreshed = true;
                    LOGGER.info("createEntityManagerforTransaction()---->Metadata refreshed");
                }
            }
        }
    } catch (Exception ex) {
        LOGGER.error("MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> Exception while creating EntityManagerForTransaction " + ex.getMessage());
    }
    return refreshed ? super.createEntityManagerForTransaction() : em;
}

}

关注https://www.eclipse.org/eclipselink/documentation/2.5/solutions/multitenancy002.htm

这可能有效:

@Override
protected synchronized javax.persistence.EntityManager createEntityManagerForTransaction() {
    boolean refreshed = false;
    EntityManagerFactory emf = getEntityManagerFactory();
    EntityManager em = null;
    try {
        if (schemaProvider != null) {
            TenantSessionCustomizer.setSchemaName(schemaProvider.getSchema());
        }
        Map tenantProp = new HashMap();

        if (tenantResolver != null && tenantResolver.getCurrentTenant() != null) {
           tenantProp.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenantResolver.getCurrentTenant().getHandle());

             em = emf.createEntityManager(tenantProp);
        }
    } catch (Exception ex) {
        LOGGER.error("MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> Exception while creating EntityManagerForTransaction " + ex.getMessage());
    }
    return em;
}

public class MultiTenantJpaTransactionManager 扩展 JpaTransactionManager { private static final Logger LOGGER = LoggerFactory.getLogger(MultiTenantJpaTransactionManager.class);

TenantResolver<Tenant> tenantResolver; 
SchemaProvider schemaProvider;

@Autowired
public void setTenantResolver(TenantResolver<Tenant> tenantResolver) {
    this.tenantResolver = tenantResolver;
}

@Autowired(required = false)
public void setSchemaProvider(SchemaProvider schemaProvider) {
    this.schemaProvider = schemaProvider;
}

@Override
protected synchronized javax.persistence.EntityManager createEntityManagerForTransaction() {
    boolean refreshed = false;
    EntityManagerFactory emf = getEntityManagerFactory();
    EntityManager em = super.createEntityManagerForTransaction();
    try {
        LOGGER.info("Entering createEntityManagerforTransaction()");
        if (schemaProvider != null) {
            TenantSessionCustomizer.setSchemaName(schemaProvider.getSchema());
        }
        ServerSession ss = ((EntityManagerImpl) em.getDelegate()).getServerSession();
        Map sessionProp = ss.getProperties();

        if (tenantResolver != null && tenantResolver.getCurrentTenant() != null) {
            sessionProp.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenantResolver.getCurrentTenant().getHandle());

            em = emf.createEntityManager(sessionProp);
        }
    } catch (Exception ex) {
        LOGGER.error("MultiTenantJpaTransactionManager.createEntityManagerForTransaction()-> Exception while creating EntityManagerForTransaction " + ex.getMessage());
    }
    return em;
}

}

目前正在使用上面的代码进行测试,它似乎已经解决了问题。