illegally attempted to associate a proxy with two open Sessions Exception in the Multiple Threaded Enviroment

Hi team, I am working on an requirement in which system reads the patient information from the file system and storing the data into the openMRS db. This include registation,visit and obs operations.For better performance data which read from file system divided among the multiple threads.Patient registation is done without any issue but I am getting following exception while starting of the visit.

illegally attempted to associate a proxy with two open Sessions

Partial stack trace

org.springframework.orm.hibernate4.HibernateSystemException: illegally attempted to associate a proxy with two open Sessions; nested exception is org.hibernate.HibernateException: illegally attempted to associate a proxy with two open Sessions at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:218) at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:730) at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:592) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:515) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at com.sun.proxy.$Proxy201.saveVisit(Unknown Source)

I am starting the session using Context.openSession() and setting the context to in thread using Context.setUserContext(userContext).

is that the important part of the stack trace or you want to give the full at pastebin.com ?

and what are the params for userContext as well

I have pasted some more stack trace here . I am not passing any param in usercontext. I am only setting usercontext. Sorry If I misunderstood you incorrectly.

Did you instantiate two sessions at the same time ?

I think no.I am starting new session after closing previous one. I am checking session whether it is active or not using following code:

Context.isSessionOpen()

So do you mind sharing the whole snippet?

Yup.

  • I am using executor framework and submitting task to it.
BlockingQueue<CustomPatientInfobq = new LinkedBlockingDeque<>(patientInfo);
DataTask ddt =  new DataTask(bq,location,customePatientService);
ExecutorService es = Executors.newWorkStealingPool(10);
Future ft = es.submit(ddt);
  • Data Task constructor
public DataTask(BlockingQueue<CustomPatientInfodata, Location loc,CustomePatientService customePatientService,) {
  this.data = data;
  this.event = event;
  this.customePatientService = customePatientService;
  this.userContext = Context.getUserContext();
}
  • Overriding call method of callable interface
@Override
public Set<CustomPatientInfocall()throws Exception{
  while (data.size() 0) {
    CustomPatientInfo customPatientInfo = data.poll();
     process(customPatientInfo);
  }
      return null;
}
  • Following method having the core implementation part
private CustomPatientInfo process(CustomPatientInfo customPatientInfo) throws  Exception {
     Context.openSession();
  Context.setUserContext(userContext);
  try{
  Patient registeredPatient = registrationCoreService.registerPatient(customPatientInfo);
  }finally {
    Context.closeSession();
  }
    if (!Context.isSessionOpen()) {
    Context.openSession();
    Context.setUserContext(userContext);
  }
   VisitService visitService = Context.getVisitService();
  visitType = visitService.getVisitTypeByUuid(VISI_TYPE_UUID);
    Visit visit = new Visit();
  Context.clearSession();
  visit.setPatient(registeredPatient);
  visit.setVisitType(visitType);
  Date startDatetime = new Date();
  visit.setStartDatetime(startDatetime);
  visit.setLocation(loc);
  try {
     return visitService.saveVisit(visit);
  } finally {
    Context.closeSession();
  }
}

I hope this might be give you some idea. If you want I could push the code to git repo.

it looks like you are opening up a session twice,could you create a pull request with the code that is performing your functionality so as we get a better view of what you are trying to do @mukesh

Thanks @herbert24 and @tendomart . I pushed the code into git repository.Please follow the MR