Uploaded image for project: 'IronJacamar'
  1. IronJacamar
  2. JBJCA-676

Evicted and closed CachedPreparedStatement leased out again on next call to prepareStatement by LIRS cache.

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • Critical
    • 1.0.5.Final, 1.1.0.Alpha3
    • 1.0.4.Final
    • JDBC
    • None
    • Hide

      This issue occurs on a 4-core i7 desktop and a 16-core HP ProLiant BL490c server.
      The database is hosted on the same machine as AS7.
      Use AS7.1 Alpha 2.

      Show
      This issue occurs on a 4-core i7 desktop and a 16-core HP ProLiant BL490c server. The database is hosted on the same machine as AS7. Use AS7.1 Alpha 2.
    • Workaround Exists
    • Hide

      I have found a workaround for this exception. By switching the cache eviction policy from LIRS to LRU this issue is no longer a problem.

      You will need to switch the ENUM in the constructor of PreparedStatementCache located here
      ironjacamar/adapters/src/main/java/org/jboss/jca/adapters/jdbc/PreparedStatementCache.java

      and replace the generated artifact here in a typical AS7.1 installation
      modules/org/jboss/ironjacamar/jdbcadapters/main/ironjacamar-jdbc-1.0.4.Final.jar

      Show
      I have found a workaround for this exception. By switching the cache eviction policy from LIRS to LRU this issue is no longer a problem. You will need to switch the ENUM in the constructor of PreparedStatementCache located here ironjacamar/adapters/src/main/java/org/jboss/jca/adapters/jdbc/PreparedStatementCache.java and replace the generated artifact here in a typical AS7.1 installation modules/org/jboss/ironjacamar/jdbcadapters/main/ironjacamar-jdbc-1.0.4.Final.jar

    Description

      My application throws an exception that reports the PreparedStatement cannot be used after it is closed. The exception is

      javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: No operations allowed after statement closed.

      It appears the PreparedStatementCache is not flushing an evicted item from the cache. The cache does call PreparedStatementEvictionListener.onEntryEviction(Map) which closes all the cached items being evicted. But it does not remove the item from the cache in that same call.
      When a client then calls prepareStatement(String) using the identical sql as a cached item the lookup in the cache returns the closed CachedPreparedStatement.

      I have a test case that calls the transaction on the server. The client makes an EJB call using a web service endpoint. The test case only executes one client call at a time.

      Observed behaviour
      This behaviour has only been seen to occur when eviction and prepare call are for identical SQL and when no other JDBC work happens between the two calls. Additionally it is timing sensitive. Turning on DEBUG logging makes the issue go away. To generate the logs attached I used a ramdisk and an ASYNC logging appender to eliminate delays due to saving to disk.

      Attached are logs with DEBUG level messages turned on for these categories: org.hibernate.SQL, org.hibernate.engine.jdbc.internal.JdbcResourceRegistryImpl and jboss.jdbc.spy

      To highlight the behaviour I added two logging messages. Source files are attached as a diff.

      a) The first is when items in the cache are evicted. The log message shows the hash identity of the CachedPreparedStatement and the SQL statement. Message added to org.jboss.jca.adapters.jdbc.PreparedStatementCache.onEntryEviction(Map) on line 255.

      b) The second is just before the first parameter (a String) is bound to a PreparedStatement. The message logs the hash identity of the CachedPreparedStatement, the SQL and hashed identity of the underlying driver com.mysql.jdbc.JDBC4PreparedStatement. The message is added to org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.setString(int, String) on line 637

      The log file shows the two events that match the behaviour detailed earlier. The log file is an small extract of the original. The first (the eviction) on line 21 and the second (the parameter binding) on 24.

      A test case will follow with an attempt to use H2 rather than MySQL.

      Attachments

        Issue Links

          Activity

            People

              jpederse@redhat.com Jesper Pedersen
              jwhiting@redhat.com Jeremy Whiting
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: