2014-04-30 20 views
0

我試圖讓TaskExecutor(ThreadPoolTask​​Executor)爲當前運行良好的事務處理服務工作,但是當我啓動任務時,現有事務不再被發現。Spring TaskExecutor事務丟失(代理與直接調用)

(在下面的start()方法被調用已經有活躍的交易) (爲SimplePojo北京時間斷章取義,只保留一些數據,讓說要存儲在數據庫中)

@Component 
@Transactional(rollbackFor = { Exception.class }) 
public class MyService { 

    @Autowired 
    MyTaskRunner myTaskRunner; 

    public void start() { 

     // TransactionSynchronizationManager.isActualTransactionActive() -> true 

     SimplePOJO pojo = new SimplePOJO(); 
     myTaskRunner.executeTask(pojo); 
    } 
} 

以上服務使用該組件:

@Component 
public class MyTaskRunner implements ApplicationContextAware { 

    @Autowired 
    private TaskExecutor taskExecutor; 

    private static ApplicationContext applicationContext = null; 

    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
     MyTaskRunner.applicationContext = applicationContext; 
    } 

    public void executeTask(SimplePOJO simplePOJO) { 

     // TransactionSynchronizationManager.isActualTransactionActive() -> true 

     MyDelegate myDelegate = applicationContext.getBean(MyDelegate.class); 
     myDelegate.setSimplePOJO(simplePOJO); 
     taskExecutor.execute(myDelegate); 
    } 
} 

那得到配置ThreadPoolTask​​Executor類是這樣的:

<bean id="taskExecutor" 
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> 
    <property name="corePoolSize" value="1" /> 
    <property name="maxPoolSize" value="5" /> 
    <property name="queueCapacity" value="25" /> 
</bean> 

而應終於開始在每個任務一個新的事務異步工作:

@Component 
@Scope(BeanDefinition.SCOPE_PROTOTYPE) 
public class MyDelegate implements Runnable { 

    private SimplePOJO simplePOJO; 

    @Override 
    public void run() { 

     // TransactionSynchronizationManager.isActualTransactionActive()); -> False! 

     if (this.simplePOJO != null) { 
      this.doStuff(angebotAnfrageContainer); 
     } 
    } 

    public void setSimplePOJO(SimplePOJO simplePOJO) { 
     this.simplePOJO = simplePOJO; 
    } 

    @Async 
    @Transactional(propagation = Propagation.REQUIRES_NEW) 
    private void doStuff() { 

     // TransactionSynchronizationManager.isActualTransactionActive()); -> False! 

     // do stuff with the pojos data in the transaction (persist on DB) 
    } 

} 

你有什麼建議什麼,我在這裏失蹤?

很多預先感謝!

我試圖 寫上面的代碼&搜索了幾個小時的網,這是我發現:

我不得不承認我是很新的春天和還沒有被瞭解的框架太清楚。在嘗試和搜索網頁的最後幾個小時內,我認爲它與從Spring創建的Proxys beeing有關,並且當我調用execute()方法或TaskRunner調用run()時,鏈斷裂調用代理直接調用實現(MyDelegate)...但我絕對沒有想法如何我可以驗證或改變它。

提前很多感謝

+0

Spring使用代理服務器和代理服務器將只用於外部方法調用工作。你的run方法用'@Transactional'調用方法,但是它總是從代理中調用,所以不會有事務開始。 –

+0

非常感謝您的回覆。我想我明白了......你會推薦什麼? (我現在將嘗試在另一個Spring Bean中使用doStuff()方法,並從run()方法中調用此方法) – JBA

+0

O.k.你輸入的是關鍵,我可以通過上面的doSomething()來解決它 - 然後從run()方法調用自己的Component中的方法。畢竟這嘗試和東西,我需要重新考慮,如果我甚至需要@Async了;) – JBA

回答

1

交易都使用AOP應用。 Spring默認使用proxies來應用AOP。代理的使用只會導致調用(外部方法調用)對象被攔截。在你的情況下,你正在從對象內部進行一個方法調用,它不會通過代理並且不會被攔截,基本上使得@Transactional無用。

只需將@Transactional移動到run方法應該可以解決您的問題,因爲run方法現在將在事務中運行。

@Transactional 
public void run() {...} 

還可以這裏並不做任何事情,你是一個TaskExecutor執行的任務已經使他們(取決於TaskExecutor使用)異步刪除@Async

鏈接:

  1. Understanding AOP Proxies
  2. TaskExecutor
+0

如果我在run()方法上執行了@Transactional方法,我得到一個BeanNotOfRequiredTypeException:名爲'myDelegate'的Bean必須是[MyDelegate]類型,但實際上是類型[$ Proxy86] – JBA

+1

你是對的,你應該使用基於類的代理而不是基於接口的代理,如果你想要的話。 Spring默認使用基於接口的代理。 –

相關問題