title: Proper way to configure Spring transaction manager on a multi-datasource scenario (hibernate 5.2.6)
body: <p>After upgrading my application to hibernate 5.2.6 (was 5.0) and spring-core to 4.3.6 I started having tons of the infamous "Could not obtain transaction-synchronized Session for current thread" Hibernate exception.</p>
  
  <pre><code>15:13:36,907 ERROR [foo.my.CustomLdapAuthoritiesPopulator] (default task-10) Error populating authorities: javax.persistence.TransactionRequiredException: no transaction is in progress
      at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3450)
      at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1418)
      at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1414)
      at org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:144)
      at org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
  </code></pre>
  
  <p>This application works with 3 datasources, all configured as Non-XA datasources in Jboss Wildfly which are:</p>
  
  <ol>
  <li>Db1: mysql, using Hibernate using legacy deprecated Criteria API.</li>
  <li>Db2: mysql, plain JDBC.</li>
  <li>Db3: sql server, Hibernate with JPA CriteriaBuilder.</li>
  </ol>
  
  <p>There are no cross-database queries. Each service is @Transactional and the specific Services, DAO's and Model classes (for hibernate) are separated in different packages. No references exist between them.</p>
  
  <p>The problem is, i'm very unsured on how to configure the transaction managers in a "proper way". The only solution I managed to get working was by painstakingly changing every @transaction annotation to include the transction manager name:</p>
  
  <pre><code>@Transactional(transactionManager="tmDb1")
  </code></pre>
  
  <p>Thus resulting in the following complete application-context.xml file (hibernate properties, xmlns namespaces omitted)</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans&gt;
  
      &lt;task:annotation-driven /&gt;
      &lt;mvc:annotation-driven&gt;&lt;/mvc:annotation-driven&gt;
  
      &lt;!-- Exclude controllers --&gt;
      &lt;context:component-scan base-package="foo.my.framework, foo.my.app"&gt;
          &lt;context:exclude-filter type="regex" expression="foo\.my\.app\.web\.controllers\..*" /&gt;
      &lt;/context:component-scan&gt;
  
      &lt;!-- DB1 Datasource Hibernate mysql --&gt;
      &lt;bean id="DB1" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
          &lt;property name="jndiName" value="java:/myconnections/db1-datasource" /&gt;
      &lt;/bean&gt;
  
      &lt;bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"&gt;
          &lt;property name="dataSource" ref="DB1" /&gt;
          &lt;property name="packagesToScan"&gt;
              &lt;list&gt;
                  &lt;value&gt;foo.my.framework.domain&lt;/value&gt;
                  &lt;value&gt;foo.my.app.model&lt;/value&gt;
              &lt;/list&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;bean id="tmDb1" class="org.springframework.orm.hibernate5.HibernateTransactionManager"&gt;
          &lt;property name="sessionFactory" ref="sessionFactory" /&gt;
      &lt;/bean&gt;
  
      &lt;!-- DB2 Datasource JDBC mysql --&gt;
      &lt;bean id="DB2" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
          &lt;property name="jndiName" value="java:/myconnections/db2-datasource" /&gt;
      &lt;/bean&gt;
      &lt;bean id="tmDb2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;
          &lt;property name="dataSource" ref="DB2" /&gt;
      &lt;/bean&gt;
  
      &lt;!-- DB3 Datasource Hibernate SQL Server JPA CriteriaBuilder --&gt;
      &lt;bean id="DB3" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
          &lt;property name="jndiName" value="java:/myconnections/db3-datasource" /&gt;
      &lt;/bean&gt;
  
      &lt;bean id="punDB3" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
          &lt;property name="persistenceUnitName" value="punDB3" /&gt;
          &lt;property name="dataSource" ref="DB3" /&gt;
          &lt;property name="packagesToScan"&gt;
              &lt;list&gt;
                  &lt;value&gt;foo.my.app.model.db3model&lt;/value&gt;
              &lt;/list&gt;
          &lt;/property&gt;
          &lt;property name="jpaVendorAdapter"&gt;
              &lt;bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
  
      &lt;bean id="tmDb3" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
          &lt;property name="entityManagerFactory" ref="punDB3" /&gt;
      &lt;/bean&gt;
  
      &lt;tx:annotation-driven transaction-manager="tmDb1" /&gt;
      &lt;tx:annotation-driven transaction-manager="tmDb2" /&gt;
      &lt;tx:annotation-driven transaction-manager="tmDb3" /&gt;
  &lt;/beans&gt;
  </code></pre>
  
  <p>My questions are:</p>
  
  <ol>
  <li><p>How many tx-managers should be used? Can it be done with one, using <code>&lt;tx:jta-transaction-manager  /&gt;</code> ? I tried some combinations but to no avail. If possible I would like to have only one transaction manager.</p></li>
  <li><p>Is there a way (with 1 or more tx-managers) to avoid declaring the tx-name inside the <code>@Transactional</code> annotation?</p></li>
  <li><p>Why did this error appear when migrating hibernate from 5.0 to 5.2? It worked perfectly with the 3 tx:annotation-driven blocks and no need to indicate the TM's name on the <code>@Transactional</code> annotation.</p></li>
  <li><p>In essence, what's the cleanest way to configure multiple datasources in spring with different datasource types (some with entity managers) ?</p></li>
  </ol>
  
  <p>Some remarks:</p>
  
  <ul>
  <li>Every datasource is configured in Wildfly as Non-XA.</li>
  <li>I don't mind using the container transaction manager.</li>
  <li>All @Service classes only deal with one database at a time. No need to extend the transaction to multiple datasource.</li>
  </ul>
  
  <p><strong>Update 1</strong>
  After some investigation I think that by not declaring the transaction manager name in the @Transactional attribute, spring tries to find a TM called "transactionManager", so (maybe) this has been working because all the DAO's were in effect using the same default TM? Still doesn't explain why it stopped working then upgrade Hibernate, though.</p>