Плагин библиотеки PSD ImageIO не работает внутри банки - PullRequest
0 голосов
/ 29 декабря 2018

Я работаю с ImageIO и пытаюсь упаковать код в JAR, однако я обнаружил (после некоторой отладки), что PSD-плагин отсутствует внутри упакованного JAR

Я узнал благодаря коду в этом ответе: Добавить / удалить ImageReader из jar в ImageIO-Registry

В моем pom.xml у меня есть следующие зависимости ImageIO:

   <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-bmp</artifactId>
        <version>3.4</version>
    </dependency>
    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-psd</artifactId>
        <version>3.4</version>
    </dependency>
    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-core</artifactId>
        <version>3.4</version>
    </dependency>
    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-metadata</artifactId>
        <version>3.4</version>
    </dependency>

Используемая мной команда maven:

clean compile assembly:single

Обратите внимание на код, который я использовал для отладки:

        ImageIO.scanForPlugins()
        IIORegistry.getDefaultInstance().registerApplicationClasspathSpis()
        val ir = ImageIO.getImageReadersByFormatName("PSD")
        while (ir.hasNext())
        {
            val r = ir.next() as ImageReader
            println(r)
        }

Который в IDE печатает:

com.twelvemonkeys.imageio.plugins.psd.PSDImageReader@1963006a

И при запуске jar из командной строки он ничего не печатает, что наводит меня на мысль, что плагин PSD не работает внутри JAR, но как?

1 Ответ

0 голосов
/ 29 декабря 2018

Проблема в том, что цель assembly:single объединяет «все» из вашего собственного проекта и всех JAR-файлов, на которые есть ссылки, в один JAR, но пропускает файлы, которые там еще существуют.

ImageIO использует механизм загрузки SPI / serviceJava и, следовательно, плагины будут загружены через META-INF\services\javax.imageio.spi.ImageReaderSpi.Однако при наличии более одного JAR с таким файлом и использовании assembly:single один из этих файлов «выигрывает», а другие из других JAR пропускаются.В вашем проекте оба файла imageio-bmp и imageio-psd имеют такой файл, и первый из них "выигрывает" в полученном JAR-файле.(Похоже, IDE загружает эти файлы в другом порядке, и правильная версия «выигрывает», но это всего лишь предположение.)

Решение: Maven должен объединить все файлы META-INF\services\javax.imageio.spi.ImageReaderSpi водин файл в результирующем JAR.Для этого Maven требуется дополнительная информация о конфигурации.

  1. Добавьте файл descriptor.xml в корневой каталог вашего проекта, например, так:
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
    <!-- copied from jar-with-dependencies (http://maven.apache.org/plugins/maven-assembly-plugin/descriptor-refs.html#jar-with-dependencies) -->
    <id>jar-with-deps-merge-services</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <containerDescriptorHandlers>
        <containerDescriptorHandler>
            <handlerName>metaInf-services</handlerName>
        </containerDescriptorHandler>
    </containerDescriptorHandlers>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>
</assembly>

Важноечасть - это настройка metaInf-services, которая объединяет файлы в META-INF\services.

Добавьте ссылку на descriptor.xml в вашем pom.xml:
[...]
<build>
    <plugins>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2.1</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>your.main.MainClass</mainClass>
                    </manifest>
                </archive>
                <descriptors>
                    <descriptor>descriptor.xml</descriptor>
                </descriptors>
            </configuration>
        </plugin>
    </plugins>
</build>

Важные примечания:

  • Maven-версия сборки-плагина должна быть 2.2.1, потому что текущая версия 3.x не работает.Тем не менее, вы можете попробовать более новые версии 2.2.x или 2.x, если это действительно необходимо.Я только пробовал 2.2.1, и он работает.
  • Блок основного класса должен быть изменен в соответствии с именем вашего основного класса, если вам это нужно.
  • Файл дескриптора может быть помещен вдругой каталог в вашем проекте, но затем необходимо изменить ссылку в pom (это относительно корня вашего проекта maven).
  • Если у вас есть jar-with-dependencies в вашей конфигурации сборки, это должно бытьудален, потому что файл дескриптора включает эту настройку.

Даже при том, что я попробовал это на примере проекта, это решение может быть не идеальным, и вы можете адаптировать его в соответствии со своими потребностями, но я надеюсь, что этоподходящая точка для начала.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...