Uploaded image for project: 'LAMS Development'
  1. LAMS Development
  2. LDEV-57

Check transactions are working correctly with tools

    Details

    • Type: Task
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 2.0
    • Fix Version/s: 2.4
    • Component/s: Tools
    • Labels:
      None

      Description

      The transactions appear to be correct, but there is INFO entry in the hibernate log that is a worry:

      15:26:21,187 [main] INFO org.hibernate.transaction.TransactionFactoryFactory - Using default transaction strategy (direct JDBC transactions)
      15:26:21,218 [main] INFO org.hibernate.transaction.TransactionManagerLookupFactory - No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)

      We were thinking of using the second-level cache. Is this feasible or does JTA kill it?

        Activity

        Hide
        fionam Fiona Malikoff added a comment -
        There is definitely a problem with transactions with the tools.

        In Forum, when you save a design (in authoring), the createRootTopic() method isn't behaving correctly. The records are written to the database as soon as they are inserted in Hibernate. The method is wrapped up in a Spring transaction, but there is something wrong with Hibernate/JDBC.

        Yes if the same method is called from monitoring (during the creation of a lesson) then it works fine - the database isn't updated until the transaction ends.

        Normally within a transaction, the first db call triggers "set autocommit=0 ", then does the queries/updates. At the end of the transaction, it does "set autocommit=1". This can be seen in the mysql log by adding the entry

        log="C:/temp/mysql.log"

        to mysql.ini.


        But when it runs within Forum, the "set autocommit=0" doesn't happen.
        Show
        fionam Fiona Malikoff added a comment - There is definitely a problem with transactions with the tools. In Forum, when you save a design (in authoring), the createRootTopic() method isn't behaving correctly. The records are written to the database as soon as they are inserted in Hibernate. The method is wrapped up in a Spring transaction, but there is something wrong with Hibernate/JDBC. Yes if the same method is called from monitoring (during the creation of a lesson) then it works fine - the database isn't updated until the transaction ends. Normally within a transaction, the first db call triggers "set autocommit=0 ", then does the queries/updates. At the end of the transaction, it does "set autocommit=1". This can be seen in the mysql log by adding the entry log="C:/temp/mysql.log" to mysql.ini. But when it runs within Forum, the "set autocommit=0" doesn't happen.
        Hide
        steven Dapeng Ni (Inactive) added a comment -
        We are using OpenSessionInViewFilter over most STRUST action method (view). It causes some side effect on transaction methods.

        I did some test. Some weird things happen if there are over 1 spring-controlled transaction methods in this signle session. Only the first transaction method could work normally. But the following methods will become non-transactional methods!

        This is reason why createRootTopic() method does not work in LearningAction (which must include some other transaction methods before createRootTopic()), but works in monitoring.

        I cannot give a fix yet :(
        Show
        steven Dapeng Ni (Inactive) added a comment - We are using OpenSessionInViewFilter over most STRUST action method (view). It causes some side effect on transaction methods. I did some test. Some weird things happen if there are over 1 spring-controlled transaction methods in this signle session. Only the first transaction method could work normally. But the following methods will become non-transactional methods! This is reason why createRootTopic() method does not work in LearningAction (which must include some other transaction methods before createRootTopic()), but works in monitoring. I cannot give a fix yet :(
        Hide
        marcin Marcin Cieslak added a comment -
        The situation is more or less like this:

        1. An user presses a button.

        2. HTTP Request goes to Filter Chain.

        3. One of our Filters is CustomizedOpenSessionInViewFilter in lams_common/.../util.
        This filter opens a single session for the whole Request. The way we use it roughly reminds this pattern:
        http://www.hibernate.org/43.html
        Our filter is "custom" as it set session FlushMode to AUTO, instead of the original NEVER.

        4. Request goes to an Action method, for example to save a tool's content.

        5. After some validation, we get to a transactional method, like the one that saves the content. Such method is declared in Spring context file as transactional (proxy, PROPAGATION_REQUIRED etc.)

        6. "Proxying" of service methods works fine. The method call goes through Spring first wrapper, rather than straight to tool service.
        At this moment Spring creates a new transaction. This transaction wraps all Hibernate statements in the given service method call. This works, but
        SPRING DOES NOT BEGIN THE TRANSACTION
        like it should.

        I checked that transaction does exist and its name is equal to service method's (so Dapeng Ni was slightly wrong when he wrote "the following methods will become non-transactional methods"). The transaction was not started - connection was still set to autocommit mode (and it usually is not, while in transaction). I started the transaction myself and only then autocommit mode was set to false.

        Not only that, the transaction will also NOT ROLL BACK. Of course if it was not started, it should not roll back. But even after I started it myself and then thrown an exception (which should cause a roll back) or set the current transaction as ROLLBACK_ONLY (which should do a roll back at session close), changes in DB would not be reverted.

        Also, please notice one thing. Sometimes in the code we are using Flush method in Hibernate. Also, like I said in point 3, our FlushMode is set to AUTO, so we allow Hibernate to Flush in some situations. Flush puts the changes into DB. But even if they are already in the DB, they *can be reverted by a transaction roll back*.

        This explains the behaviour described by Fiona:
        "The records are written to the database as soon as they are inserted in Hibernate. The method is wrapped up in a Spring transaction, but there is something wrong with Hibernate/JDBC."
        There is nothing wrong with that. Hibernate Flushes immediately after creating new objects - that's OK. If we make changes to these objects, they are not reflected in the DB until we Flush - that's also OK. But our problem is that we can not revert those changes - *roll back does not work correctly*.

        This Flush policy explains also why sometimes things "work". The next step for Request is:

        7. Session is closed. If there were no errors, it is closed by our CustomizedOpenSessionInViewFilter. We have a Flush there, just before close. All pending SQL statements are executed. This looks like a transaction commit, but it is NOT a commit, because there is no transaction running!
        If there were errors, the session is also closed, but by an internal Spring method. This method does not Flush. It looks like a roll back, but it is NOT a roll back! The pending statements are simply discarded and never executed in DB. *But whatever was Flushed earlier, stays in the DB* That's a major difference between Flush and commit.
        Right now we base on Flushes. We should more depend on transactions.

        Also, the behaviour described by Fiona:
        "So when a later service level transaction fails, it triggers a rollback on the database, which then rolls back all the changes for the previous service level transactions, so in practice the whole lot does roll back."
        seems strange. It might suit us, but it is wrong. Only the changes made by the given transaction should be rolled back, not all the previous... If it's happening, then it's more a side effect than desired behaviour. And this means that there can be other side effects too.

        Our situation is very similar to this one:
        http://forum.springsource.org/showthread.php?t=15486
        but no matter what I do with these settings:

        <prop key="hibernate.connection.release_mode">auto</prop>
        <prop key="hibernate.current_session_context_class">jta</prop>
        <prop key="hibernate.transaction.auto_close_session">true</prop>

        which can be found also in
        http://forum.springsource.org/showthread.php?t=63532

        I can't get a good effect. I think our situation is slightly different. It is not about JDBC connections, it is about transactions themselves.

        Possible reasons are:
        http://opensource.atlassian.com/projects/hibernate/browse/HHH-1062
        http://opensource.atlassian.com/projects/hibernate/browse/HHH-1410
        or our LDEV-2201

        Whatever is the reason, it seems that our OpenSessionInViewFilter/JTA/Hibernate/JBoss combination causes some serious problems. I will come back to this JIRA after resolving LDEV-2201 and LDEV-2071, as they will change the situation and the problem may become solved as a side effect. On the other hand some new problems may appear, so there is no point in solving this issue right now.
        Show
        marcin Marcin Cieslak added a comment - The situation is more or less like this: 1. An user presses a button. 2. HTTP Request goes to Filter Chain. 3. One of our Filters is CustomizedOpenSessionInViewFilter in lams_common/.../util. This filter opens a single session for the whole Request. The way we use it roughly reminds this pattern: http://www.hibernate.org/43.html Our filter is "custom" as it set session FlushMode to AUTO, instead of the original NEVER. 4. Request goes to an Action method, for example to save a tool's content. 5. After some validation, we get to a transactional method, like the one that saves the content. Such method is declared in Spring context file as transactional (proxy, PROPAGATION_REQUIRED etc.) 6. "Proxying" of service methods works fine. The method call goes through Spring first wrapper, rather than straight to tool service. At this moment Spring creates a new transaction. This transaction wraps all Hibernate statements in the given service method call. This works, but SPRING DOES NOT BEGIN THE TRANSACTION like it should. I checked that transaction does exist and its name is equal to service method's (so Dapeng Ni was slightly wrong when he wrote "the following methods will become non-transactional methods"). The transaction was not started - connection was still set to autocommit mode (and it usually is not, while in transaction). I started the transaction myself and only then autocommit mode was set to false. Not only that, the transaction will also NOT ROLL BACK. Of course if it was not started, it should not roll back. But even after I started it myself and then thrown an exception (which should cause a roll back) or set the current transaction as ROLLBACK_ONLY (which should do a roll back at session close), changes in DB would not be reverted. Also, please notice one thing. Sometimes in the code we are using Flush method in Hibernate. Also, like I said in point 3, our FlushMode is set to AUTO, so we allow Hibernate to Flush in some situations. Flush puts the changes into DB. But even if they are already in the DB, they *can be reverted by a transaction roll back*. This explains the behaviour described by Fiona: "The records are written to the database as soon as they are inserted in Hibernate. The method is wrapped up in a Spring transaction, but there is something wrong with Hibernate/JDBC." There is nothing wrong with that. Hibernate Flushes immediately after creating new objects - that's OK. If we make changes to these objects, they are not reflected in the DB until we Flush - that's also OK. But our problem is that we can not revert those changes - *roll back does not work correctly*. This Flush policy explains also why sometimes things "work". The next step for Request is: 7. Session is closed. If there were no errors, it is closed by our CustomizedOpenSessionInViewFilter. We have a Flush there, just before close. All pending SQL statements are executed. This looks like a transaction commit, but it is NOT a commit, because there is no transaction running! If there were errors, the session is also closed, but by an internal Spring method. This method does not Flush. It looks like a roll back, but it is NOT a roll back! The pending statements are simply discarded and never executed in DB. *But whatever was Flushed earlier, stays in the DB* That's a major difference between Flush and commit. Right now we base on Flushes. We should more depend on transactions. Also, the behaviour described by Fiona: "So when a later service level transaction fails, it triggers a rollback on the database, which then rolls back all the changes for the previous service level transactions, so in practice the whole lot does roll back." seems strange. It might suit us, but it is wrong. Only the changes made by the given transaction should be rolled back, not all the previous... If it's happening, then it's more a side effect than desired behaviour. And this means that there can be other side effects too. Our situation is very similar to this one: http://forum.springsource.org/showthread.php?t=15486 but no matter what I do with these settings: <prop key="hibernate.connection.release_mode">auto</prop> <prop key="hibernate.current_session_context_class">jta</prop> <prop key="hibernate.transaction.auto_close_session">true</prop> which can be found also in http://forum.springsource.org/showthread.php?t=63532 I can't get a good effect. I think our situation is slightly different. It is not about JDBC connections, it is about transactions themselves. Possible reasons are: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1062 http://opensource.atlassian.com/projects/hibernate/browse/HHH-1410 or our LDEV-2201 Whatever is the reason, it seems that our OpenSessionInViewFilter/JTA/Hibernate/JBoss combination causes some serious problems. I will come back to this JIRA after resolving LDEV-2201 and LDEV-2071 , as they will change the situation and the problem may become solved as a side effect. On the other hand some new problems may appear, so there is no point in solving this issue right now.
        Hide
        marcin Marcin Cieslak added a comment -
        This ancient JIRA is now resolved.
        Please see LDEV-2071 and comments on TRANSACTIONS (issue #10) for explanation.
        Transactions in Tools work now properly.
        Show
        marcin Marcin Cieslak added a comment - This ancient JIRA is now resolved. Please see LDEV-2071 and comments on TRANSACTIONS (issue #10) for explanation. Transactions in Tools work now properly.
        Hide
        ernieg Ernie Ghiglione added a comment -
        Closing follow LDEV-2071
        Show
        ernieg Ernie Ghiglione added a comment - Closing follow LDEV-2071

          People

          • Assignee:
            marcin Marcin Cieslak
            Reporter:
            fionam Fiona Malikoff
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development