Mule ESB - FileMessageReceiver 中的 ConcurrentModificationException
Mule ESB - ConcurrentModificationException in FileMessageReceiver
我的 Mule 应用程序处理几个不同的目录并移动文件。我有一些文件入站端点和文件连接器。在某些情况下,我必须轮询不同的文件夹、处理文件、移动它们、再次轮询等。
我在日志中看到这个异常:
java.util.ConcurrentModificationException
at java.util.ArrayList.sort(ArrayList.java:1456)
at java.util.Collections.sort(Collections.java:175)
at org.mule.transport.file.FileMessageReceiver.poll(FileMessageReceiver.java:199)
at org.mule.transport.AbstractPollingMessageReceiver.performPoll(AbstractPollingMessageReceiver.java:216)
at org.mule.transport.PollingReceiverWorker.poll(PollingReceiverWorker.java:80)
at org.mule.transport.PollingReceiverWorker.run(PollingReceiverWorker.java:49)
at org.mule.transport.TrackingWorkManager$TrackeableWork.run(TrackingWorkManager.java:267)
at org.mule.work.WorkerContext.run(WorkerContext.java:286)
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)
我注意到在这种情况下 http://grepcode.com/file/repo1.maven.org/maven2/org.mule.transports/mule-transport-file/3.5.0/org/mule/transport/file/FileMessageReceiver.java#675 每次 files.isEmpty() 都会返回相同的集合对象 - 这并不理想,很可能是问题的原因。
现在,幸运的是,这个异常总体上没有破坏性,除了它可能会跳过轮询周期并污染日志。
有人以前看过这个/有想法吗?
如果我在文件列表为空时更改 listFiles() 实现,异常似乎会消失。
package org.mule.transport.file;
import org.mule.api.MuleException;
import org.mule.api.construct.FlowConstruct;
import org.mule.api.endpoint.InboundEndpoint;
import org.mule.api.lifecycle.CreateException;
import org.mule.api.transport.Connector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class PatchedFileMessageReceiver extends FileMessageReceiver
{
private static final Logger log = LoggerFactory.getLogger(PatchedFileMessageReceiver.class);
/**
*
* @param connector
* @param flowConstruct
* @param endpoint
* @param readDir
* @param moveDir
* @param moveToPattern
* @param frequency
* @throws CreateException
*/
public PatchedFileMessageReceiver(Connector connector, FlowConstruct flowConstruct, InboundEndpoint endpoint, String readDir, String moveDir, String moveToPattern, long frequency) throws CreateException
{
super(connector, flowConstruct, endpoint, readDir, moveDir, moveToPattern, frequency);
}
/**
*
* @return
* @throws MuleException
*/
@Override
List<File> listFiles() throws MuleException
{
List<File> list = super.listFiles();
if(list.isEmpty()) {
log.trace("List of files is empty, I'm gonna return a new empty ArrayList");
}
return ( list.isEmpty() ? new ArrayList<File>() : list );
}
}
然后像这样在文件连接器上设置自定义 FileMessageReceiver
<file:connector name="source-file-connector" autoDelete="false" fileAge="1000" pollingFrequency="1000" >
<service-overrides messageReceiver="org.mule.transport.file.PatchedFileMessageReceiver" />
</file:connector>
这些东西真的应该在上游得到修复。作为用户,我们希望不必处理此类问题。
比 return 每次调用 listFiles() 时创建一个新列表(并且没有文件)更好的解决方案是使用 CopyOnWriteArrayList for NO_FILES at http://grepcode.com/file/repo1.maven.org/maven2/org.mule.transports/mule-transport-file/3.5.0/org/mule/transport/file/FileMessageReceiver.java#64
private static final List<File> NO_FILES = new CopyOnWriteArrayList<File>();
这样您就可以避免创建实例。
我的 Mule 应用程序处理几个不同的目录并移动文件。我有一些文件入站端点和文件连接器。在某些情况下,我必须轮询不同的文件夹、处理文件、移动它们、再次轮询等。
我在日志中看到这个异常:
java.util.ConcurrentModificationException
at java.util.ArrayList.sort(ArrayList.java:1456)
at java.util.Collections.sort(Collections.java:175)
at org.mule.transport.file.FileMessageReceiver.poll(FileMessageReceiver.java:199)
at org.mule.transport.AbstractPollingMessageReceiver.performPoll(AbstractPollingMessageReceiver.java:216)
at org.mule.transport.PollingReceiverWorker.poll(PollingReceiverWorker.java:80)
at org.mule.transport.PollingReceiverWorker.run(PollingReceiverWorker.java:49)
at org.mule.transport.TrackingWorkManager$TrackeableWork.run(TrackingWorkManager.java:267)
at org.mule.work.WorkerContext.run(WorkerContext.java:286)
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)
我注意到在这种情况下 http://grepcode.com/file/repo1.maven.org/maven2/org.mule.transports/mule-transport-file/3.5.0/org/mule/transport/file/FileMessageReceiver.java#675 每次 files.isEmpty() 都会返回相同的集合对象 - 这并不理想,很可能是问题的原因。
现在,幸运的是,这个异常总体上没有破坏性,除了它可能会跳过轮询周期并污染日志。
有人以前看过这个/有想法吗?
如果我在文件列表为空时更改 listFiles() 实现,异常似乎会消失。
package org.mule.transport.file;
import org.mule.api.MuleException;
import org.mule.api.construct.FlowConstruct;
import org.mule.api.endpoint.InboundEndpoint;
import org.mule.api.lifecycle.CreateException;
import org.mule.api.transport.Connector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class PatchedFileMessageReceiver extends FileMessageReceiver
{
private static final Logger log = LoggerFactory.getLogger(PatchedFileMessageReceiver.class);
/**
*
* @param connector
* @param flowConstruct
* @param endpoint
* @param readDir
* @param moveDir
* @param moveToPattern
* @param frequency
* @throws CreateException
*/
public PatchedFileMessageReceiver(Connector connector, FlowConstruct flowConstruct, InboundEndpoint endpoint, String readDir, String moveDir, String moveToPattern, long frequency) throws CreateException
{
super(connector, flowConstruct, endpoint, readDir, moveDir, moveToPattern, frequency);
}
/**
*
* @return
* @throws MuleException
*/
@Override
List<File> listFiles() throws MuleException
{
List<File> list = super.listFiles();
if(list.isEmpty()) {
log.trace("List of files is empty, I'm gonna return a new empty ArrayList");
}
return ( list.isEmpty() ? new ArrayList<File>() : list );
}
}
然后像这样在文件连接器上设置自定义 FileMessageReceiver
<file:connector name="source-file-connector" autoDelete="false" fileAge="1000" pollingFrequency="1000" >
<service-overrides messageReceiver="org.mule.transport.file.PatchedFileMessageReceiver" />
</file:connector>
这些东西真的应该在上游得到修复。作为用户,我们希望不必处理此类问题。
比 return 每次调用 listFiles() 时创建一个新列表(并且没有文件)更好的解决方案是使用 CopyOnWriteArrayList for NO_FILES at http://grepcode.com/file/repo1.maven.org/maven2/org.mule.transports/mule-transport-file/3.5.0/org/mule/transport/file/FileMessageReceiver.java#64
private static final List<File> NO_FILES = new CopyOnWriteArrayList<File>();
这样您就可以避免创建实例。