Reputation: 13
I have a project that I build FatJar from. Recently I have included additional dependencies from geotools. What I quickly discovered is that due to the geotools architecture I need to merge the META-INF/services, which I do using the mergeServiceFiles() in my shadowJar task. However, even with the mergeServiceFiles I still get an error:
WARNING: Can't load a service for category "Operation". Cause is "ServiceConfigurationError: org.geotools.api.coverage.processing.Operation: Provider org.geotools.coverage.processing.operation.ShadedRelief could not be instantiated".
Both, org.geotools.api.coverage.processing.Operation
and the org.geotools.coverage.processing.operation.ShadedRelief
are present in my dependencies (gt-api
and gt-coverage
) and are also included in the services.
Also, after inspecting the generated FatJar I can see that classes org.geotools.api.coverage.processing.Operation
and org.geotools.coverage.processing.operation.ShadedRelief
are present in the jar and org.geotools.api.coverage.processing.Operation
is present in the META-INF/services
and it does contain org.geotools.coverage.processing.operation.ShadedRelief
.
My Gradle settings is in line with the GeoTools for creating FatJars FAQ instruction - I am using Gradle's shadowJar plugin with the mergeServiceFiles task which is equivalent of the Maven's shadow plugin with the ServicesResourceTransformer:
plugins {
id("com.gradleup.shadow") version "8.3.0"
java
}
group = "test.it"
version = "0.0.1"
application {
mainClass.set("test.it.ApplicationKt")
}
repositories {
maven { url = uri("https://repo.osgeo.org/repository/release/") }
mavenCentral()
}
dependencies {
implementation("org.geotools:gt-coverage:31.2")
implementation("org.geotools:gt-main:31.2")
implementation("org.geotools:gt-api:31.2")
implementation("org.geotools:gt-geotiff:31.2")
implementation("org.geotools:gt-tile-client:31.2")
implementation("org.geotools.xsd:gt-xsd-kml:31.2")
implementation("org.geotools:gt-epsg-hsql:31.2")
implementation("org.osgeo:proj4j:0.1.0")
}
tasks {
shadowJar {
mergeServiceFiles()
isZip64 = true
archiveFileName.set("${project.name}-${project.version}.jar")
manifest {
attributes["Main-Class"] = "test.it.ApplicationKt"
//fix for the imageio vendor!=null error
//https://stackoverflow.com/questions/7051603/jai-vendorname-null/18495658#18495658
attributes["Specification-Title"] = "Java Advanced Imaging Image I/O Tools"
attributes["Specification-Version"] = version
attributes["Specification-Vendor"] = "Sun Microsystems, Inc."
attributes["Implementation-Title"] = "com.sun.media.imageio"
attributes["Implementation-Version"] = version
attributes["Implementation-Vendor"] = "Sun Microsystems, Inc."
}
}
}
I tried (with no luck):
It works fine when run with the -classpath including locations of the gt-api
and gt-coverage
jars.
UPADATE 12/09/2024
A temporary solution - adding exclude("META-INF/services/org.geotools.api.coverage.processing.*")
to the shadowJar task helps. This resolves the issue for that particular missing Class throwing the error.
Upvotes: 0
Views: 74
Reputation: 10976
As described in the FAQ, you need to take care when combining modules with META-INF/services
directories containing files of the same name. The recommendation is to use the Maven shade plugin, as far as I know none of the GeoTools developers uses gradle but I would expect there to be an equivalent plugin that can combine files rather than overwriting them.
If you work it out then could you add the information to the GeoTools FAQ for the benefit of others.
Upvotes: 0