使用 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;
}
}
目前正在使用上面的代码进行测试,它似乎已经解决了问题。
我们正在使用如上所述的多租户事务管理器 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;
}
}
目前正在使用上面的代码进行测试,它似乎已经解决了问题。