2017-02-07 22 views
1

ファイルを読み込んでコンテンツをStringに変換するケースがあります。その後、文字列を複数のペイロードに分割し、それらのペイロードを個別にキューに送信します。 JmsTransactionManagerを使用して、すべてのメッセージを送信するか、まったく送信しないようにします。JmsTransactionManagerと組み合わせたTransactionSynchronizationFactoryが機能しない

TXが成功したら、ファイルをアーカイブフォルダに移動します。それ以外の場合は、失敗したフォルダに移動します。私はこれを達成するためにtransactionSynchronizationFactoryを使用できることを読んだ。しかし、JmsTransactionManagerと組み合わせて、ファイルは移動されません。 PseudoTransactionManagerを使用すると、ファイルは移動しますが、私はJmsTransactionを失います。

私は問題を再現するために簡略化したバージョンを作成しました。 (この場合のファイルの内容が値の簡単なカンマ区切りリストです)

@Bean 
public IntegrationFlow fileInboundAdaptor() { 
    return IntegrationFlows 
      .from(s -> s.file(new File(INBOUND_PATH)) 
          .patternFilter("*.txt"), 
        e -> e.poller(Pollers.fixedDelay(5000) 
          .transactionSynchronizationFactory(transactionSynchronizationFactory()) 
          .transactional(new JmsTransactionManager(connectionFactory)) 

        ) 

      ) 

      .transform(Transformers.fileToString()) 
      .split(s -> s.applySequence(false).get().getT2().setDelimiters(",")) 
      .handle((GenericHandler<String>) (payload, headers) -> { 
       jmsTemplate.send("SOME_QUEUE", (Session session) -> session.createTextMessage(payload)); 
       return payload; 
      }) 
      .channel(MessageChannels.queue("fileReadingResultChannel")) 
      .get(); 
} 

transactionSynchronizationFactoryは次のようになります。

@Bean 
public TransactionSynchronizationFactory transactionSynchronizationFactory() { 
    ExpressionParser parser = new SpelExpressionParser(); 

    ExpressionEvaluatingTransactionSynchronizationProcessor syncProcessor 
      = new ExpressionEvaluatingTransactionSynchronizationProcessor(); 
    syncProcessor.setBeanFactory(applicationContext.getAutowireCapableBeanFactory()); 
    syncProcessor.setAfterCommitExpression(parser.parseExpression(
      "payload.renameTo(new java.io.File('test/archive' " + 
        " + T(java.io.File).separator + 'ARCHIVE-' + payload.name))")); 
    syncProcessor.setAfterRollbackExpression(parser.parseExpression(
      "payload.renameTo(new java.io.File('test/fail' " + 
        " + T(java.io.File).separator + 'FAILED-' + payload.name))")); 
    return new DefaultTransactionSynchronizationFactory(syncProcessor); 
} 

だから私の質問は次のとおりです。TransactionSynchronizationFactoryはPseudoTransactionManagerで動作しませんまたはJmsTransactionManagerでも動作するはずですか?私はJmsTransactionにtransactionSynchronizationを設定するために必要な

ソリューション

。このような何か:

public JmsTransactionManager transactionManager() { 
    JmsTransactionManager jmsTransactionManager = new JmsTransactionManager(connectionFactory); 
    jmsTransactionManager.setTransactionSynchronization(AbstractPlatformTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION); 
    return jmsTransactionManager; 
} 
+0

にそれをオンにする必要があります'@ Bean'。その '.transactional()'オプションからApplicationContextに登録されていません –

+0

これは問題ではありませんでした。私は私の元のポストで解決策を追加しました。 –

答えて

0

まあ、私はあなたの問題はここにあると思う:

だから、
/** 
* Create a new JmsTransactionManager for bean-style usage. 
* <p>Note: The ConnectionFactory has to be set before using the instance. 
* This constructor can be used to prepare a JmsTemplate via a BeanFactory, 
* typically setting the ConnectionFactory via setConnectionFactory. 
* <p>Turns off transaction synchronization by default, as this manager might 
* be used alongside a datastore-based Spring transaction manager like 
* DataSourceTransactionManager, which has stronger needs for synchronization. 
* Only one manager is allowed to drive synchronization at any point of time. 
* @see #setConnectionFactory 
* @see #setTransactionSynchronization 
*/ 
public JmsTransactionManager() { 
    setTransactionSynchronization(SYNCHRONIZATION_NEVER); 
} 

、手動で `JmsTransactionManager`としてことを確認してくださいsetTransactionSynchronization(AbstractPlatformTransactionManager.SYNCHRONIZATION_ALWAYS);

+0

はい、それは動作します!同期がデフォルトでオフになっているかどうかはわかりませんでした。ご協力いただきありがとうございます! –

+0

どちらもそうです。JavaDocsは私たちの友人です:) –

関連する問題