Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"You cannot set autocommit during a managed transaction" when createEntityManagerFactory called

Tags:

java

jpa

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?

like image 337
Mitch Talmadge Avatar asked Jul 17 '16 12:07

Mitch Talmadge


People also ask

Is autocommit enabled by default?

By default, connection to the MySQL server begins with autocommit mode enabled, which automatically commits every SQL statement as you execute it.

What does set autocommit true do?

The statement con. setAutoCommit(true); enables auto-commit mode, which means that each statement is once again committed automatically when it is completed.

What is set autocommit on?

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.


1 Answers

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 {


}
like image 103
Ajay Deshwal Avatar answered Sep 21 '22 22:09

Ajay Deshwal