在Spring中为Imap空闲通道适配器设置事务管理器

时间:2018-05-18 16:14:54

标签: java spring spring-boot spring-integration

我想为ImapIdleChannelAdapter收到的电子邮件设置事务行为。在事务提交后我想从电子邮件中删除邮件。我已经以这种方式设置了我的邮件接收器配置:

@Configuration
@EnableAsync
@EnableTransactionManagement
@ConfigurationProperties(prefix = "email")
@Profile("email")
public class MailReceiverConfiguration {

    @Setter
    private String imapUsername;

    @Setter
    private String imapPassword;

    @Setter
    private String imapServer;

    @Setter
    private String imapServerPort;

    @Setter
    private String folder;

    @Setter
    private String storeProtocol;

    @Bean(name = "emailTransactionManager")
    public PlatformTransactionManager emailTransactionManager() {
        PseudoTransactionManager pseudoTransactionManager = new PseudoTransactionManager();
        pseudoTransactionManager.getTransactionSynchronization();
        return pseudoTransactionManager;
    }

    @Bean
    public QueueChannel receiveChannel() {
    return new QueueChannel();
    }

    @Bean
    public ImapIdleChannelAdapter imapIdleChannelAdapter(ImapMailReceiver imapMailReceiver) {
        ImapIdleChannelAdapter imapIdleChannelAdapter = new ImapIdleChannelAdapter(imapMailReceiver);
        imapIdleChannelAdapter.setAutoStartup(true);
        imapIdleChannelAdapter.setOutputChannel(receiveChannel());
        imapIdleChannelAdapter.setTransactionSynchronizationFactory(transactionSynchronizationFactory());

        return imapIdleChannelAdapter;
    }

    @Bean
    public ImapMailReceiver imapMailReceiver() throws UnsupportedEncodingException {
        ImapMailReceiver receiver = new ImapMailReceiver(
            storeProtocol + "://" + URLEncoder.encode(imapUsername, "UTF-8") + ":" + imapPassword + "@" + imapServer + ":" + imapServerPort + "/" + folder
    );
        receiver.setShouldDeleteMessages(false);
        receiver.setShouldMarkMessagesAsRead(true);
        return receiver;
    }

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

        ExpressionEvaluatingTransactionSynchronizationProcessor syncProcessor =
            new ExpressionEvaluatingTransactionSynchronizationProcessor();
        syncProcessor.setAfterCommitExpression(parser.parseExpression("@messagesDeleter.process(payload)"));

        return new DefaultTransactionSynchronizationFactory(syncProcessor);
        }

        @Bean
        public MessagesDeleter messagesDeleter() {
            return new MessagesDeleter();
        }

}

Bean MessageDeleter有void方法将标志删除为消息:

public class MessagesDeleter{

public void process(MimeMessage message) throws Exception{
    Folder folder = message.getFolder();
    String messageId = message.getMessageID();
    Message[] messages = folder.getMessages();
    for (int i = 0; i < messages.length; i++) {
        if (((MimeMessage) messages[i]).getMessageID().equals(messageId)) {
            messages[i].setFlag(Flags.Flag.DELETED, true);
            break;
        }
    }
    folder.close(true);
}

我尝试在spring documentation中做所有事情。我收到消息,但交易不存在。我在方法createMessageSendingTask(final Object mailMessage)中的ImapIdleChannelAdapter中发现,当检查TransactionSynchronizationManager.isActualTransactionActive()时,它返回false。我如何添加喜欢的TransactionManager或包含它。或者我犯了什么错误?

1 个答案:

答案 0 :(得分:1)

imapIdleChannelAdapter.setTransactionSynchronizationFactory(transactionSynchronizationFactory());你是对的。

您遗失的是在TransactionInterceptor中添加imapIdleChannelAdapter.setAdviceChain()的事实:

imapIdleChannelAdapter.setAdviceChain(
                 Collections.singletonList(
                        new TransactionInterceptorBuilder()
                              .transactionManager(emailTransactionManager())
                              .build()))

<强>更新

在Spring Integration 5.0之前,您需要手动配置TransactionInterceptor

TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
MatchAlwaysTransactionAttributeSource txAttributeSource = new MatchAlwaysTransactionAttributeSource();
txAttributeSource.setTransactionAttribute(new DefaultTransactionAttribute());
transactionInterceptor.setTransactionAttributeSource(txAttributeSource);
transactionInterceptor.setTransactionManager(emailTransactionManager());