Skip to content

sebthom.de

Menu
  • Home
  • Über mich
  • Impressum
    • Datenschutzerklärung
  • Gästebuch
Menu

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

Posted on Samstag, der 2. Oktober 2010Samstag, der 2. Oktober 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/

Kategorien

  • Blog (1)
  • IT (21)
    • Entwicklung (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)

Neueste Beiträge

  • 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

Neueste Kommentare

  • koliko2k3 bei Gästebuch
  • hdkid bei MyPad v1.1.6 – ein PHP Editor
  • Luis Diego Villarreal bei Excel – VBA Timer Example v1.0.1
  • jonathan bei Gästebuch
  • Pierre bei Lotus Notes [Send only] und [Send and File] Schaltflächen für Outlook 2003

Archive

  • Juni 2014
  • Mai 2012
  • Januar 2011
  • Oktober 2010
  • September 2010
  • März 2010
  • Februar 2010
  • September 2009
  • Juli 2009
  • März 2009
  • Februar 2009
  • November 2008
  • September 2008
  • Mai 2008
  • September 2007
  • Juli 2007
  • Juli 2004
  • März 2003
  • August 2002
  • April 2002
  • Januar 2002
  • Deutsch (de)Deutsch
  • English (en)English
© 2023 sebthom.de | Powered by Minimalist Blog WordPress Theme