I want to access different Geotools datastores using Geotools (v. 17.1). In my POM I am using the maven assembly plugin (v. 3.0.0) to aggregate my project output:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<archive>
<manifest>
<mainClass>de.my.project.MainClass</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
My geotools dependencies:
dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>17.1</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geopkg</artifactId>
<version>17.1</version>
</dependency>
...
The problem is that I can just access Shapefiles. In a test class I wrote this code to figure out if the Datastores can be found:
Iterator gtIterator = DataStoreFinder.getAvailableDataStores();
while(gtIterator.hasNext()){
System.out.println(gtIterator.next().toString());
}
// results in:
/*
org.geotools.data.postgis.PostgisNGJNDIDataStoreFactory@25a65b77
org.geotools.data.postgis.PostgisNGDataStoreFactory@55ca8de8
org.geotools.geopkg.GeoPkgDataStoreFactory@8b96fde
org.geotools.data.mysql.MySQLJNDIDataStoreFactory@5d47c63f
org.geotools.data.oracle.OracleNGOCIDataStoreFactory@105fece7
org.geotools.data.shapefile.ShapefileDataStoreFactory@1dd92fe2
org.geotools.data.mysql.MySQLDataStoreFactory@275710fc
org.geotools.data.oracle.OracleNGDataStoreFactory@35083305
org.geotools.data.csv.CSVDataStoreFactory@6f3b5d16
org.geotools.data.shapefile.ShapefileDirectoryFactory@4f9a3314
org.geotools.data.oracle.OracleNGJNDIDataStoreFactory@2145433b
*/
If I am running the same code using the generated JAR I just get:
//org.geotools.data.shapefile.ShapefileDataStoreFactory@1188e820
//org.geotools.data.shapefile.ShapefileDirectoryFactory@40f08448
Any ideas what could cause this problem?
Geotools uses Java's Service infrastructure to load classes implementing certain interfaces, like DataStores. Java's Service infrastructure works with text files located in /META-INF/services/ inside the jar-files.
When building a jar-with-dependencies, you combine multiple jar files into one. Most likely, the text-files inside /META-INF/services/ overwrite each other when multiple jar files provide implementations for the same interface.
You could verify that by looking at the services-directory in the created "fat-jar", especially at the entry /META-INF/services/org.geotools.data.DataStoreFactorySpi. Several of the original Geotools jar-files will have such an entry with different content, but the "fat-jar" will just contain one with the content of a random one (in your case the one for the ShapeFiles).
I'm not really familiar with the maven-shade-plugin, but other questions on SO (like Maven shade + resteasy Could find writer for content-type suggest to use an additional transformer:
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
Have also a look at a similar SO-question with GeoTools: Geotools cannot find HSQL EPSG DB, throws error: NoSuchAuthorityCodeException