使用Spring Integration DSL Mail时出现ConcurrentModificationException

时间:2016-04-16 10:41:19

标签: spring spring-integration spring-dsl spring-cloud-stream spring-cloud-dataflow

我正在尝试使用Spring Integration Java DSL来接收电子邮件(gmail)。我也在使用Redis。当我收到邮件时,我得到ConcurrentModificationException。在搜索时我也发现人们在卡夫卡也遇到了同样的错误。以下是我的代码和例外。

感谢您提供帮助。

    Properties javaMailProperties = new Properties();
    javaMailProperties.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    javaMailProperties.setProperty("mail.imap.socketFactory.fallback", "false");
    javaMailProperties.setProperty("mail.store.protocol", "imaps");
    javaMailProperties.setProperty("mail.debug", "false");
    String imapUrl = "imaps://email%40gmail.com:password@imap.gmail.com:993/INBOX";



    IntegrationFlowBuilder flowBuilder = IntegrationFlows.from(Mail.imapInboundAdapter(imapUrl).javaMailProperties(javaMailProperties).shouldMarkMessagesAsRead(true)
            , new Consumer<SourcePollingChannelAdapterSpec>() {


        @Override
        public void accept(SourcePollingChannelAdapterSpec sourcePollingChannelAdapterSpec) {
            sourcePollingChannelAdapterSpec
                    .poller(defaultPoller);
        }
    });
    return flowBuilder.channel(source.output()).get();

例外:

2016-04-16 09:19:51.449  INFO 11640 --- [ask-scheduler-7] o.s.integration.mail.ImapMailReceiver    : attempting to receive mail from folder [INBOX]
2016-04-16 09:21:31.463 ERROR 11640 --- [ask-scheduler-7] o.s.integration.handler.LoggingHandler   : org.springframework.messaging.MessageHandlingException: error occurred in message handler [org.springframework.cloud.stream.binder.redis.RedisMessageChannelBinder$SendingHandler@2f104438]; nested exception is com.esotericsoftware.kryo.KryoException: java.util.ConcurrentModificationException
Serialization trace:
classes (sun.misc.Launcher$AppClassLoader)
classloader (java.security.ProtectionDomain)
context (java.security.AccessControlContext)
acc (sun.security.ssl.SSLSocketImpl)
c (sun.security.ssl.AppInputStream)
in (com.sun.mail.util.TraceInputStream)
in (java.io.BufferedInputStream)
bin (com.sun.mail.iap.ResponseInputStream)
input (com.sun.mail.imap.protocol.IMAPProtocol)
authenticatedConnections (com.sun.mail.imap.IMAPStore$ConnectionPool)
pool (com.sun.mail.imap.IMAPSSLStore)
store (com.sun.mail.imap.IMAPFolder)
folder (com.sun.mail.imap.IMAPMessage)
source (org.springframework.integration.mail.AbstractMailReceiver$IntegrationMimeMessage)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:139)
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120)
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:392)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105)
    at org.springframework.integration.endpoint.SourcePollingChannelAdapter.handleMessage(SourcePollingChannelAdapter.java:161)
    at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:251)
    at org.springframework.integration.endpoint.AbstractPollingEndpoint.access$000(AbstractPollingEndpoint.java:57)
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:176)
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:173)
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:330)
    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:324)
    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:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.esotericsoftware.kryo.KryoException: java.util.ConcurrentModificationException
Serialization trace:
classes (sun.misc.Launcher$AppClassLoader)
classloader (java.security.ProtectionDomain)
context (java.security.AccessControlContext)
acc (sun.security.ssl.SSLSocketImpl)
c (sun.security.ssl.AppInputStream)
in (com.sun.mail.util.TraceInputStream)
in (java.io.BufferedInputStream)
bin (com.sun.mail.iap.ResponseInputStream)
input (com.sun.mail.imap.protocol.IMAPProtocol)
authenticatedConnections (com.sun.mail.imap.IMAPStore$ConnectionPool)
pool (com.sun.mail.imap.IMAPSSLStore)
store (com.sun.mail.imap.IMAPFolder)
folder (com.sun.mail.imap.IMAPMessage)
source (org.springframework.integration.mail.AbstractMailReceiver$IntegrationMimeMessage)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:101)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:628)
    at com.esotericsoftware.kryo.serializers.DefaultArraySerializers$ObjectArraySerializer.write(DefaultArraySerializers.java:366)
    at com.esotericsoftware.kryo.serializers.DefaultArraySerializers$ObjectArraySerializer.write(DefaultArraySerializers.java:307)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObjectOrNull(Kryo.java:606)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:87)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObjectOrNull(Kryo.java:606)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:87)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:628)
    at com.esotericsoftware.kryo.serializers.CollectionSerializer.write(CollectionSerializer.java:100)
    at com.esotericsoftware.kryo.serializers.CollectionSerializer.write(CollectionSerializer.java:40)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:534)
    at org.springframework.integration.codec.kryo.PojoCodec.doEncode(PojoCodec.java:92)
    at org.springframework.integration.codec.kryo.AbstractKryoCodec$2.execute(AbstractKryoCodec.java:66)
    at com.esotericsoftware.kryo.pool.KryoPoolQueueImpl.run(KryoPoolQueueImpl.java:61)
    at org.springframework.integration.codec.kryo.AbstractKryoCodec.encode(AbstractKryoCodec.java:63)
    at org.springframework.cloud.stream.binder.AbstractBinder.serializePayloadIfNecessary(AbstractBinder.java:230)
    at org.springframework.cloud.stream.binder.AbstractBinder.serializePayloadIfNecessary(AbstractBinder.java:210)
    at org.springframework.cloud.stream.binder.redis.RedisMessageChannelBinder.access$800(RedisMessageChannelBinder.java:71)
    at org.springframework.cloud.stream.binder.redis.RedisMessageChannelBinder$SendingHandler.handleMessageInternal(RedisMessageChannelBinder.java:295)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
    ... 28 more
Caused by: java.util.ConcurrentModificationException
    at java.util.Vector$Itr.checkForComodification(Vector.java:1156)
    at java.util.Vector$Itr.next(Vector.java:1133)
    at com.esotericsoftware.kryo.serializers.CollectionSerializer.write(CollectionSerializer.java:92)
    at com.esotericsoftware.kryo.serializers.CollectionSerializer.write(CollectionSerializer.java:40)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:552)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:80)
    ... 84 more

2016-04-16 09:21:36.188  INFO 11640 --- [ask-scheduler-7] o.s.integration.mail.ImapMailReceiver    : attempting to receive mail from folder [INBOX]
2016-04-16 09:21:39.104  INFO 11640 --- [ask-scheduler-7] o.s.integration.mail.ImapMailReceiver    : attempting to receive mail from folder [INBOX]

1 个答案:

答案 0 :(得分:0)

看起来我们需要MimeMessage的自定义kryo序列化程序(由Spring Cloud Stream使用)。我针对Spring Integration打开了JIRA Issue

然而,当我测试它时,我遇到了堆栈溢出错误,而不是您看到的异常。

如果您可以将mail.debug javamail属性设置为true的控制台输出附加到JIRA问题,并显示您的问题,那么我们可以确保修复那个问题,因为那时我们可以重建一个类似的MimeMessage

修改

初步分析显示问题是在mime消息的java.util.Logger字段中序列化session

此外,事实证明这个对象(AbstractMailReceiver.IntegrationMimeMessage)完全不适合序列化,因为它在其范围内具有整个应用程序上下文,因为它是邮件接收器中的嵌套类。

因此,我建议在邮件模块中添加一个转换器,将此对象转换为适合任何类型序列化的对象。

<强> EDIT2

一种解决方法是将.transform(mailToStringTransformer())添加到流程中。邮件内容将是邮件的正文,from,bcc,cc,to,replyTo和Subject将被添加到邮件头。