Error when using the listFiles method in a javascript script in Fiji

javascript
fiji
Tags: #<Tag:0x00007fb87e6364e0> #<Tag:0x00007fb87e6362d8>

#1

Hi, I’m learning to write scripts in Fiji using javascript (which I’m relatively familiar with) but found an issue that I cannot explain. When I run the following script in macro editor:

importClass(Packages.java.io.File);
importClass(Packages.ij.IJ);
var inputDirName, inputDir, list;
inputDirName = IJ.getDirectory("Choose input directory");
inputDir = new File(inputDirName);
list = inputDir.listFiles();

…I get a misterious error:

[WARNING] Ignoring unsupported output: result [java.io.File]
[ERROR] Module threw exception
java.lang.NullPointerException
	at org.scijava.plugins.scripting.javascript.JavaScriptScriptLanguage.decode(JavaScriptScriptLanguage.java:126)
	at org.scijava.script.ScriptModule.run(ScriptModule.java:180)
	at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
	at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	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)
[ERROR] null
java.util.concurrent.ExecutionException: java.lang.NullPointerException
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at org.scijava.ui.swing.script.TextEditor.evalScript(TextEditor.java:2348)
	at org.scijava.ui.swing.script.TextEditor.access$1000(TextEditor.java:149)
	at org.scijava.ui.swing.script.TextEditor$20.execute(TextEditor.java:1939)
	at org.scijava.ui.swing.script.TextEditor$Executer$1.run(TextEditor.java:1751)
Caused by: java.lang.NullPointerException
	at org.scijava.plugins.scripting.javascript.JavaScriptScriptLanguage.decode(JavaScriptScriptLanguage.java:126)
	at org.scijava.script.ScriptModule.run(ScriptModule.java:180)
	at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
	at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	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)

However I do not get any error if I hide the same lines in a function. The directory I’m using as a test is located in my desktop folder. I am on MacOs High Sierra.

Does anyone have a clue as to what’s going on?


#2

Tested on Windows works fine for me:

importClass(Packages.java.io.File);
importClass(Packages.ij.IJ);
var inputDirName, inputDir, list;
inputDirName = IJ.getDirectory("Choose input directory");
inputDir = new File(inputDirName);
list = inputDir.listFiles();
for (var i = 0; i < list.length; i++) {
	print(list[i])
}

Do you have filenames with extra chars, etc. What happen if you create a testfolder with subfolders?
On which OS are you working?


#3

This is not exactly the same script that @lollopus was using.

The issue specifically occurs when the script ends with a statement like:

list = inputDir.listFiles();

The SciJava script processor (part of ImageJ2 which is included in Fiji) will implicitly treat the last statement of a script as its output and try to handle it somehow (i.e. display it if it’s an image, show numbers in a table, etc.). It turns out that there’s no output postprocessor for outputs of type File (yet), and this case isn’t handled otherwise, unfortunately.

The output processing will not happen if:

  • your script specifically defines an output using script parameters, such as:
    #@output Integer result
    
    or
  • the last statement of your script doesn’t have a return value.

For example, these variations of your script will run without error:

importClass(Packages.java.io.File);
importClass(Packages.ij.IJ);
var inputDirName, inputDir, list;
inputDirName = IJ.getDirectory("Choose input directory");
inputDir = new File(inputDirName);
list = inputDir.listFiles();
null // suppress SciJava output postprocessing

importClass(Packages.java.io.File);
importClass(Packages.ij.IJ);
var inputDirName, inputDir, list;
inputDirName = IJ.getDirectory("Choose input directory");
inputDir = new File(inputDirName);
list = inputDir.listFiles();
print(list);

#@output Integer result
result = 42;

importClass(Packages.java.io.File);
importClass(Packages.ij.IJ);
var inputDirName, inputDir, list;
inputDirName = IJ.getDirectory("Choose input directory");
inputDir = new File(inputDirName);
list = inputDir.listFiles();

#4

Thanks for the thorough clarification!


#5

Indeed I tested it (the original) on ImageJ and then the variation on FIJI.

When using the original script I can reproduce the error as a result of the statement of @imagejan :

It turns out that there’s no output postprocessor for outputs of type File (yet), and this case isn’t handled otherwise, unfortunately.