2016-09-03 62 views
1

我想通過JavaConfig替換Spring Integration XML配置,但我無法正確定義JpaOutboundGateway。在XML中,我有以下bean定義:在Java配置中如何恰當地定義Spring集成JpaOutboundGateway?

<int-jpa:outbound-channel-adapter id="saveOffer" entity-manager-factory="entityManagerFactory" channel="channel5" 
            flush-size="100" entity-class="JobOffer"> 
    <int-jpa:transactional transaction-manager="transactionManager"/> 
</int-jpa:outbound-channel-adapter> 

它工作正常。但是,當我試圖將其移動到Java配置bean我不知道如何定義事務管理...我仍然收到與事務相關的錯誤。

@Bean 
@ServiceActivator(inputChannel="channel5") 
public JpaOutboundGatewayFactoryBean save() throws Exception { 

    JpaExecutor executor = new JpaExecutor(entityManager); 
    executor.setFlushSize(10); 
    executor.setEntityClass(JobOffer.class); 

    JpaOutboundGatewayFactoryBean factoryBean = new JpaOutboundGatewayFactoryBean(); 
    factoryBean.setJpaExecutor(executor); 
    factoryBean.setProducesReply(false); 

    return factoryBean; 
} 

我試圖在JpaExecutor中使用EntityManager和EntityManagerFactory。但是,在這兩種情況下拋出異常:

2016-09-03 09:20:42.440 ERROR o.s.integration.handler.LoggingHandler : org.springframework.messaging.MessageHandlingException: error occurred in message handler [[email protected]1fc306d3]; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call 
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:139) 
    at org.springframework.integration.endpoint.PollingConsumer.handleMessage(PollingConsumer.java:129) 
    at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:272) 
    at org.springframework.integration.endpoint.AbstractPollingEndpoint.access$000(AbstractPollingEndpoint.java:58) 
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:190) 
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:186) 
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:353) 
    at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:55) 
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) 
    at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:51) 
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:344) 
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) 
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:282) 
    at com.sun.proxy.$Proxy121.merge(Unknown Source) 
    at org.springframework.integration.jpa.core.DefaultJpaOperations.persistOrMerge(DefaultJpaOperations.java:248) 
    at org.springframework.integration.jpa.core.DefaultJpaOperations.merge(DefaultJpaOperations.java:215) 
    at org.springframework.integration.jpa.core.JpaExecutor.executeOutboundJpaOperation(JpaExecutor.java:253) 
    at org.springframework.integration.jpa.outbound.JpaOutboundGateway.handleRequestMessage(JpaOutboundGateway.java:81) 
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:109) 
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) 
    ... 19 more 

回答

1

這是一個更復雜的端點,我們需要爲參考手冊添加一個Java配置示例;我打開了一個JIRA Issue

您可以隨時查看the XML parser查看需要什麼。

特別是:

  1. JpaExecutor應該被定義爲作爲@Bean
  2. 您需要將交易建議添加到適配器的txAdviceChain
  3. 您可以查看IntegrationNamespaceUtils.configureTransactionAttributes以查看連接到TransactionInterceptor的交易建議(交易屬性,屬性來源,TM等)需要什麼。
+0

謝謝您的回答。我試圖在問這裏問題之前分析XML解析器,但我不明白這些交易建議鏈的東西......但也許你的建議,我會讓它工作。 – daprog

+0

我的「醜陋但工作」版本在下一個答案。我承認這遠不如我預期的那麼直觀...... – daprog

+0

當然,使用XML的一個好處是 - 解析器對你有很大的幫助。對於java配置,當我們將JPA支持添加到[Java DSL](https://github.com/spring-projects/spring-integration-java-dsl)時,配置會更容易一些。 DSL正在被納入5.0的主要項目。 –

1

我的 「醜陋的,但是,工作」 的版本:

@Bean 
public JpaExecutor jpaExecutor() { 

    JpaExecutor executor = new JpaExecutor(entityManagerFactory); 
    executor.setFlushSize(10); 
    executor.setEntityClass(JobOffer.class); 
    return executor; 
} 

@Bean 
@ServiceActivator(inputChannel="channel5") 
public JpaOutboundGateway save(JpaExecutor jpaExecutor, PlatformTransactionManager transactionManager) throws Exception { 

    DefaultTransactionAttribute dta = new DefaultTransactionAttribute(); 
    dta.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); 
    dta.setReadOnly(false); 

    MatchAlwaysTransactionAttributeSource matas = new MatchAlwaysTransactionAttributeSource(); 
    matas.setTransactionAttribute(dta); 

    TransactionInterceptor ic = new TransactionInterceptor(); 
    ic.setTransactionManager(transactionManager); 
    ic.setTransactionAttributeSource(matas); 

    List<Advice> adviceChain = new ArrayList<>(); 
    adviceChain.add(ic); 

    JpaOutboundGateway gateway = new JpaOutboundGateway(jpaExecutor); 
    gateway.setAdviceChain(adviceChain); 
    gateway.setProducesReply(false); 

    return gateway; 
} 
相關問題