Announcement Announcement Module
Collapse
No announcement yet.
Rollback in Weblogic SLSB won't allow any reads afterwards Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Rollback in Weblogic SLSB won't allow any reads afterwards

    Our application uses SLSBs which act as a thin facade layer that call directly into Spring POJO services. The session beans all have a transaction attribute of Supports. All of these service classes have been proxied, using the MatchAlwaysTransactionAttributeSource interceptor to ensure that each service call will be within a transaction. All data access occurs within the services.

    In addition, we have a transaction filter in our web front-end which starts the transaction and keeps it open for the life of the request. Reason for this is eventually, our front-end will call our Spring services directly, instead of the SLSBs. That way, multiple service calls in the front end can participate in the same transaction. Unfortunately, not all of our front end code has been updated to call the services, some still do call the SLSBs.

    What happens on Weblogic is, if I call a method on a SLSB and an error occurs, the transaction is marked for rollback (which is all good). But then, in some cases, the front end makes other calls to the back end to retrieve certain data so an error page can be displayed. These extra calls after the rollback fail, getting an error such as:

    org.springframework.jdbc.UncategorizedSQLException : (Hibernate operation): encountered SQLException [The transaction is no longer active - status: 'Rolled back. [Reason=Unknown]'. No further JDBC access is allowed within this transaction.]; nested exception is java.sql.SQLException: The transaction is no longer active - status: 'Rolled back. [Reason=Unknown]'. No further JDBC access is allowed within this transaction.
    I have seen comments on the web that this is somewhat of a known Weblogic issue, where once a transaction is marked for rollback, weblogic will not resume the transaction, and that we should use org.springframework.transaction.jta.WebLogicJtaTra nsactionManager as our JTA Transaction Manager. I declared that in our application context, but seems to do no good.

    Any ideas? BTW, all of this works beautifully on JBoss. Seems to be just weblogic which is fussy.

    Thanks.

  • #2
    Actually, here is a better stack trace:

    2005-06-16 09:19:46,675 [ExecuteThread: '13' for queue: 'weblogic.kernel.Default'] ERROR rome.business.service.RatingServiceImpl - (User:administrator) Transaction BEA1-01DA1B88B7917F28EDB9 not active anymore. tx status = Marked rollback. [Reason=weblogic.transaction.internal.AppSetRollbac kOnlyException]
    java.sql.SQLException: Transaction BEA1-01DA1B88B7917F28EDB9 not active anymore. tx status = Marked rollback. [Reason=weblogic.transaction.internal.AppSetRollbac kOnlyException]
    at weblogic.jdbc.jts.Driver.getTransaction(Driver.jav a:367)
    at weblogic.jdbc.jts.Driver.connect(Driver.java:126)
    at weblogic.jdbc.common.internal.RmiDataSource.getCon nection(RmiDataSource.java:305)
    I also tried changing the transaction attribute on the Session Beans to RequiresNew, thinking that way once the facade is called, the transaction started at the beginning of the request would be suspended, and all calls from within the SLSB would be part of a new transaction. What happens is this:

    org.springframework.jdbc.UncategorizedSQLException : (Hibernate operation): encountered SQLException [The transaction is no longer active - status: 'Committed'. No further JDBC access is allowed within this transaction.]; nested exception is java.sql.SQLException: The transaction is no longer active - status: 'Committed'. No further JDBC access is allowed within this transaction.
    java.sql.SQLException: The transaction is no longer active - status: 'Committed'. No further JDBC access is allowed within this transaction.
    at weblogic.jdbc.wrapper.JTSConnection.checkIfRolledB ack(JTSConnection.java:118)
    at weblogic.jdbc.wrapper.JTSConnection.checkConnectio n(JTSConnection.java:127)
    at weblogic.jdbc.wrapper.Connection.prepareStatement( Connection.java:324)
    at weblogic.jdbc.wrapper.JTSConnection.prepareStateme nt(JTSConnection.java:426)
    at net.sf.hibernate.impl.BatcherImpl.getPreparedState ment(BatcherImpl.java:263)
    And this happens on successful calls. It appears the second SLSB call in the front-end class is trying to use the same transaction, instead of a new one that I would think RequiresNew implies.

    Comment


    • #3
      This might be related to how you handle your Hibernate Sessions. Are you using a single Hibernate Session per request? How do you manage that - through Spring's Hibernate support? The Hibernate Session holds a reference to an internal JDBC Connection per Session, so you might see a side effect of that Connection being used even outside its original transaction (in your "RequiresNew" scenario).

      In general, I recommend to not use a single JTA transaction per HTTP request. Aside from the issue you're experiencing when the transaction has rolled back and you want to load data for an error page, there is also the issue of database locks getting acquired and held until the web page has been rendered - potentially suffering from I/O congestion when sending a large HTTP response back to the client.

      Instead, I recommend to stick with transactions at the service facade level. This will use individual transactions for service calls, allowing for individual rollbacks: Even if one transaction rolled back, another one can still load data for an error page without any issues (i.e. without further work on a transaction that's already marked for rollback). Furthermore, database locks will be released early, before generation of the HTTP response starts.

      You might still want to use a single Hibernate Session per request: That is facilitated by the Open Session in View pattern. Spring's OpenSessionInViewFilter will use one Hibernate Session per HTTP request, with service layer transactions working on that Session. This is a compromise between efficient Hibernate Session usage (reused for an entire HTTP request) and short-lived transactions (per service operation).

      Juergen

      Comment

      Working...
      X