Announcement Announcement Module
Collapse
No announcement yet.
Committ problems with @Transactional annotations Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Committ problems with @Transactional annotations

    Hello folks,

    I am currently trying to implement annotation-based transactions with Spring 2.x and Hibernate with Oracle. So far I configured the <tx:annotation-driven>-tag and the corresponding transaction manager:

    PHP Code:
        <!-- transaction manager -->
        <
    bean id="transactionManager"
            
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <
    property name="dataSource" ref="dataSource"/>
        </
    bean>

        <
    bean id="sessionFactory"
            
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
            <
    property name="configLocation"
                
    value="classpath:hibernate.cfg.xml" />
        </
    bean
    Every service class implementation has a @Transactional annotation attached:

    Code:
    @Transactional
    public class UserServiceImpl ......
    All read operations have "@Transactional(readOnly=true)".

    When using the services to persist some entity there seems to be no problem:

    Code:
    Hibernate: insert into SCHEMA.USER ...........
    ... however the data is not committed to the database. There is no new entry! Where to configure the commit command?
    Last edited by Rapthor; Jul 18th, 2007, 03:42 PM.

  • #2
    If you are using Hibernate, shouldn't you be using the HibernateTransactionManager instead? Also you've marked the transaction as readOnly but you want to commit?
    Last edited by karldmoore; Aug 27th, 2007, 05:29 PM.

    Comment


    • #3
      Originally posted by karldmoore View Post
      If you are using Hibernate, shouldn't you be using the HibernateTransactionManager instead? Also you've marked the transaction as readOnly but you want to commit?
      The problem is I cannot use HibernateTransactionManager since third party webapps will use my services and they cannot see Hibernate's ConnectionWrapper interface from their classloaders (which seems to be an integral part of Hibernate's Transaction strategy). Using the configuration I described above seems to work partly ... however actions are not committed.

      ReadOnly is only used for "find*-methods". Methods like "makePersistent" have NO "@Transactional(readOnly=true)"-attribute. They fall back to the annotation defined for the service-class (@Transactional). I have done this following the Spring documentation.

      In fact my services are using DAOs which themselves have the SessionFactory you can see above. Is that useless concerning the configuration I made so far? (Using "DataSourceTransactionManager" instead of "HibernateTransactionManager"?)

      Sorry to bother you with questions like that, but the problem with the ConnectionWrapper-interface spoiled me for tooooooooo long. So I really really hope that discarding Hibernate's Transaction Manager can solve my problems.

      Thanks in advance ...

      (I am about to try using "<tx:advice id="txAdvice" transaction-manager="transactionManager">....". I think I will have the same committ-problem with that approach.)

      Comment


      • #4
        PHP Code:
            <tx:advice id="txAdvice" transaction-manager="transactionManager">
                <
        tx:attributes>
                    <
        tx:method name="find*" read-only="true" />
                    <
        tx:method name="*" />
                </
        tx:attributes>
            </
        tx:advice>

            <
        aop:config>
                <
        aop:pointcut id="serviceMethods"
                    
        expression="execution(* com.mycomapny.service.*.*(..))" />
                <
        aop:advisor advice-ref="txAdvice"
                    
        pointcut-ref="serviceMethods" />
            </
        aop:config
        "<tx:advice..." doesn't work either. The service methods being called by the second webapp are not executed within a transaction. Even though calls from within the first webapp that provides the services are in deed transactionized.

        Code:
        org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
        	at org.springframework.orm.hibernate3.AbstractSessionFactoryBean$TransactionAwareInvocationHandler.invoke(AbstractSessionFactoryBean.java:299)

        Comment


        • #5
          Originally posted by Rapthor View Post
          Sorry to bother you with questions like that, but the problem with the ConnectionWrapper-interface spoiled me for tooooooooo long. So I really really hope that discarding Hibernate's Transaction Manager can solve my problems.
          To use Hibernate and transactions you need HibernateTransactionManager, and there is no way about it.

          But, you could try to explain us the problem with Hibernate ConnectionWrappers - is sounds like something that should be fairly easy to work around.

          Comment


          • #6
            Originally posted by dejanp View Post
            To use Hibernate and transactions you need HibernateTransactionManager, and there is no way about it.

            But, you could try to explain us the problem with Hibernate ConnectionWrappers - is sounds like something that should be fairly easy to work around.
            I posted a thread on this topic a few weeks ago but got no response that solved the problem:

            http://forum.springframework.org/sho...781#post128781

            (See the picture tomcat.jpg in the 3rd post. It describes best what my current situation is.)

            I even tried to use <tx:advice> like described above with HibernateTransactionManager and got the same ConnectionWrapper exception.

            Comment


            • #7
              You can't reference child classloaders from the parent classloaders:

              Class A (Classloader 1)
              Class B (Classloader 2)
              Class C (Classloader 1)

              You can't have A->B->C. You can put B in classloader 1 or you can put C in classloader 2.

              In other words: pack your jar with Hibernate jars. No matter if both are in the shared lib or in the web-app, but they need to be together.

              Btw, I'd say using a shared lib is not a realistic solution. It creates a hard dependency between application version and your library version. When you change the library all apps _must_ be rewritten at the same time, you need to stop the server, change the library, redeploy all the apps, restart the server. Not very nice and, at larger scale, absolutely unfeasible.

              Comment


              • #8
                Seems as if I will have to put the webapps together to avoid the bad style you mentioned. Unfortunately I am going to raise another bad style to put all of the persistence, application and ui components into one single webapp. I would have like to seperate persistence and application from ui without using any EJB application server.

                Nevertheless, thanks for the advice!

                Comment


                • #9
                  By putting a jar file in one or the other classloader you do not separate anything imo.

                  The separation is done on the application design level, not on the deployment/packaging level. If your application is well designed, so that it logically separates differenent concerns then the packaging doesn't really matter and is usually done in the way that allows most flexibility (what that means is up to your needs).

                  Comment


                  • #10
                    Originally posted by dejanp View Post
                    By putting a jar file in one or the other classloader you do not separate anything imo.

                    The separation is done on the application design level, not on the deployment/packaging level. If your application is well designed, so that it logically separates differenent concerns then the packaging doesn't really matter and is usually done in the way that allows most flexibility (what that means is up to your needs).
                    I was searching for a way to keep transactions within one webapp in order to provide "Value Objects" (or "Transfer Objects") at the surface. I am really surprised about not being able to isolate all the transaction stuff from other webapps. I still wonder if there is a way to do transactions within my logic and persistence webapp only and have another webapp access only the "Value Objects" that represent the results of those transactions.

                    I think of dynamically changing the UI webapp that handles "Value Objects" without having to shut down the whole webapp that contains the logic stuff. Furthermore I am about to create another webservice application that should use the Value Objects just like the UI webapp should do.

                    Comment


                    • #11
                      Of course you can do that, but it has nothing to do with packaging. If your web-app uses a certain facade interface to do persistence/transactions then that's it - you isolated it. You can put the implementation of that facade anywhere you want (packed in war/lib, on the app-server classpath or exposed as a remote service) , it will not change it's semantic.

                      Comment

                      Working...
                      X