Не удается найти хранилища данных Geotools при использовании подключаемого модуля maven

Я хочу получить доступ к различным хранилищам данных Geotools, используя Geotools (v. 17.1). В моем POM я использую плагин сборки maven (v. 3.0.0) для агрегирования выходных данных моего проекта:

<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>

Мои зависимости от геоинструментов:

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>
...

Проблема в том, что я могу просто получить доступ к шейп-файлам. В тестовом классе я написал этот код, чтобы выяснить, можно ли найти хранилища данных:

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
*/

Если я запускаю тот же код, используя сгенерированный JAR, я просто получаю:

//org.geotools.data.shapefile.ShapefileDataStoreFactory@1188e820
//org.geotools.data.shapefile.ShapefileDirectoryFactory@40f08448

Есть идеи, что может вызвать эту проблему?

1 ответ

Решение

Geotools использует инфраструктуру Java-сервисов для загрузки классов, реализующих определенные интерфейсы, такие как DataStores. Сервисная инфраструктура Java работает с текстовыми файлами, расположенными в /META-INF/services/ внутри jar-файлов.

При создании JAR-с-зависимостями вы объединяете несколько JAR-файлов в один. Скорее всего, текстовые файлы внутри /META-INF/services/ перезаписывают друг друга, когда несколько jar-файлов предоставляют реализации для одного и того же интерфейса.

Вы можете убедиться в этом, посмотрев на каталог services в созданной "fat-jar", особенно на запись /META-INF/services/org.geotools.data.DataStoreFactorySpi. Некоторые из исходных jar-файлов Geotools будут иметь такую ​​запись с разным содержимым, но "fat-jar" будет просто содержать один с содержимым случайного (в вашем случае тот, что для ShapeFiles).

Я не очень знаком с maven-shade-plugin, но другие вопросы по SO (такие как Maven shade + resteasy. Могут найти автора для типа контента, предложившего использовать дополнительный преобразователь:

<transformer
    implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />

Посмотрите также на аналогичный SO-вопрос с GeoTools: Geotools не может найти HSQL EPSG DB, выдает ошибку: NoSuchAuthorityCodeException

Другие вопросы по тегам