Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 313022 - Same connection is getting released twice and added to the ConnectionPool
Summary: Same connection is getting released twice and added to the ConnectionPool
Status: NEW
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 7
: P2 major (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-05-15 15:49 EDT by Ulrich Fuchs CLA
Modified: 2022-06-09 10:24 EDT (History)
1 user (show)

See Also:


Attachments
Testcase again (2.52 KB, text/plain)
2010-05-16 04:35 EDT, Ulrich Fuchs CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ulrich Fuchs CLA 2010-05-15 15:49:33 EDT
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>
Comment 1 Ulrich Fuchs CLA 2010-05-15 15:51:47 EDT
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>
Comment 2 Ulrich Fuchs CLA 2010-05-16 04:35:01 EDT
Created attachment 168646 [details]
Testcase again

Testcase again; sorry, the one in the description still referred some classes of my framework
Comment 3 Tom Ware CLA 2010-06-07 14:24:09 EDT
Setting target and priority.  See the following page for details of the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines
Comment 4 Eclipse Webmaster CLA 2022-06-09 10:14:52 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink
Comment 5 Eclipse Webmaster CLA 2022-06-09 10:24:47 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink