| Summary: | Same connection is getting released twice and added to the ConnectionPool | ||||||
|---|---|---|---|---|---|---|---|
| Product: | z_Archived | Reporter: | Ulrich Fuchs <mail> | ||||
| Component: | Eclipselink | Assignee: | Nobody - feel free to take it <nobody> | ||||
| Status: | NEW --- | QA Contact: | |||||
| Severity: | major | ||||||
| Priority: | P2 | CC: | tom.ware | ||||
| Version: | unspecified | ||||||
| Target Milestone: | --- | ||||||
| Hardware: | PC | ||||||
| OS: | Windows 7 | ||||||
| Whiteboard: | |||||||
| Attachments: |
|
||||||
Sorry, I copypasted the wrong persistenceUnit. This is the one that goes with the test:
<persistence-unit name="persistence.test.TestReleasedConnectionBug" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>de.asnit.libs.persistence.tests.PureSimpleEntity</class>
</persistence-unit>
Created attachment 168646 [details]
Testcase again
Testcase again; sorry, the one in the description still referred some classes of my framework
Setting target and priority. See the following page for details of the meanings of these fields: http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink |
Build Identifier: Eclipselink 2.0.2.v20100323-r6872 The following test case creates a situation, where the same Accessor ends up multiple times in the availableConnections list of ConnectionPool. As soon as the maximum number of connections is reached, the next time the Accessor is released, it's not added as available, it's disconnected instead. So, the next call to acquireConnection returns a now disconnected Accessor Reproducible: Always Steps to Reproduce: Test Case: ------------------------- PureSimpleEntity.java ------------------ package de.asnit.libs.persistence.tests; import java.util.UUID; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version; import org.eclipse.persistence.annotations.ChangeTracking; import org.eclipse.persistence.annotations.ChangeTrackingType; import sun.misc.BASE64Encoder; @Entity @Table (name="simpleentity") public class PureSimpleEntity { @Id @Column (name = "f_id") public String id; @Version private long _version; @Column (name = "f_desc") public String desc; private PureSimpleEntity() { id = generateID (); } public PureSimpleEntity (String desc) { this (); this.desc = desc; } public static String generateID () { return new BASE64Encoder().encode(asByteArray( UUID.randomUUID())); } public static byte[] asByteArray(UUID uuid) { long msb = uuid.getMostSignificantBits(); long lsb = uuid.getLeastSignificantBits(); byte[] buffer = new byte[16]; for (int i = 0; i < 8; i++) { buffer[i] = (byte) (msb >>> 8 * (7 - i)); } for (int i = 8; i < 16; i++) { buffer[i] = (byte) (lsb >>> 8 * (7 - i)); } return buffer; } } ------------------------- Junit Test case ------------------ @Test public void testBugPureSimple () throws SQLException, ClassNotFoundException { DALProvider provider=null; DAL dal = null; boolean excThrown = false; EntityManagerFactory emf =null; EntityManager em=null; try { Map props = new HashMap(); props.put (PersistenceUnitProperties.JDBC_USER, "eptest"); props.put (PersistenceUnitProperties.JDBC_PASSWORD, "eptest"); props.put (PersistenceUnitProperties.JDBC_URL, "jdbc:mysql://localhost:3306/eptest"); props.put (PersistenceUnitProperties.JDBC_DRIVER, "com.mysql.jdbc.Driver"); props.put (PersistenceUnitProperties.WEAVING, "true"); props.put (PersistenceUnitProperties.WEAVING_LAZY, "true"); emf = Persistence.createEntityManagerFactory("persistence.test.TestReleasedConnectionBug", props); em = emf.createEntityManager(); for (int i = 1; i<=50; i++ ) { System.out.println ("--- "+i+" ---"); em.getTransaction().begin(); PureSimpleEntity entity = new PureSimpleEntity ("Hallo"); em.persist(entity); JpaQuery q = (JpaQuery) em.createQuery("select s from PureSimpleEntity s order by s.id"); q.setHint (QueryHints.CURSOR, "true"); Cursor c = null; try { c = q.getResultCursor(); // Gets the second connection from ConnectionPool's availableConnections, // which also is the write connection, and releases it if (c.hasMoreElements()) { PureSimpleEntity se = (PureSimpleEntity) c.nextElement(); } } finally {if (c!=null) c.close();} em.getTransaction().commit(); // Releases the write connection again, so now the write connection // is twice in ConnectionPool's availableConnections. // This goes on unless all 32 connection "slots" are used. // If this happens the next time, the connection is not added to // the available connections, but disconnected instead. // However, this connection is available another 31 times in // avaiableConnections. So, when the next connection is returned // by ConnectionPool's acquireConnection, a disconnected connection // is returned, causing test failure. } } catch (Exception e) { excThrown = true; System.err.println (e); e.printStackTrace(System.err); } finally { if (dal != null) dal.close(); if (provider !=null) provider.close(); em.close(); emf.close(); } assertFalse (excThrown); // If the bug exists, we fail here } @Before public void createTables () throws ClassNotFoundException, SQLException { try {deleteTables ();} catch (Exception exc) {} Statement s = JDBCFassade.getConnection().createStatement(); s.executeUpdate("CREATE TABLE simpleentity (" + "f_id char(24) default '' NOT NULL ,"+ "f_desc varchar(64) default '' NOT NULL ," + "_version integer default 0 NOT NULL , " + "PRIMARY KEY (f_id)" + ")" ); s.close(); JDBCFassade.closeConnection(); } @After public void deleteTables () throws SQLException, ClassNotFoundException { try { Statement s = JDBCFassade.getConnection().createStatement(); s.executeUpdate("DROP TABLE simpleentity" ); s.close(); }finally { JDBCFassade.closeConnection(); } } ------------------------- Persistence Unit of persistence.xml ------------------ <persistence-unit name="persistence.test.TestSimpleEntities" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>de.asnit.libs.persistence.tests.SimpleEntity</class> </persistence-unit>