Skip to content

sebthom.de

Menu
  • Home
  • About me
  • Imprint
    • Datenschutzerklärung
  • Guestbook
Menu

Configuring EMF Teneo with Hibernate, Commons DBCP, Spring Hibernate Transaction Manager, and the OpenSessionInViewFilter

Posted on Saturday October 2nd, 2010Saturday October 2nd, 2010 by sebthom

While trying to get an application working with , Hibernate, Commons DBCP, Spring Hibernate Transaction Manager and the OpenSessionInViewFilter I encountered several unexpected issues. Here is an example of a working configuration for this software stack. Read the comments below the XML file for some explanations.

HbDataStoreWithDataSource.java:

package de.sebthom.util;

import java.sql.*;
import java.util.Properties;
import javax.sql.DataSource;
import org.eclipse.emf.teneo.PersistenceOptions;
import org.eclipse.emf.teneo.hibernate.HbSessionDataStore;
import org.hibernate.HibernateException;
import org.hibernate.cfg.*;
import org.hibernate.connection.ConnectionProvider;

/**
 * @author Sebastian Thomschke
 */
public class HbDataStoreWithDataSource extends HbSessionDataStore {
  public final static class CustomConnectionProvider implements ConnectionProvider {
    private DataSource ds;

    public void close() throws HibernateException { }

    public void closeConnection(final Connection conn) throws SQLException {
      conn.close();
    }

    public void configure(final Properties props) throws HibernateException {
      ds = _CONFIG_TIME_DS_HOLDER.get();
    }

    public Connection getConnection() throws SQLException {
      return ds.getConnection();
    }

   public boolean supportsAggressiveRelease() {
     return false;
   }
  }

  private static final long serialVersionUID = 1L;
  private static HbDataStoreWithDataSource INSTANCE;

  /**
   * the data source holder acts as a thread safe bridge between the DSConnectionProvider which is instantiated by Hibernate internally
   * and the data source injected into the session factory during spring configuration time. 
   */
  private static final ThreadLocal _CONFIG_TIME_DS_HOLDER = new ThreadLocal();

  public static HbDataStoreWithDataSource getInstance() {
		return INSTANCE;
  }

  private final Properties props = new Properties();

  public HbDataStoreWithDataSource() {
    INSTANCE = this;

    props.setProperty(PersistenceOptions.ADD_INDEX_FOR_FOREIGN_KEY, "true");
    props.setProperty(PersistenceOptions.FETCH_CONTAINMENT_EAGERLY, "false");
    props.setProperty(PersistenceOptions.FETCH_ASSOCIATION_EXTRA_LAZY, "false");

    // tell Teneo to not change the table names, we do this using Hibernate's ImprovedNamingStrategy
    props.setProperty(PersistenceOptions.SQL_CASE_STRATEGY, "none");
    props.setProperty(PersistenceOptions.MAXIMUM_SQL_NAME_LENGTH, "-1");
  }

  protected Configuration createConfiguration() {
    Configuration cfg = super.createConfiguration();
    cfg.setNamingStrategy(ImprovedNamingStrategy.INSTANCE);

    // only if a DS is injected we register our connection provider
    if (_CONFIG_TIME_DS_HOLDER.get() != null)
      cfg.setProperty(Environment.CONNECTION_PROVIDER, CustomConnectionProvider.class.getName());
    return cfg;
  }

  public void setDataSource(final DataSource ds) {
    _CONFIG_TIME_DS_HOLDER.set(ds);
  }

  public final void setHibernateProperties(final Properties hibernateProperties) {
    throw new UnsupportedOperationException();
  }

  public final void setPersistenceProperties(final Properties persistenceOptions) {
    throw new UnsupportedOperationException();
  }

  public void setProperties(final Properties props) {
    this.props.putAll(props);
    super.setProperties(this.props);
  }
}

web.xml:


  openSessionInViewFilter
  org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    
      singleSession
      true
    
    
      sessionFactoryBeanName
      realSessionFactory
    


  openSessionInViewFilter
  /*
  REQUEST
  ERROR

applicationContext.xml:



  

  
    
      
        ${jdbc.driverClassName}
        ${jdbc.url}
        ${jdbc.username}
        ${jdbc.password}
        false
        ${jdbc.maxConnections}
        ${jdbc.minConnections}
        10000
        ${jdbc.minConnections}
        ${jdbc.validationQuery}
        false
        true
        1200000
        1800000
        5
      
    
  

  
    
      hibernate.dialect=${hibernate.dialect}
      hibernate.hbm2ddl.auto=${hibernate.hbm2ddl.auto}
      hibernate.jdbc.batch_size=2000
      hibernate.show_sql=${hibernate.show_sql}
      hibernate.transaction.auto_close_session=false
      hibernate.current_session_context_class=org.springframework.orm.hibernate3.SpringSessionContext
      hibernate.transaction.factory_class=org.springframework.orm.hibernate3.SpringTransactionFactory
    
    com.acme.ShopPackageImpl 
  

  

  

  


Comments:

  1. VERY IMPORTANT:The HibernateTransactionManager does NOT get the teneoSessionFactory(HbSessionDataStore) object passed in as sessionFactory, but the underlying Hibernate SessionFactory that can be retrieved from the HbSessionDataStore via the getSessionFactory() method. Not doing so will result in duplicate Hibernate Sessions completely breaking the transaction managment. This happens because in that case the TransactionSynchronizationManager will sometimes internally bind the hibernate session to the current thread based on different keys and thus does not find it again. Here are some stacktraces showing the problem:
    TransactionSynchronizationManager.bindResource(Object, Object) line: 170	
    at OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 183
    => results in TransactionSynchronizationManager.bindResource(HbSessionDataStore, SessionHolder) => as key the Teneo SessionFactory is used
    
    TransactionSynchronizationManager.bindResource(Object, Object) line: 170	
    at SessionFactoryUtils.doGetSession(SessionFactory, Interceptor, SQLExceptionTranslator, boolean) line: 339	
    at SessionFactoryUtils.doGetSession(SessionFactory, boolean) line: 256	
    at SpringSessionContext.currentSession() line: 60	
    at SessionFactoryImpl.getCurrentSession() line: 700	
    at HbSessionDataStore(HbBaseSessionDataStore).getCurrentSession() line: 161	
    => results in TransactionSynchronizationManager.bindResource(SessionFactoryImpl, SessionHolder) => as key the Hibernate SessionFactory is used
    
    TransactionSynchronizationManager.bindResource(Object, Object) line: 170	
    at HibernateTransactionManager.doBegin(Object, TransactionDefinition) line: 577	
    at HibernateTransactionManager(AbstractPlatformTransactionManager).getTransaction(TransactionDefinition) line: 371
    at TransactionInterceptor(TransactionAspectSupport).createTransactionIfNecessary(PlatformTransactionManager, TransactionAttribute, String) line: 316	
    at TransactionInterceptor.invoke(MethodInvocation) line: 105	
    at ReflectiveMethodInvocation.proceed() line: 172
    => results in TransactionSynchronizationManager.bindResource(HbSessionDataStore, SessionHolder) => as key the Teneo SessionFactory is used
    
  2. defaultAutoCommit is set to false to ensure that Spring has full control over the transaction and that the connection pool is not committing statements automatically based on it’s own strategies.
  3. The example uses an extended version of the org.eclipse.emf.teneo.hibernate.HbSessionDataStore class that allows the usage of a DataSource object and that configures Teneo to not alter the table, column names but let’s Hibernate handle this via its ImprovedNamingStrategy.
  4. hibernate.transaction.auto_close_session is set to false to avoid “SessionException: Session is closed!” in conjunction with the OpenSessionInViewListener.
  5. hibernate.current_session_context_class and hibernate.transaction.factory_class are set to special Spring implementations to avoid “org.hibernate.HibernateException: No CurrentSessionContext configured!” when not using Spring Hibernate Template via HibernateDAOSupport. It is not recommended to use the Hibernate Template anymore, see //blog.springsource.com/2007/06/26/so-should-you-still-use-springs-hibernatetemplate-andor-jpatemplate/

Categories

  • Blog (1)
  • IT (21)
    • Development (16)
      • Java (7)
      • Jython (4)
      • Visual Basic (5)
    • Linux (3)
    • WebSphere Application Server (1)
    • WebSphere Portal (2)
    • Windows (1)
  • My Freeware (2)
  • My Music (3)

Recent Posts

  • Logging WebSphere API calls in wsadmin scripts
  • [Solved] Windows 7 “Safely Remove Hardware” pop-up menu horrendously slow
  • Bash: Capturing stderr in a variable while still printing to the console.
  • Configuring EMF Teneo with Hibernate, Commons DBCP, Spring Hibernate Transaction Manager, and the OpenSessionInViewFilter
  • Using EMF ECore model objects with Wicket components
  • Installing Tomcat 6 on Debian Squeeze
  • Leveraging PyDev’s auto-completion for indirectly created objects
  • OVal 1.40 released
  • Installing WebSphere Portal in a local network
  • Comparing version numbers in Jython / Python

Blogroll

  • E L S U A
  • elektrofever.de
  • OVal
  • Sweettt.com
  • Twins’ Running Blog

Recent Comments

  • Annibale on Visual Basic – Multiple Undos Class v2.04
  • Annibale on Visual Basic – Multiple Undos Class v2.04
  • koliko2k3 on Guestbook
  • hdkid on MyPad v1.1.6 – a PHP Editor
  • Luis Diego Villarreal on Excel – VBA Timer Example v1.0.1

Archives

  • June 2014
  • May 2012
  • January 2011
  • October 2010
  • September 2010
  • March 2010
  • February 2010
  • September 2009
  • July 2009
  • March 2009
  • February 2009
  • November 2008
  • September 2008
  • May 2008
  • September 2007
  • July 2007
  • July 2004
  • March 2003
  • August 2002
  • April 2002
  • January 2002
  • Deutsch (de)Deutsch
  • English (en)English
© 2025 sebthom.de | Powered by Minimalist Blog WordPress Theme