views:

124

answers:

1

my service layer methods are transactional, when i use ExecutorService and submit task to threads, i cannot pass servicelayer as parameter to each threads, as i get error

Dec 14, 2009 10:40:18 AM com.companyx.applicationtest.applicationtestcompanyx.services.threadtestRunnable run
SEVERE: null
org.hibernate.HibernateException: No Hibernate Session bound to thread, and conf
iguration does not allow creation of non-transactional one here
        at org.springframework.orm.hibernate3.SpringSessionContext.currentSessio
n(SpringSessionContext.java:63)
        at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactor
yImpl.java:542)

my service layer

ExecutorService executor = Executors.newFixedThreadPool(10);
                  for (final Object item : CollectionsTest{ 
                      executor.submit(new threadtestRunnable((Long)item,collectionAfterfiltered,this));  //'this' is service layer
                  }
  1. should i pass the service layer to each thread like this?
  2. what is the proper way to do it, i need each thread to call method in service layer? (i'm using spring)
+1  A: 

Generally, as said in the comments, transactions shouldn't be run in multiple threads. However, there are cases, where it is acceptable.

  • you need to make some asynchronous communication with a web-service (without making the user wait for the result), and store the result when it comes
  • you need read-only transactions in the multiple threads.

If you create your thread using new, it is not part of the spring context. Hence, when the method creating the thread finishes, your transaction interceptor will close the transaction (and session, eventually), and you will get the above exception.

(For more details - Spring docs, see "Lookup injection")

You need to create your threads within the spring context. And since you are probably creating them from a singleton bean, it is the rare case of creating prototype beans from a singleton bean. So in order to create a thread in the spring context, you can use:

You should also map your ThreadtestRunnable class in the applicationContext.xml or annotate it as @Component("myThreadBean").

Then define an abstract method on your main bean named createThread and returning your thread class. Annotate your run method with @Transactional (or define the appropriate aop rules), and try it. Perhaps you will need to set propagateion=Propagation.REQUIRES_NEW" in your @Transactional. If anything is wrong, get back here.

Bozho
by registering thread in xml. i no longer should call new threadtestRunnable((Long)item,collectionAfterfiltered,this) in ExecutionService right? and use applicationContext.getbean("thread") ?
cometta
no, you should call your createThread method and it will create the thread for you
Bozho
why not just use @Configurable and minimize the required to change of code and only need to add annotation in ThreadtestRunnable
cometta
Either way should work. But adding @Configurable won't save much configuration ;) you will save one like for the lookup method replaced with one line for the load-time weaving
Bozho