My target is to create an application, which uses Java 21.0.7 (OpenJDK), JavaFx 23.0.2 and GeoTools 34-SNAPSHOT to show S57 sea charts.
As a prerequirement I have downloaded javafx-sdk-23.0.2 as well and set the environment variable FX-PATH=C:\Git\openjfx-23.0.2_windows-x64_bin-sdk\javafx-sdk-23.0.2\lib.
The application contains the pom.xml and two classes:
<?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>org.example</groupId>
<artifactId>GeoToolsTest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<version.java>21</version.java>
<maven.compiler.source>${version.java}</maven.compiler.source>
<maven.compiler.target>${version.java}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.javafx>23.0.2</version.javafx>
<version.geotools>34-SNAPSHOT</version.geotools>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<dependencyManagement>
<dependencies>
<!-- Import the GeoTools BOM -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-bom</artifactId>
<version>${version.geotools}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>osgeo</id>
<name>OSGeo Release Repository</name>
<url>https://repo.osgeo.org/repository/release/</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
<repository>
<id>osgeo-snapshot</id>
<name>OSGeo Snapshot Repository</name>
<url>https://repo.osgeo.org/repository/snapshot/</url>
<snapshots><enabled>true</enabled></snapshots>
<releases><enabled>false</enabled></releases>
</repository>
</repositories>
<build>
<resources>
<resource>
<directory>src/main/config</directory>
<targetPath>${project.build.directory}</targetPath>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.0</version>
<configuration><release>${version.java}</release></configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<configuration><mainClass>org.example.Main</mainClass></configuration>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>org.example.Starter</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx</artifactId>
<version>${version.javafx}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${version.javafx}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId>
<version>${version.javafx}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-swing</artifactId>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-api</artifactId>
</dependency>
</dependencies>
</project>
The class org.example.Starter (which acts as a wrapper class):
package org.example;
public class Starter {
//Wrapper class
public static void main(String[] args) {
Main.main(args);
}
}
And the file: org.example.Main:
package org.example;
import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import org.geotools.api.data.DataStore;
import org.geotools.api.data.DataStoreFinder;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.swing.JMapPane;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("S-57 seachart with GeoTools");
SwingNode swingNode = new SwingNode();
createAndSetMapPane(swingNode);
BorderPane root = new BorderPane();
root.setCenter(swingNode);
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private void createAndSetMapPane(SwingNode swingNode) {
javafx.application.Platform.runLater(() -> {
MapContent mapContent = new MapContent();
mapContent.setTitle("S-57 Sea chart");
try {
File s57File = new File("PathToS57Files\\file.000");
Map<String, Object> params = new HashMap<>();
params.put("url", s57File.toURI().toURL());
DataStore dataStore = DataStoreFinder.getDataStore(params);
String typeName = dataStore.getTypeNames()[0];
Layer layer = new org.geotools.map.FeatureLayer(dataStore.getFeatureSource(typeName), null);
mapContent.addLayer(layer);
JMapPane mapPane = new JMapPane();
mapPane.setMapContent(mapContent);
swingNode.setContent(mapPane);
} catch (Exception e) {
e.printStackTrace();
}
});
}
public static void main(String[] args) {
launch(args);
}
}
I start my application with the following command:
java --module-path %FX-PATH% --add-modules javafx.controls,javafx.swing -jar GeoToolsTest-1.0-SNAPSHOT.jar Main
but it ends up with the following exception:
Exception in thread "main" java.lang.NoClassDefFoundError: org/geotools/api/data/FeatureSource
at org.example.Starter.main(Starter.java:7)
Caused by: java.lang.ClassNotFoundException: org.geotools.api.data.FeatureSource
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
... 1 more
Could someone explain, what is missing or wrong?
Some notices:
As far as i can see the class
FeatureSourceis part oforg.geotools.gt-apiand this dependency is included.Even if i remove the
gt-bom-pattern (which is introduced by version34-SNAPSHOT) and set allgeotools-dependencies to the last stable version33.2this exception appears.
--add-modules javafx.controls,javafx.swing← You didn’t add a module containing the geotools api classes, so it makes sense that the program cannot find them at runtime.