Bug#1087811: josm: MapWithAI plugin – java.lang.ClassNotFoundException: org.apache.commons.io.input.BoundedInputStream
Hermann Schwarting
bugs.debian.org at knackich.de
Mon Nov 18 23:15:50 GMT 2024
Package: josm
Version: 0.0.svn19253+dfsg-1
Severity: normal
X-Debbugs-Cc: bugs.debian.org at knackich.de
Dear Maintainer,
I’m trying to use the MapWithAI plugin with a specific data source and
it fails to download data with this error:
java.lang.ClassNotFoundException:
org.apache.commons.io.input.BoundedInputStream
The problem was introduced at some point during October 2024. I’ve used
the plugin successfully many times at least until September 2024.
Steps to reproduce:
Add the plugin. Open the Preferences (F12) › Plugins. Search for
"mapwithai". Check the entry and confirm with OK.
Add a custom data source: Menu › Data › MapWithAI › MapWithAI
Preferences. In the bottom part, press the "+" button to add a custom
data source. In the dialog that comes up, enter:
2. Enter Service URL =
https://hfs.github.io/brandenburg-addresses/missing.pmtiles
3. Enter name for this source = GeoBasis-DE/LGB (2024): Georeferenzierte
Adresse
4. What is the type of this source? = PMTILES
Close the preferences with OK.
Now download some OpenStreetMap data. File › Download data…
Zoom in on any region in the map – the location in the world doesn’t
matter – and draw a small rectangle › Download.
The OpenStreetMap data is downloaded and shown as new editor layer.
Now try to download extra data using the plugin. Data › MapWithAI ›
GeoBasis-DE/LGB (2024): Georeferenzierte Adresse
The expected behavior would be that data gets fetched for the selected
location and displayed in a new layer called "MapWithAI". If the
selected location happens to be in Brandenburg, Germany, there might be
actual data to download. Anywhere else, there will be no data and the
"MapWithAI" layer would be empty.
Instead, the error dialog comes up. This Java exception is logged:
2024-11-18 21:56:19.278 SEVERE: Handled by bug report queue:
java.lang.NoClassDefFoundError. Cause: java.lang.NoClassDefFoundError:
org/apache/commons/io/input/BoundedInputStream. Cause:
java.lang.ClassNotFoundException:
org.apache.commons.io.input.BoundedInputStream
java.lang.NoClassDefFoundError
at
java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
at
java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
at
java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
at
java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:542)
at
java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:567)
at java.base/java.util.concurrent.ForkJoinTask.join(ForkJoinTask.java:653)
at
org.openstreetmap.josm.plugins.mapwithai.actions.AddMapWithAILayerAction.realRun(AddMapWithAILayerAction.java:123)
at
org.openstreetmap.josm.plugins.mapwithai.actions.AddMapWithAILayerAction.lambda$actionPerformed$2(AddMapWithAILayerAction.java:88)
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.NoClassDefFoundError:
org/apache/commons/io/input/BoundedInputStream
at
org.openstreetmap.josm.plugins.pmtiles.lib.PMTiles.decompressInputStream(PMTiles.java:263)
at
org.openstreetmap.josm.plugins.pmtiles.lib.PMTiles.readRootDirectory(PMTiles.java:69)
at
org.openstreetmap.josm.plugins.mapwithai.backend.BoundingBoxMapWithAIDownloader.readMvt(BoundingBoxMapWithAIDownloader.java:296)
at
org.openstreetmap.josm.plugins.mapwithai.backend.BoundingBoxMapWithAIDownloader.parseDataSet(BoundingBoxMapWithAIDownloader.java:265)
at
org.openstreetmap.josm.io.BoundingBoxDownloader.parseOsm(BoundingBoxDownloader.java:217)
at
org.openstreetmap.josm.plugins.mapwithai.backend.BoundingBoxMapWithAIDownloader.parseOsm(BoundingBoxMapWithAIDownloader.java:160)
at
org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIDataUtils.lambda$download$6(MapWithAIDataUtils.java:178)
at
java.base/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1456)
at
java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:387)
at
java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843)
at
java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808)
at
java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188)
Caused by: java.lang.ClassNotFoundException:
org.apache.commons.io.input.BoundedInputStream
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)
... 13 more
This error affects only the Debian version of JOSM. When I download the
official release from https://josm.openstreetmap.de/josm-tested.jar and
run it with
java --add-exports=java.base/sun.security.action=ALL-UNNAMED
--add-exports=java.desktop/com.sun.imageio.plugins.jpeg=ALL-UNNAMED
--add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED -jar
josm-tested.jar
it works as expected. The official release version is currently 19253,
which is the same as used in the Debian package.
I believe this is a dependency version conflict regarding the Apache
commons-io library.
The MapWithAI plugin (version 837) gets installed into
~/.local/share/JOSM/plugins/mapwithai.jar
It pulls in other plugin as dependency: apache-commons (version 36349) in
~/.local/share/JOSM/plugins/apache-commons.jar
and pmtiles (version 36219) in
~/.local/share/JOSM/plugins/pmtiles.jar
PMTiles.decompressInputStream(PMTiles.java:263) from the stacktrace is
this place in the PMTiles plugin:
https://josm.openstreetmap.de/browser/osm/applications/editors/josm/plugins/pmtiles/src/main/java/org/openstreetmap/josm/plugins/pmtiles/lib/PMTiles.java?rev=36219#L263
The line that fails is
new GzipCompressorInputStream(inputStream);
org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
comes from commons-compress.
According to
https://josm.openstreetmap.de/browser/josm/trunk/nodist/pom.xml?rev=19251#L287
JOSM uses version 1.27.1 of commons-compress.
The constructor of GzipCompressorInputStream,
https://github.com/apache/commons-compress/blob/rel/commons-compress-1.27.1/src/main/java/org/apache/commons/compress/compressors/gzip/GzipCompressorInputStream.java#L155
calls
countingStream =
BoundedInputStream.builder().setInputStream(inputStream).get();
org.apache.commons.io.input.BoundedInputStream is a dependency from
commons-io and the class the ClassNotFoundException was about.
BoundedInputStream is indeed included in the apache-commons plugin:
$ unzip -l ~/.local/share/JOSM/plugins/apache-commons.jar | grep
BoundedInputStream
(base)
732 2024-08-16 20:14
org/apache/commons/compress/utils/BoundedInputStream.class
1925 2024-09-15 14:44
org/apache/commons/io/input/BoundedInputStream$AbstractBuilder.class
1532 2024-09-15 14:44
org/apache/commons/io/input/BoundedInputStream$Builder.class
3831 2024-09-15 14:44
org/apache/commons/io/input/BoundedInputStream.class
By running JOSM with -verbose:class, I noticed that
GzipCompressorInputStream gets loaded from the system-wide version and
not from the plugin:
[28,500s][info][class,load]
org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
source: file:/usr/share/java/commons-compress.jar
In contrast, when running JOSM’s official release, it gets loaded from
the plugin
[25,273s][info][class,load]
org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
source: file:/home/user/.local/share/JOSM/plugins/apache-commons.jar
I also found it noteworthy that BoundedInputStream is contained in the
official JOSM JAR, but not Debian’s JAR?
[27,222s][info][class,load]
org.apache.commons.io.input.BoundedInputStream source:
file:/home/user/Download/josm-tested.jar
[27,230s][info][class,load]
org.apache.commons.io.input.BoundedInputStream$AbstractBuilder source:
file:/home/user/Download/josm-tested.jar
[27,230s][info][class,load]
org.apache.commons.io.input.BoundedInputStream$Builder source:
file:/home/user/Download/josm-tested.jar
$ unzip -l /usr/share/josm/josm-0.0.svn19253+dfsg.jar | grep BoundedInput
1862 2024-11-01 05:02
org/openstreetmap/josm/io/OsmPbfReader$BoundedInputStream.class
I have no idea how the class loaders are set up to support plugins.
Could it be that GzipCompressorInputStream from
/usr/share/java/commons-compress.jar can’t "see" BoundedInputStream from
the plugin, because that would require to go through a different class
loader?
As a little experiment I edited
/usr/share/josm/josm-0.0.svn19253+dfsg.jar and added
/usr/share/java/commons-io.jar to the Class-Path: line in
META-INF/MANIFEST.MF. This fixed the immediate issue, but I have no idea
about possible side effects.
Thanks!
Hermann
-- System Information:
Debian Release: trixie/sid
APT prefers testing
APT policy: (700, 'testing'), (650, 'unstable'), (600,
'experimental'), (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 6.11.5-amd64 (SMP w/8 CPU threads; PREEMPT)
Locale: LANG=de_DE.utf8, LC_CTYPE=de_DE.utf8 (charmap=UTF-8), LANGUAGE
not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
Versions of packages josm depends on:
ii default-jre [java11-runtime] 2:1.21-76
ii fonts-noto 20201225-2
ii jmapviewer 2.22+dfsg-1
ii libcommons-compress-java 1.27.1-2
ii libgettext-commons-java 0.9.6-6
ii openjdk-11-jre [java11-runtime] 11.0.25+9-1
ii openjdk-14-jre [java11-runtime] 14.0.2+12-2
ii openjdk-17-jre [java11-runtime] 17.0.13+11-2
ii openjdk-21-jre [java11-runtime] 21.0.5+11-1
ii proj-data 9.5.0-1
Versions of packages josm recommends:
ii josm-l10n 0.0.svn19253+dfsg-1
ii openjfx 11.0.11+1-3.2
josm suggests no packages.
-- Configuration Files:
/etc/default/josm changed [not included]
-- no debconf information
Java version:
$ java -version
openjdk version "21.0.5" 2024-10-15
OpenJDK Runtime Environment (build 21.0.5+11-Debian-1)
OpenJDK 64-Bit Server VM (build 21.0.5+11-Debian-1, mixed mode, sharing)
More information about the Pkg-grass-devel
mailing list