0 Replies Latest reply on Oct 27, 2008 9:19 AM by martin.ahrer

    Spring integration: transactional method, read only flag not working

    martin.ahrer

      I'm trying to utilize Spring managed transactions using Springs @Transactional annotation. Methods that are supposed to read data only also carry the read only flag.
      In order to test that this is working I created a method that tries to break this.


      It executes a entitymanager.merge() operation. Surprisingly the data is written to the database even though the method is marked read only. Just right after the merge() operation it seems that the hibernate session/persistence context is flushed. As far as I know Spring is setting the flush mode MANUAL for read only marked methods.
      Also I have marked the Seam methods with flush mode MANUAL!


      I'm not sure if I'm doing something fundamentally wrong. I would appreciate any hints on that!


      Here is the hibernate config (from persistence.xml)


      <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
      <property name="hibernate.connection.username" value="sa" />
      <property name="hibernate.connection.autocommit" value="false" />
      <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:pac" />
      <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
      <property name="hibernate.transaction.manager_lookup_class"
           value="org.hibernate.transaction.JBossTransactionManagerLookup" />
      <property name="hibernate.hbm2ddl.auto" value="update" />
      <property name="hibernate.show_sql" value="true" />
      <property name="hibernate.use_sql_comments" value="true" />
      <property name="hibernate.format_sql" value="true" />
      <property name="hibernate.connection.default_schema" value="DBO" />
      <property name="hibernate.transaction.flush_before_completion" value="false"/>
      



      Seam is configured in components.xml


      <core:init debug="true"  transaction-management-enabled="false" />
      <spring:context-loader config-locations="classpath:/beans/seamContext.xml" />
      <persistence:managed-persistence-context name="entityManager" auto-create="true"
           entity-manager-factory="#{entityManagerFactorySpring}" />
      <transaction:no-transaction />
      


      So as you see Seam is not responsible for handling transactions at all!


      The spring stuff is configured


      <context:annotation-config />
      <tx:annotation-driven proxy-target-class="true"/>
      
      <seam:configure-scopes />
      
      <!-- The entity manager factory that will be used to hand off entity managers to Spring based components-->
      <bean id="entityManagerFactory"
           class="org.jboss.seam.ioc.spring.SeamManagedEntityManagerFactoryBean">
           <property name="persistenceContextName" value="entityManager" />
      </bean>
      
      <!-- The entity manager factory provided to Seam for creating a seam managed entity manager factory -->
      <bean id="entityManagerFactorySpring"
           class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
           p:persistenceUnitName="pac" p:persistenceProviderClass="org.hibernate.ejb.HibernatePersistence">
           <property name="persistenceUnitManager">
                <bean
                     class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
                     <property name="persistenceXmlLocations"
                          value="classpath*:META-INF/persistence.xml" />
                </bean>
           </property>
      </bean>
      
      <!-- The transaction manager -->
      <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
           <property name="entityManagerFactory" ref="entityManagerFactory" />
      </bean>
      

           
           
      The seam component that invokes the transactional method looks as     


      @Create
      @Begin(flushMode = FlushModeType.MANUAL, join = false)
      public void create() {
           return;
      }
      
      @Conversational
      public String createPersonWithReadOnlyTransaction() {
           ...
           comp.saveWithReadOnlyTransaction(person);
           ...
           return "SUCCESS";
      }     
      


           
      And the transactional method


      @Transactional(readOnly=true)
      public Person saveWithReadOnlyTransaction(Person person) {
           return getJpaTemplate().merge(person);
      }