Установите диспетчер транзакций для Imap Idle Channel Adapter весной - PullRequest
0 голосов
/ 18 мая 2018

Я хочу настроить транзакционное поведение для сообщений электронной почты, полученных 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);
}

Я пытаюсь сделать все как в пружинная документация .Я получаю сообщения, но транзакций не существует.Я обнаружил, что в ImapIdleChannelAdapter в методе createMessageSendingTask(final Object mailMessage) при разрыве при проверке TransactionSynchronizationManager.isActualTransactionActive() возвращается false.Как я могу добавить понравившийся TransactionManager или включить его.Или что я делаю не так?

1 Ответ

0 голосов
/ 18 мая 2018

Вы правы с imapIdleChannelAdapter.setTransactionSynchronizationFactory(transactionSynchronizationFactory());.

Вам не хватает факта добавления TransactionInterceptor в imapIdleChannelAdapter.setAdviceChain():

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

ОБНОВЛЕНИЕ

до интеграции с Spring5.0 вам необходимо настроить TransactionInterceptor вручную:

TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
MatchAlwaysTransactionAttributeSource txAttributeSource = new MatchAlwaysTransactionAttributeSource();
txAttributeSource.setTransactionAttribute(new DefaultTransactionAttribute());
transactionInterceptor.setTransactionAttributeSource(txAttributeSource);
transactionInterceptor.setTransactionManager(emailTransactionManager());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...