0
votes
private File moveFileTo(File usageFile, File target) {
        File movedFile = new File(target.getPath() + File.separator + usageFile.getName());
        try {
            Files.move(usageFile.toPath(), movedFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
        } catch (Exception e) {
            log.error("Error while moving {} to {}", usageFile, movedFile, e);
            throw new AppException("Cannot move usage file from " + usageFile + " to " + movedFile);
        }
        return movedFile;
    }  

At the line with Files.move throws FileSystemException. I have a bunch of integration tests and 2 of them fail everytime with the following stacktrace:

java.nio.file.FileSystemException: C:\Users\ANDREI~1.TAN\AppData\Local\Temp\input\test-xml-usages-file-copy.xml -> C:\Users\ANDREI~1.TAN\AppData\Local\Temp\process\test-xml-usages-file-copy.xml: The process cannot access the file be cause it is being used by another process.

    at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
    at sun.nio.fs.WindowsFileCopy.move(WindowsFileCopy.java:301)
    at sun.nio.fs.WindowsFileSystemProvider.move(WindowsFileSystemProvider.java:287)
    at java.nio.file.Files.move(Files.java:1395)
    at com.bisnode.usagemanagement.infrastructure.importer.file.UsageFileImporterService.moveFileTo(UsageFileImporterService.java:122)
    at com.bisnode.usagemanagement.infrastructure.importer.file.UsageFileImporterService.importUsagesFile(UsageFileImporterService.java:42)
    at com.bisnode.usagemanagement.infrastructure.importer.file.scheduler.UsageFileImportScheduler.importFiles(UsageFileImportScheduler.java:33)
    at com.bisnode.usagemanagement.infrastructure.importer.file.scheduler.UsageFileImportScheduler.importUsageFiles(UsageFileImportScheduler.java:23)
    at com.bisnode.usagemanagement.infrastructure.importer.UsageImportIntegrationTest.testEndToEndImportXmlUsages(UsageImportIntegrationTest.java:119)
    at com.bisnode.usagemanagement.infrastructure.importer.UsageImportIntegrationTest.testEndToEndImportXmlUsagesFromInputFileWithoutNamespace(UsageImportIntegrationTest.java:114)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1259)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1259)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:150)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:124)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
    at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)  

I was thinking about a file locking but the thing is, in my tests, the threads are disabled so no concurrency issues are there. I have tried not just Files.move but a few more libraries to move the file but all of them failed. The code works fine on Mac but it fails on Windows. I think I miss something but I cannot figure what.

UPDATE

    public void importUsagesFile(File usageFile) {
    log.info("Received usage file to import {}, size {} bytes", usageFile.getName(), usageFile.length());
    if (!isValidUsageFile(usageFile)) {
        return;
    }

    log.info("Processing file. Move the file {} to process folder", usageFile.getName());
    File usageFileToProcess = moveFileTo(usageFile, usageFileDirectory.getProcess());
    processUsageFile(usageFileToProcess);
}  

This method will call moveFileTo, actually, after calling moveFileTo, will call processUsageFile that has a try-with-resources. So on short, importUsagesFile calls moveFileTo, then start to do some business logic.
UPDATE
So I've found the problem, in a test case I was using FileReader and therefore the file was locked. I put it in a try-with-resources and now it works :D.

1
What are you doing with the files before calling moveFileTo()? Most likely, it's the Java program itself that's holding the file open because you forgot to close an InputStream/OutputStream, which is a sign that you might have forgotten to use try-with-resources. - Andreas
I have updated the code. Basically in importUsagesFile I call moveFileTo to move my file into another directory. - Dolphy the Reaper
Yeah, after you call isValidUsageFile(), so maybe that method opens the file to validate the content, and doesn't close the file. - Andreas
I have updated the code. A test case was using FileReader with no close option. I put it in a try-with-resources and works like a charm. Thank you for your help :D. - Dolphy the Reaper

1 Answers

1
votes

This is a cross-site dupe to https://serverfault.com/q/1966/22361.

Something else is holding those handles open. You may be leaking open files in your own code (did you use try-with-resources everywhere?), or something else invoked as part of your test scripts is conflicting.

So you will have to debug it using Process Explorer or a similar tool (lsof on Linux, for example). I'd put a breakpoint in your code to catch the condition and then look for the handle using Process Explorer. This may be hard to catch, but there's really no other way to do it.