I am trying to implement multi-tenancy by separating schemas in my application. In doing this, I have a Tenant
entity which contains a String schemaName
, and I have a Singleton
Startup
EJB which creates a map of EntityManagerFactory
's on startup; one factory assigned to each Tenant
.
Here is my EJB:
@Startup
@Singleton
public class TenantManagementServiceImpl implements TenantManagementService {
private Map<Tenant, EntityManagerFactory> entityManagerFactoryMap;
@PersistenceContext
private EntityManager entityManager;
@PostConstruct
private void init()
{
buildEntityManagerFactories();
}
private List<Tenant> getAllTenants() {
return entityManager.createNamedQuery("Tenant.getAll", Tenant.class).getResultList();
}
private void buildEntityManagerFactories() {
entityManagerFactoryMap = new HashMap<>();
for (Tenant tenant : getAllTenants()) {
Map<String, String> properties = new HashMap<>();
properties.put("hibernate.default_schema", tenant.getSchemaName());
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("MyApp", properties);
entityManagerFactoryMap.putIfAbsent(tenant, entityManagerFactory);
}
}
@Override
public EntityManagerFactory getEntityManagerFactory(Tenant tenant) {
return entityManagerFactoryMap.get(tenant);
}
}
And the NamedQuery
being used:
@NamedQuery(name = "Tenant.getAll", query = "SELECT t FROM Tenant t")
Unfortunately, on startup, I receive this error:
java.lang.Exception: {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"myapp-1.0-SNAPSHOT.war\".component.TenantManagementServiceImpl.START" => "org.jboss.msc.service.StartException in service jboss.deployment.unit.\"myapp-1.0-SNAPSHOT.war\".component.TenantManagementServiceImpl.START: java.lang.IllegalStateException: WFLYEE0042: Failed to construct component instance
Caused by: java.lang.IllegalStateException: WFLYEE0042: Failed to construct component instance
Caused by: javax.ejb.EJBException: javax.persistence.PersistenceException: [PersistenceUnit: MyApp] Unable to build Hibernate SessionFactory
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: MyApp] Unable to build Hibernate SessionFactory
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Unable to open JDBC connection for schema management target
Caused by: java.sql.SQLException: IJ031017: You cannot set autocommit during a managed transaction"}}
The error takes place on this line:
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("MyApp", properties);
I am using this guide as a reference. I don't understand why I am receiving this error. I am using WildFly 10. What is going wrong, and how can I correct it?
By default, connection to the MySQL server begins with autocommit mode enabled, which automatically commits every SQL statement as you execute it.
The statement con. setAutoCommit(true); enables auto-commit mode, which means that each statement is once again committed automatically when it is completed.
SET AUTOCOMMIT sets the autocommit behavior of the current database session. By default, embedded SQL programs are not in autocommit mode, so COMMIT needs to be issued explicitly when desired. This command can change the session to autocommit mode, where each individual statement is committed implicitly.
The default transaction behavior of an EJB is container-managed, which means transaction lifecycle is managed by ejb container of the application server. You need to set it as bean-managed by annotating your ejb class like:
@Startup
@Singleton
@TransactionManagement(value=TransactionManagementType.BEAN)
public class TenantManagementServiceImpl implements TenantManagementService {
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With