How SciJava is related to the User Interface

I had a code that is opening CZI files as well as other images using imageJ through maven dependencies. As I was building up on that code I decided to use java 9 instead of the older version and in the way I decided to use updated versions of the dependencies. I managed to find the versions that runs together to have the code functional as expected.

My Current problem is that I use JavaFX file chooser which raises scijava alarms as well as errors related to missed classes of loci dependency which I am not using. I can ignore the loci problem for now but with scijava, my executable file doesn’t show up the file chooser as expected which I am able to open through the IDE.

I am attaching below the error alarms and loci errors that I got from the IDE. Any Idea how Scijava is messing with the UI thread?

The list of maven dependencies and repositories I am currently using,

    <repositories>
        <!-- ImageJ -->
        <repository>
            <id>imagej.public</id>
            <url>http://maven.imagej.net/content/groups/public</url>
        </repository>
    </repositories>
        <dependency>
            <groupId>net.imagej</groupId>
            <artifactId>imagej</artifactId>
            <version>2.0.0-rc-71</version>
        </dependency>

        <dependency>
            <groupId>net.imglib2</groupId>
            <artifactId>imglib2-ij</artifactId>
            <version>2.0.0-beta-45</version>
        </dependency>

        <dependency>
            <groupId>io.scif</groupId>
            <artifactId>scifio-bf-compat</artifactId>
            <version>4.1.0</version>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>ome</groupId>
            <artifactId>formats-gpl</artifactId>
            <version>6.2.1</version>
        </dependency>

        <dependency>
            <groupId>io.scif</groupId>
            <artifactId>scifio</artifactId>
            <version>0.41.0</version>
        </dependency>

I am uploading the error log here (64.9 KB)

I’m not sure ImageJ is compatible with Java 9. Is it ? Maybe @imagejan knows.

Note: I removed the #bio-formats tag since the only relationship in the log I can see is just debugging output:

12:52:45.043 [SciJava-5ebc997b-Thread-0] DEBUG loci.formats.ClassList - Could not find loci.formats.in.RCPNLReader
java.lang.ClassNotFoundException: loci.formats.in.RCPNLReader
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) ~[na:na]
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
2 Likes

As far as I can tell, it’s still recommended to use Java 8 for components of the SciJava software stack. I don’t remember the exact reasons, but I think some components were not yet working well with Java 9+. Maybe the situation has changed by now, though…

You should separate these two things: using Java 9; and updating the dependency versions.

For managing your dependencies, I recommend you inherit from the pom-scijava bill of materials (BOM), that way you can be sure to get versions that work well together.

If you want to work with JavaFX while using OpenJDK 8, you can install openjfx, as it’s done e.g. in this project for Travis CI:


To simplify troubleshooting, it would certainly help if you share your entire code repository, instead of just excerpts of your pom.xml.

5 Likes

Here this is the full pom I am using,

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mygroupId</groupId>
    <artifactId>myProjectName</artifactId>
    <version>0.0.1</version>
    <packaging>jar</packaging>


    <build>
        <plugins>
            <!-- Copy Dependencies -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <archive>
                                <manifest>
                                    <mainClass>
                                        com.mygroupId.MainClass
                                    </mainClass>
                                </manifest>
                            </archive>
                            <descriptorRefs>
                                <descriptorRef>jar-with-dependencies</descriptorRef>
                            </descriptorRefs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <!-- Compiler needed for java11 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <release>11</release>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.ow2.asm</groupId>
                        <artifactId>asm</artifactId>
                        <version>8.0.1</version>
                    </dependency>
                </dependencies>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.mygroupId.MainClass</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>

            <!-- JavaFX -->
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.4</version>
                <configuration>
                    <mainClass>com.mygroupId.MainClass</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <!-- Set Maven encoding -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>11</java.version>
        <maven.compiler.release>11</maven.compiler.release>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <repositories>
        <!-- ImageJ -->
        <repository>
            <id>imagej.public</id>
            <url>http://maven.imagej.net/content/groups/public</url>
        </repository>

        <!-- The two below repositories can replace the public one -->
        <!--<repository>
            <id>imagej.releases</id>
            <url>http://maven.imagej.net/content/repositories/releases/</url>
        </repository>
        <repository>
            <id>scijava.public</id>
            <url>https://maven.scijava.org/content/groups/public</url>
        </repository>-->

    </repositories>

    <dependencies>
        <!-- JavaFX 11 is not part of the JDK anymore -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>11</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>11</version>
            <type>jar</type>
        </dependency>

        <!-- ImageJ -->
        <dependency>
            <groupId>net.imagej</groupId>
            <artifactId>imagej</artifactId>
            <version>2.0.0-rc-71</version>
        </dependency>

        <dependency>
            <groupId>net.imglib2</groupId>
            <artifactId>imglib2-ij</artifactId>
            <version>2.0.0-beta-45</version>
        </dependency>

        <dependency>
            <groupId>io.scif</groupId>
            <artifactId>scifio-bf-compat</artifactId>
            <version>4.1.0</version>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>ome</groupId>
            <artifactId>formats-gpl</artifactId>
            <version>6.2.1</version>
        </dependency>

        <dependency>
            <groupId>io.scif</groupId>
            <artifactId>scifio</artifactId>
            <version>0.41.0</version>
        </dependency>
    </dependencies>

</project>

Below is my code,

import ij.CompositeImage;
import ij.ImagePlus;
import ij.IJ;
import ij.ImageStack;
import ij.plugin.HyperStackReducer;
import net.imagej.Dataset;
import net.imagej.ImageJ;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.*;

import java.util.Arrays;
import java.util.List;

import net.imglib2.img.Img;
import net.imglib2.img.display.imagej.ImageJFunctions;
import org.apache.commons.io.filefilter.WildcardFileFilter;


import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.util.*;

import static ij.plugin.ChannelSplitter.splitRGB;


public class MainController implements Initializable {

    @FXML
    private ProgressIndicator progressIndicator;

    @FXML
    private Label notifyLabel;

    @FXML
    private TabPane imageTabs;

    public void initialize(URL location, ResourceBundle resources) {
        System.out.println("The Window is Loaded!!!");
    }

    @FXML
    void openBtnAction() {
        System.out.println("Open Button Clicked!!!");

        // imageJ variables
        ImageJ imageJ = new ImageJ(); // all the errors appears at this step

errors.txt (65.5 KB)

I don’t know about Scijava, but your log mentioned MacOSPlatform: if you’re running on a Mac, there certainly are threading troubles when mixing JavaFX with AWT/Swing.

See for example this old (yet open) bug report:

These Mac-specific, JavaFX-related issues also arose recently on image.sc here:

My experience so far has been that there is generally a way to get JavaFX to work nicely with other Java code (except perhaps with system menubars…), but copying with the Application thread vs. Event Dispatch Thread requires a lot of extra care on the Mac – and often some rather ugly workarounds.

(PS. If you’re making the leap from Java 8 to 9, why not go further to Java 11…? Since it’s a long term support release, and 9/10 were somewhat short-lived, I guess there might be better documentation available for any issues.)

2 Likes

I am running on windows not on mac and I am not intending to use the UI of imageJ. I only need its reading for images single, stack, composite and CZI format. I am using JDK 11.0.4.

Should I switch to lower jdk or is it possible to work with the current or higher versions?
I have almost (the executable doesn’t show up anything) the same problem with jdk 8 but with different code and I thought that I did something wrong with the build in maven.

Also do you suggest opening the images in different way than having an instance of ImageJ as I did in this code?

Ah ok, I misunderstood the significance of the line

[JavaFX Application Thread] DEBUG org.bushe.swing.event.EventService  - Subscribing by class, class:class org.scijava.display.event.window.WinActivatedEvent, subscriber:AbstractProxySubscriber{realSubscriber=org.scijava.plugins.platforms.macos.MacOSPlatform@56db64d5, subscriptionMethod=protected void org.scijava.plugins.platforms.macos.MacOSPlatform.onEvent(org.scijava.display.event.window.WinActivatedEvent), veto=false, referenceStrength=WEAK, eventService=org.scijava.event.DefaultEventBus@4560b94}

Sorry I don’t know enough about scijava to help further in that regard.

I develop QuPath, which is a JavaFX application that uses the latest OpenJDK (compatible with 11+, but works best with 14+ because of the inclusion of jpackager to create installers) and Bio-Formats directly to read images, including CZI. QuPath can also convert images into ImageJ1-friendly formats (ImagePlus, CompositeImage) as required, but doesn’t use them as its primary representation.

So I’m effectively only using formats-gpl from your original list of maven dependencies, in addition to ij (but this isn’t strictly needed unless you need to create an ImagePlus).

I’ve had no problems with that arrangement. I expect scijava has a lot of advantages, but I haven’t had the time or need to explore them yet – and I’ve wanted to keep dependencies relatively low, while embracing JavaFX.

(Sidenote: I have not found a way to call Fiji from within QuPath, since they do have quite a lot of incompatible dependencies… but I can launch QuPath from Fiji via a script and things mostly work, if Fiji is running on JDK 11+. This is however a lot more awkward and quite brittle, since both sides are fairly complex.)

4 Likes

I tried that but I am having error reading CZI file using this method,

ImagePlus imp = null;
ImagePlus [] imps = null;

try {
    imps = BF.openImagePlus(selectedFile.getPath());
    } 
	
	catch (FormatException e) {
		e.printStackTrace();
    } 
	
	catch (IOException e) {
        e.printStackTrace();
    }
	
    imp = imps[0];

using the maven dependency of loci plugins as follows,

        <dependency>
            <groupId>loci</groupId>
            <artifactId>loci_plugins</artifactId>
            <version>5.0.0-beta1</version>
        </dependency>

I get this error at BF.openImagePlus() line error.txt (24.6 KB)

Instead I use this method which works only with the IDE but not in the executable as I think I am using the UI thread creating ImageJ instance,

ImageJ imageJ = new ImageJ();
ImagePlus imp = null;
Dataset dataset = null;

try {
    dataset = imageJ.scifio().datasetIO().open(selectedFile.getPath());
    } 
	
	catch (IOException e) {
        e.printStackTrace();
    }
}

//converting from ImageJ2 ImgPlus() to ImageJ1 ImagePlus()
Img image = dataset.getImgPlus().getImg();
imp = ImageJFunctions.wrap(image);

I also tried this method but it can’t read the image giving null,
imp = ij.io.Opener.openUsingBioFormats(selectedFile.getPath());

So generally I can’t find away reading CZI files. I searched online and found only the top two methods used. I don’t know If I need to read more about ImageJ tutorials or that it might be something related to version conflicts or as stated earlier that ImageJ doesn’t work with Java11.

All I see in that file is debug output, but nothing that looks like an error.
So what’s the actual error you get?

3 Likes

my mistake it actually at this step throw an UI thread exception. The exception shown directly after the alarms I have sent. error.txt (6.1 KB)

I debugged to see where is the last point before the exception is thrown. That is in the class OptionsList

Object o;
        for(Iterator i$ = ini.iterator(); i$.hasNext(); this.options.put(((Option)o).getKey(), o)) {
            IniTable entry = (IniTable)i$.next();
            String type = entry.get("type");  // at this step

I also made another trial with replacing the ImageJ instance by calling directly the SCIFIO class as below,

try {
    SCIFIO scifio = new SCIFIO();  // first file alarms
    dataset = scifio.datasetIO().open(selectedFile.getPath()); // second file alarms
    // dataset = imageJ.scifio().datasetIO().open(selectedFile.getPath());
} 

catch (IOException e) {
    e.printStackTrace();
}

yet the file chooser wasn’t blocked in the executable at the location where I used to have imageJ instance yet it didn’t show what I was expecting it to show (a window showing information about the chosen file) which again works normally in the IDE.
first file alarms (55.1 KB)
second file alarms (23.5 KB)

and to isolate the problem that it is not with the window I created, I confirmed that it shows up normally using the executable with the below line.
imp = IJ.openImage(selectedFile.getPath());

It is also important to mention while building with maven I get the below warning,

Supported source version ‘RELEASE_8’ from annotation processor ‘org.scijava.annotations.AnnotationProcessor’ less than -source ‘11’

and if I excluded SciJava from the repositories,

<repository>
    <id>scijava.public</id>
    <url>https://maven.scijava.org/content/groups/public</url>
</repository>

I would get the following errors while building with maven,

Failure to find ome:formats-gpl:pom:6.2.1 in http://maven.imagej.net/content/repositories/releases/ was cached in the local repository, resolution will not be reattempted until the update interval of imagej.releases has elapsed or updates are forced

Could not find artifact ome:formats-gpl:jar:6.2.1 in imagej.releases (http://maven.imagej.net/content/repositories/releases/)

I added the line of dataset calling dataset = scifio.datasetIO().open(selectedFile.getPath()); in a separate thread and yet the window I am expecting to showup is running in the background but not seen. In order to edit the executable I have to force close it from the task manager.

While trying to run the jar file through the IDE I got the below error

[WARNING] Class pool is empty: forgot to call Thread#setClassLoader?
Exception in thread “JavaFX Application Thread” java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

Caused by: java.lang.IllegalArgumentException: No compatible service: org.scijava.service.SciJavaService at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:244)

Caused by: java.lang.IllegalArgumentException: No compatible service: org.scijava.service.SciJavaService

The full log is here (6.3 KB)

I also found a previous question related to the problem

I also found this question that is having the same exact error and I also had similar pom file regarding maven plugin but when I applied the solution worked for him, I still got errors with SciJava.

Also In MailArchive link is stating a problem with SciJava Service problem with showing images.

@imagejan

I did inherit from pom-imagej as advised and I got

Failed to execute goal org.apache.maven.plugins:maven-enforcer-plugin:1.4.1:enforce (enforce-rules) on project rebuildingStructure: Some Enforcer rules have failed. Look above for specific messages explaining why the rule failed.

<parent>
    <groupId>org.scijava</groupId>
    <artifactId>pom-scijava</artifactId>
    <version>29.2.1</version>
</parent>

The warnings,

[WARNING] Rule 2: org.apache.maven.plugins.enforcer.RequireJavaVersion failed with message:
Detected JDK Version: 11.0.8 is not in the allowed range [1.8.0-101,1.8.9999].
[WARNING] Rule 3: org.apache.maven.plugins.enforcer.BanDuplicateClasses failed with message:
No Duplicate Classes Allowed!

  • For duplicate transitive dependencies, add dependency exclusions.
  • For duplications between direct dependencies, resolve or add
    ignored classes to this rule’s configuration.
    Found in:
    org.openjfx:javafx-base:jar:win:11.0.1:compile

full warnings.txt (255.6 KB)

@petebankhead

I started this project having no imageJ dependencies and I started adding the minimum possible and whenever I add one I find classes missing so I addd the other. All I need is to use imagePlus and open bioformats. For example I needed net.imglib2.img.display.imagej.ImageJFunctions; to convert ImgPlus to ImagePlus which is needed to open bioformats into dataset then from dataset to ImgPlus then to ImagePlus and finally I apply same commands on all ImagePlus either opened directly or through bioformats.

I would also need ParticleAnaylzer and 3D Counting. I don’t need any User Interfaces from ImageJ, as I am showing only specific data out of the analysis.

I am struggling with Bioformats for now so how did you manage that with only formats-gpl? Can you show me an example?

now that I am trying this method after adding more dependencies from loci to assure it is working. The error comes at

  public OptionsList(IniList ini) {
    options = new HashMap<String, Option>();
    for (IniTable entry : ini) {
      String type = entry.get(INI_TYPE);
      Option o;
      if (type.equals(TYPE_BOOLEAN)) o = new BooleanOption(entry);
      else if (type.equals(TYPE_STRING)) o = new StringOption(entry);
      else throw new IllegalArgumentException("Unknown type: " + type);
      options.put(o.getKey(), o);
    }
  }

where it tries to get INI_TYPE but this doesn’t exist in the entry object,
image

Error

Caused by: java.lang.NoSuchMethodError: ‘java.lang.String loci.common.IniTable.get(java.lang.Object)’
at loci.plugins.prefs.OptionsList.(OptionsList.java:72)
at loci.plugins.prefs.OptionsList.(OptionsList.java:66)
at loci.plugins.in.ImporterOptions.(ImporterOptions.java:158)
at loci.plugins.BF.openImagePlus(BF.java:78)
at com.navimatix.controllers.MainController.openBtnAction(MainController.java:206)
… 59 more

this method using BF worked now but with using only bio-formats_plugins in both IDE and executable. I also added net.imglib2 as it provided ij.ImagePlus.

    <dependency>
        <groupId>net.imglib2</groupId>
        <artifactId>imglib2-ij</artifactId>
        <version>2.0.0-beta-45</version>
    </dependency>

    <dependency>
        <groupId>ome</groupId>
        <artifactId>bio-formats_plugins</artifactId>
        <version>6.1.1</version>
    </dependency>