     <link rel="alternate" type="application/atom+xml" title="sebthom.de Category: Java" href="https://sebthom.de/de/category/it/development/java-coding/feed/" />
{"id":152,"date":"2010-10-02T17:26:40","date_gmt":"2010-10-02T16:26:40","guid":{"rendered":"http:\/\/sebthom.de\/?p=152"},"modified":"2010-10-02T17:48:19","modified_gmt":"2010-10-02T16:48:19","slug":"configuring-emf-teneo-hibernate-dbcp-spring-transactions-opensessioninviewfilter","status":"publish","type":"post","link":"https:\/\/sebthom.de\/de\/152-configuring-emf-teneo-hibernate-dbcp-spring-transactions-opensessioninviewfilter\/","title":{"rendered":"Configuring EMF Teneo with Hibernate, Commons DBCP, Spring Hibernate Transaction Manager, and the OpenSessionInViewFilter"},"content":{"rendered":"<p>While trying to get an application working with <a href=\"http:\/\/wiki.eclipse.org\/Teneo\/Hibernate\/Download_and_Install\"EMF Teneo<\/a>, <a href=\"http:\/\/www.hibernate.org\/\">Hibernate<\/a>, <a href=\"http:\/\/commons.apache.org\/dbcp\/\">Commons DBCP<\/a>, <a href=\"http:\/\/static.springsource.org\/spring\/docs\/current\/spring-framework-reference\/html\/orm.html#orm-hibernate-tx-declarative\/\">Spring Hibernate Transaction Manager<\/a> and the <a href=\"http:\/\/static.springsource.org\/spring\/docs\/current\/javadoc-api\/org\/springframework\/orm\/hibernate3\/support\/OpenSessionInViewFilter.html\">OpenSessionInViewFilter<\/a> 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.<\/p>\n<p><b>HbDataStoreWithDataSource.java:<\/b><\/p>\n<pre class=\"java\" name=\"code\">\r\npackage de.sebthom.util;\r\n\r\nimport java.sql.*;\r\nimport java.util.Properties;\r\nimport javax.sql.DataSource;\r\nimport org.eclipse.emf.teneo.PersistenceOptions;\r\nimport org.eclipse.emf.teneo.hibernate.HbSessionDataStore;\r\nimport org.hibernate.HibernateException;\r\nimport org.hibernate.cfg.*;\r\nimport org.hibernate.connection.ConnectionProvider;\r\n\r\n\/**\r\n * @author Sebastian Thomschke\r\n *\/\r\npublic class HbDataStoreWithDataSource extends HbSessionDataStore {\r\n  public final static class CustomConnectionProvider implements ConnectionProvider {\r\n    private DataSource ds;\r\n\r\n    public void close() throws HibernateException { }\r\n\r\n    public void closeConnection(final Connection conn) throws SQLException {\r\n      conn.close();\r\n    }\r\n\r\n    public void configure(final Properties props) throws HibernateException {\r\n      ds = _CONFIG_TIME_DS_HOLDER.get();\r\n    }\r\n\r\n    public Connection getConnection() throws SQLException {\r\n      return ds.getConnection();\r\n    }\r\n\r\n   public boolean supportsAggressiveRelease() {\r\n     return false;\r\n   }\r\n  }\r\n\r\n  private static final long serialVersionUID = 1L;\r\n  private static HbDataStoreWithDataSource INSTANCE;\r\n\r\n  \/**\r\n   * the data source holder acts as a thread safe bridge between the DSConnectionProvider which is instantiated by Hibernate internally\r\n   * and the data source injected into the session factory during spring configuration time. \r\n   *\/\r\n  private static final ThreadLocal<DataSource> _CONFIG_TIME_DS_HOLDER = new ThreadLocal<DataSource>();\r\n\r\n  public static HbDataStoreWithDataSource getInstance() {\r\n\t\treturn INSTANCE;\r\n  }\r\n\r\n  private final Properties props = new Properties();\r\n\r\n  public HbDataStoreWithDataSource() {\r\n    INSTANCE = this;\r\n\r\n    props.setProperty(PersistenceOptions.ADD_INDEX_FOR_FOREIGN_KEY, \"true\");\r\n    props.setProperty(PersistenceOptions.FETCH_CONTAINMENT_EAGERLY, \"false\");\r\n    props.setProperty(PersistenceOptions.FETCH_ASSOCIATION_EXTRA_LAZY, \"false\");\r\n\r\n    \/\/ tell Teneo to not change the table names, we do this using Hibernate's ImprovedNamingStrategy\r\n    props.setProperty(PersistenceOptions.SQL_CASE_STRATEGY, \"none\");\r\n    props.setProperty(PersistenceOptions.MAXIMUM_SQL_NAME_LENGTH, \"-1\");\r\n  }\r\n\r\n  protected Configuration createConfiguration() {\r\n    Configuration cfg = super.createConfiguration();\r\n    cfg.setNamingStrategy(ImprovedNamingStrategy.INSTANCE);\r\n\r\n    \/\/ only if a DS is injected we register our connection provider\r\n    if (_CONFIG_TIME_DS_HOLDER.get() != null)\r\n      cfg.setProperty(Environment.CONNECTION_PROVIDER, CustomConnectionProvider.class.getName());\r\n    return cfg;\r\n  }\r\n\r\n  public void setDataSource(final DataSource ds) {\r\n    _CONFIG_TIME_DS_HOLDER.set(ds);\r\n  }\r\n\r\n  public final void setHibernateProperties(final Properties hibernateProperties) {\r\n    throw new UnsupportedOperationException();\r\n  }\r\n\r\n  public final void setPersistenceProperties(final Properties persistenceOptions) {\r\n    throw new UnsupportedOperationException();\r\n  }\r\n\r\n  public void setProperties(final Properties props) {\r\n    this.props.putAll(props);\r\n    super.setProperties(this.props);\r\n  }\r\n}\r\n<\/pre>\n<p><b>web.xml:<\/b><\/p>\n<pre class=\"xml\" name=\"code\">\r\n<filter>\r\n  <filter-name>openSessionInViewFilter<\/filter-name>\r\n  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter<\/filter-class>\r\n    <init-param>\r\n      <param-name>singleSession<\/param-name>\r\n      <param-value>true<\/param-value>\r\n    <\/init-param>\r\n    <init-param>\r\n      <param-name>sessionFactoryBeanName<\/param-name>\r\n      <param-value>realSessionFactory<\/param-value>\r\n    <\/init-param>\r\n<\/filter>\r\n<filter-mapping>\r\n  <filter-name>openSessionInViewFilter<\/filter-name>\r\n  <url-pattern>\/*<\/url-pattern>\r\n  <dispatcher>REQUEST<\/dispatcher>\r\n  <dispatcher>ERROR<\/dispatcher>\r\n<\/filter-mapping>\r\n<\/pre>\n<p><b>applicationContext.xml:<\/b><\/p>\n<pre class=\"xml\" name=\"code\">\r\n<beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:context=\"http:\/\/www.springframework.org\/schema\/context\" xmlns:p=\"http:\/\/www.springframework.org\/schema\/p\" xmlns:tx=\"http:\/\/www.springframework.org\/schema\/tx\" xsi:schemaLocation=\" http:\/\/www.springframework.org\/schema\/context http:\/\/www.springframework.org\/schema\/context\/spring-context-3.0.xsd http:\/\/www.springframework.org\/schema\/beans http:\/\/www.springframework.org\/schema\/beans\/spring-beans-3.0.xsd  http:\/\/www.springframework.org\/schema\/tx http:\/\/www.springframework.org\/schema\/tx\/spring-tx-3.0.xsd\" default-lazy-init=\"false\">\r\n\r\n  <context:property-placeholder location=\"WEB-INF\/application.spring.properties\"><\/context:property-placeholder>\r\n\r\n  <bean id=\"dataSource\" class=\"org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy\">\r\n    <property name=\"targetDataSource\">\r\n      <bean class=\"org.apache.commons.dbcp.BasicDataSource\" init-method=\"createDataSource\" destroy-method=\"close\">\r\n        <property name=\"driverClassName\">${jdbc.driverClassName}<\/property>\r\n        <property name=\"url\">${jdbc.url}<\/property>\r\n        <property name=\"username\">${jdbc.username}<\/property>\r\n        <property name=\"password\">${jdbc.password}<\/property>\r\n        <property name=\"defaultAutoCommit\">false<\/property>\r\n        <property name=\"maxActive\">${jdbc.maxConnections}<\/property>\r\n        <property name=\"maxIdle\">${jdbc.minConnections}<\/property>\r\n        <property name=\"maxWait\">10000<\/property>\r\n        <property name=\"initialSize\">${jdbc.minConnections}<\/property>\r\n        <property name=\"validationQuery\">${jdbc.validationQuery}<\/property>\r\n        <property name=\"testOnBorrow\">false<\/property>\r\n        <property name=\"testWhileIdle\">true<\/property>\r\n        <property name=\"timeBetweenEvictionRunsMillis\">1200000<\/property>\r\n        <property name=\"minEvictableIdleTimeMillis\">1800000<\/property>\r\n        <property name=\"numTestsPerEvictionRun\">5<\/property>\r\n      <\/bean>\r\n    <\/property>\r\n  <\/bean>\r\n\r\n  <bean id=\"teneoSessionFactory\" class=\"de.sebthom.util.HbSessionDataStoreWithDataSource\" init-method=\"initialize\" p:name=\"myDataStore\" p:dataSource-ref=\"dataSource\">\r\n    <property name=\"properties\"><value>\r\n      hibernate.dialect=${hibernate.dialect}\r\n      hibernate.hbm2ddl.auto=${hibernate.hbm2ddl.auto}\r\n      hibernate.jdbc.batch_size=2000\r\n      hibernate.show_sql=${hibernate.show_sql}\r\n      hibernate.transaction.auto_close_session=false\r\n      hibernate.current_session_context_class=org.springframework.orm.hibernate3.SpringSessionContext\r\n      hibernate.transaction.factory_class=org.springframework.orm.hibernate3.SpringTransactionFactory\r\n    <\/value><\/property>\r\n    <property name=\"EPackageClasses\"><list><value>com.acme.ShopPackageImpl<\/value><\/list><\/property> \r\n  <\/bean>\r\n\r\n  <bean id=\"realSessionFactory\" factory-bean=\"teneoSessionFactory\" factory-method=\"getSessionFactory\"><\/bean>\r\n\r\n  <bean id=\"transactionManager\" class=\"org.springframework.orm.hibernate3.HibernateTransactionManager\" p:sessionFactory-ref=\"realSessionFactory\" p:nestedTransactionAllowed=\"true\" p:earlyFlushBeforeCommit=\"true\"><\/bean>\r\n\r\n  <tx:annotation-driven transaction-manager=\"transactionManager\"><\/tx:annotation-driven>\r\n\r\n<\/beans>\r\n<\/pre>\n<p><b>Comments:<\/b><\/p>\n<ol>\n<li><b>VERY IMPORTANT:<\/b>The <b>HibernateTransactionManager<\/b> 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:\n<pre>\r\nTransactionSynchronizationManager.bindResource(Object, Object) line: 170\t\r\nat OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 183\r\n=> results in TransactionSynchronizationManager.bindResource(<b>HbSessionDataStore<\/b>, SessionHolder) => as key the <b>Teneo SessionFactory<\/b> is used\r\n\r\nTransactionSynchronizationManager.bindResource(Object, Object) line: 170\t\r\nat SessionFactoryUtils.doGetSession(SessionFactory, Interceptor, SQLExceptionTranslator, boolean) line: 339\t\r\nat SessionFactoryUtils.doGetSession(SessionFactory, boolean) line: 256\t\r\nat SpringSessionContext.currentSession() line: 60\t\r\nat SessionFactoryImpl.getCurrentSession() line: 700\t\r\nat HbSessionDataStore(HbBaseSessionDataStore).getCurrentSession() line: 161\t\r\n=> results in TransactionSynchronizationManager.bindResource(<b>SessionFactoryImpl<\/b>, SessionHolder) => as key the <b>Hibernate SessionFactory<\/b> is used\r\n\r\nTransactionSynchronizationManager.bindResource(Object, Object) line: 170\t\r\nat HibernateTransactionManager.doBegin(Object, TransactionDefinition) line: 577\t\r\nat HibernateTransactionManager(AbstractPlatformTransactionManager).getTransaction(TransactionDefinition) line: 371\r\nat TransactionInterceptor(TransactionAspectSupport).createTransactionIfNecessary(PlatformTransactionManager, TransactionAttribute, String) line: 316\t\r\nat TransactionInterceptor.invoke(MethodInvocation) line: 105\t\r\nat ReflectiveMethodInvocation.proceed() line: 172\r\n=> results in TransactionSynchronizationManager.bindResource(<b>HbSessionDataStore<\/b>, SessionHolder) => as key the <b>Teneo SessionFactory<\/b> is used\r\n<\/pre>\n<li><b>defaultAutoCommit<\/b> is set to <b>false<\/b> to ensure that Spring has full control over the transaction and that the connection pool is not committing statements automatically based on it&#8217;s own strategies.\n<li>The example uses an extended version of the <b>org.eclipse.emf.teneo.hibernate.HbSessionDataStore<\/b> class that allows the usage of a DataSource object and that configures Teneo to not alter the table, column names but let&#8217;s Hibernate handle this via its ImprovedNamingStrategy.\n<li><b>hibernate.transaction.auto_close_session<\/b> is set to <b>false<\/b> to avoid &#8220;SessionException: Session is closed!&#8221; in conjunction with the OpenSessionInViewListener.\n<li><b>hibernate.current_session_context_class<\/b> and <b>hibernate.transaction.factory_class<\/b> are set to special Spring implementations to avoid &#8220;org.hibernate.HibernateException: No CurrentSessionContext configured!&#8221; when not using Spring Hibernate Template via HibernateDAOSupport. It is not recommended to use the Hibernate Template anymore, see <a href=\"http:\/\/blog.springsource.com\/2007\/06\/26\/so-should-you-still-use-springs-hibernatetemplate-andor-jpatemplate\/\">http:\/\/blog.springsource.com\/2007\/06\/26\/so-should-you-still-use-springs-hibernatetemplate-andor-jpatemplate\/<\/a>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>While trying to get an application working with<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[43],"tags":[96,88,93,30,97,94,92,95],"class_list":["post-152","post","type-post","status-publish","format-standard","hentry","category-java-coding","tag-dbcp","tag-emf","tag-hibernate","tag-java","tag-persistence","tag-spring","tag-teneo","tag-transaction"],"_links":{"self":[{"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/posts\/152","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/comments?post=152"}],"version-history":[{"count":0,"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/posts\/152\/revisions"}],"wp:attachment":[{"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/media?parent=152"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/categories?post=152"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/tags?post=152"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}