how to use util concurrent package to replicate the load testing concurrent problems

we have provided some RESTFUL webservices ,where client is going to consume these services.for this we have used spring restful services+JPA.
while doing load testing of 100 or more concurrent users we are facing exceptions like "LockAcquistionException" and
"Unable to commit: transaction marked for rollback". in normal scenarios its working fine but while doing load testing we are getting above exceptions

to replicate these scenarios we used Java Concurrent package and come up with the below code.
can we i use below code so that 100 or 200  users call these service concurrently?my intension is to replicate the scenario thats happening in load testing?

public class RestClientTest  
{
  ExecutorService executor = Executors.newFixedThreadPool(30);
  String	BASE_URL_DOC =null;
  
  
  @Autowired
  RestTemplate restTemplate;
  
  @Test
  public void updateDoc() throws Exception{
    
    try {
    	
    	for(int i = 1; i <= 100; i++) {
            Runnable worker = new MyRunnable(i);
            executor.execute(worker);
        }
        executor.shutdown();
        // Wait until all threads are finish
        while (!executor.isTerminated()) {
 
        }
        System.out.println("\nFinished all threads");
        
   
	} catch (Exception e) {
		e.printStackTrace();
	}

  }
 
  
  public  class MyRunnable implements Runnable {
  
	  private int i;
      MyRunnable(int i) {
          this.i = i;
      }

      public void run() {
    	  
    	  try {
    			   String	BASE_URL_DOC = "http://localhost:8080/docws/updateDocument/"+i+"/13131313";
        		   output= 	 restTemplate.getForObject(BASE_URL_DOC,Response.class);
        	
          } catch (Exception e) {
             e.printStackTrace();
          }
         
      }
  }

Open in new window

 
}

//above restful websrevices internally calls this JPA code
************************************************************
@Transactional
public int updateDocument(Long empId, Long docId) {
		
		Query updateDocumentQuery = em.createNamedQuery("updateDocument");
		updateDocumentQuery.setParameter("empId", empId);
		updateDocumentQuery.setParameter("docId", docId);
		int updated = updateDocumentQuery.executeUpdate();
		
		if (updated != 0) {			
			recordHistory(empId, docId);			
		}
		return updated;
	}
	
	private void recordHistory(Long empId, Long docId) {
		Date currentDate = new Date();
		Query historyRecQuery = em.createNamedQuery("getHistoryRecord");
		historyRecQuery.setParameter("empId", empId);
		
		List results = (List) historyRecQuery.getResultList();
		if (!results.isEmpty()) {
			HistoryRecs historyRec = (HistoryRecs) results.get(0);
			historyRec.setEndDate(currentDate);
			em.persist(historyRec);
		}
		Employee emp = em.find(Employee.class, empId); //some times here we are getting LockAcquistionException here
		
		
		HistoryRecs historyRecs = new HistoryRecs();
		historyRecs.setEmpId(empId);
		historyRecs.setDocId(docId);		
		if(emp.getpath() != null){
			historyRecs.setpath(emp.getpath());
		}
		
		historyRecs.setFromDate(currentDate);
		em.persist(historyRecs);
	}

Open in new window

LVL 20
chaitu chaituAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mccarlIT Business Systems Analyst / Software DeveloperCommented:
can we i use below code so that 100 or 200  users call these service concurrently?
You can use that code, but you would need to change the number of threads allocated to the "executor". As it stands, it would only run (at most) 30 concurrent connections. The rest of the 'worker' object that you set it to execute, will wait in a queue for one of those 30 threads to become available.

As for the exceptions that you are getting, you really need to understand what all the JPA calls translate into on the DB side, and know what locking is performed by these calls so that you can analyse for possibility of deadlocks/livelocks/etc. And this will likely depend on what DB you are using too, as each has different locking semantics.
0
dpearsonCommented:
Like mccarl said, the issue will be the underlying SQL queries.

What's happening is that one thread is executing this code:

...
// This will involve locking some rows in the database during the update
updateDocumentQuery.executeUpdate();
...


while a second thread tries to execute this code:

..
Employee emp = em.find(Employee.class, empId);
...


One approach is to add "synchronized" to the two methods (updateDocument and recordHistory).  This will make them no longer execute at the same time, so you should no longer get the exception, but you'll also get worse throughput.

Doug
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.