correct way to pass service layer to threads
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.application开发者_StackOverflowtestcompanyx.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
}
- should i pass the service layer to each thread like this?
- what is the proper way to do it, i need each thread to call method in service layer? (i'm using spring)
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:
<bean id="mainBean"
class="com.my.MyClass">
<lookup-method name="createThread" bean="myThreadBean"/>
</bean>
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 propagation=Propagation.REQUIRES_NEW"
in your @Transactional
. If anything is wrong, get back here.
精彩评论