Announcement Announcement Module
Collapse
No announcement yet.
Transactions are not starting Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Transactions are not starting

    This post is coming in to parts, because this is my first post, and forum does not allow urls in first post.

  • #2
    Hi all

    I'm making larger application and I found it had problems with OpenSessionInView and transactions (extremely slow). I decided to try out annotation based transaction management with extremely simple application to test out what I was doing wrong.

    I found out that transactions are not started with @Transactional even though HibernateTransactionManager is configured and <tx:annotation-driven /> is used.

    I am probably missing something, could someone point out what I am doing wrong, or point to documentation what I've missed.

    I am using spring 2.5.6 and hibernate 3.2 (tried 3.3, no effect).

    My application-context.xml is following:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/aop
                            http://www.springframework.org/schema/aop/spring-aop.xsd
                            http://www.springframework.org/schema/tx
                            http://www.springframework.org/schema/tx/spring-tx.xsd
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context.xsd">
    
    
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName">
                <value>org.h2.Driver</value>
            </property>
            <property name="url">
                <value>jdbc:h2:tcp://localhost/~/test</value>
            </property>
            <property name="username" value="sa" />
            <property name="password" value="" />
        </bean>
    
        <bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
            <property name="properties">
                <props>
                    <prop key="hibernate.hbm2ddl.auto">update</prop>
                    <prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
                    <prop key="hibernate.show_sql">false</prop>
                    <prop key="hibernate.format_sql">true</prop>
                    <prop key="hibernate.c3p0.minPoolSize">5</prop>
                    <prop key="hibernate.c3p0.maxPoolSize">20</prop>
                    <prop key="hibernate.c3p0.timeout">600</prop>
                    <prop key="hibernate.c3p0.max_statement">50</prop>
                    <prop key="hibernate.c3p0.testConnectionOnCheckout">false</prop>
                </props>
            </property>
        </bean>
    
        <!-- Also tried mode="aspectj" but it made no difference -->
        <tx:annotation-driven transaction-manager="transactionManager" mode="proxy"/>
    
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="annotatedClasses">
                <list>
                    <value>spring.test.model.Event</value>
                </list>
            </property>
    
            <property name="hibernateProperties" ref="hibernateProperties"/>
    
            <property name="entityInterceptor" ref="hibernateInterceptor" />
        </bean>
    
        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
        </bean>
    
        <bean id="dao" class="spring.test.dao.PersistenceManagerImpl">
            <property name="sessionFactory" ref="sessionFactory" />
        </bean>
    
        <bean id="hibernateInterceptor" class="spring.test.TransactionInterceptor" />
    
        <bean id="transactionTester" class="spring.test.TransactionTesterServiceImpl">
            <property name="dao" ref="dao" />
        </bean>
    
        <bean id="main" class="spring.test.Main">
            <constructor-arg ref="transactionTester" />
        </bean>
    </beans>
    Code of the relevant classes below, please ask if I didn't provide enough information.

    In transactionInterceptor only postFlush and preFlush get called.

    Code:
    public class TransactionInterceptor extends EmptyInterceptor {
    
        Logger log = Logger.getLogger(getClass());
    
        public void afterTransactionBegin(final Transaction tx) {
            log.debug("TransactionInterceptor.afterTransactionBegin() " + tx);
        }
    
        public void afterTransactionCompletion(final Transaction tx) {
            log.debug("TransactionInterceptor.afterTransactionCompletion() " + tx);
        }
    
        public void beforeTransactionCompletion(final Transaction tx) {
            log.debug("TransactionInterceptor.beforeTransactionCompletion() " + tx);
        }
    
        public void postFlush(final Iterator entities) {
            log.debug("TransactionInterceptor.postFlush()");
        }
    
        public void preFlush(final Iterator entities) {
            log.debug("TransactionInterceptor.preFlush()");
        }
    }
    Main class.

    Code:
    public class Main {
    
        private static final Logger log = Logger.getLogger(Main.class);
    
        public static void main(final String[] args) {
    
            log.debug("Main.main() Application starting!");
            final XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("res/application-context.xml"));
    
            final Main main = (Main) factory.getBean("main");
    
            main.createTestData();
        }
    
        private final TransactionTesterService tts;
    
        public Main(final TransactionTesterService testerService) {
            tts = testerService;
        }
    
    
    // Also tried transactional here (better choise naturally to insert all
    // events in same transaction, but no effect on transactions)
    //    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
        public void createTestData() {
            for (int i = 0; i < 100; ++i) {
                final Event e = new Event();
                e.setDate(new Date());
                e.setTitle("title " + (i + 1));
                tts.save(e);
            }
        }
    }
    Here I also tested programmatic transaction management and it seems to be "working" (transaction-interceptor methods get called). Although program freezes after 7 inserts... And I keep wondering why declarative version is not working.

    Code:
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public class TransactionTesterServiceImpl implements TransactionTesterService {
        private PersistenceManager dao;
    
        public void setDao(final PersistenceManager dao) {
            this.dao = dao;
        }
    
        @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
        public Event save(final Event event) {
    //        final Transaction transaction = dao.createTransaction();
            final Event e = dao.save(event);
    //        transaction.commit();
            return e;
        }
    
        public List<Event> loadAll() {
            return dao.findAll(Event.class);
        }
    }
    And the persistenceManagerImpl.

    Code:
    public class PersistenceManagerImpl extends HibernateDaoSupport implements PersistenceManager {
    
        public <T extends AbstractModelEntity> List<T> findAll(final Class<T> entity) {
            final List<T> results = getHibernateTemplate().loadAll(entity);
            return results;
        }
    
        public <T extends AbstractModelEntity> T findbyId(final Class<T> entityClass,
                final Long id) {
            final T object = (T) getHibernateTemplate().get(entityClass, id);
            return object;
        }
    
        public <T extends AbstractModelEntity> T save(final T entity) {
            getHibernateTemplate().saveOrUpdate(entity);
            return entity;
        }
    
        public Transaction createTransaction() {
            return getSession().beginTransaction();
        }
    }
    All the classes have obvious interfaces but I chose to leave them out to shorten this (already quite lengthy post).

    Comment


    • #3
      I continued digging on subject and came across couple of promising settings for application-context.xml. I tried adding:

      Code:
      <aop:aspectj-autoproxy proxy-target-class="true" />
      <context:annotation-config />
      to the beginning of the application-context.xml, but these made no difference.

      I am willing to admit that I am seriously missing something here. I've read way too many tutorials, manuals and threads in past week, but I don't seem to be able to find solution to my problem(s). Any help is greatly appreciated.

      Comment


      • #4
        1. Spring transactions are built on top of the Spring AOP and you use self-calls at your example. Check the reference for more details - 6.6.1. Understanding AOP proxies;
        2. You use BeanFactory instead of ApplicationContext. That means that all post-processor-based stuff in uninitialized. Reference - 3.8.1. BeanFactory or ApplicationContext?;

        Comment


        • #5
          Thank You!

          Using ClassPathXmlApplicationContext (or FileSystemXmlApplicationContext) resolved problems in this test application. I kept reading and reading all about transaction management and orm-integration and had missed this completely.

          Using ApplicationContext and <tx:annotation-driven mode="proxy"/> seems to be enough and no proxy factories are needed. And changing proxy-target-class to false removes CGLIB-warnings.

          Comment

          Working...
          X