javamaven-dependency-plugintwelvemonkeys

TwelveMonkeys 3.1.1 || 3.1.2 not working with maven-dependency-plugin


I am trying to use TwelveMonkeys in my application to deal with thumbnail generation. Also, I am using maven-dependency-plugin to unpack all dependencies and create a FAT jar. Though, plugin work quite well in normal scenarios, but simply not working when used with maven-dependency-plugin. Here is my POM XML:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.prakhar</groupId>
    <artifactId>demo</artifactId>
    <name>demo</name>

    <packaging>jar</packaging>
    <version>0.0.1-SNAPSHOT</version>

    <organization>
        <!-- Used as the 'Vendor' for JNLP generation -->
        <name>Your Organisation</name>
    </organization>

    <properties>
        <slf4j.version>1.6.1</slf4j.version>
    </properties>

    <build>
        <plugins>

            <plugin>
                <!-- Get the dependencies jar files to a common place, for jar signing -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>unpack-dependencies</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>unpack-dependencies</goal>
                        </goals>
                        <configuration>
                            <!-- <includeArtifactIds>commons-net,imageio-bmp,imageio-jpeg,imageio-tiff,imageio-pnm,imageio-psd,imageio-iff,imageio-pcx,imageio-pict,imageio-sgi,imageio-tga,imageio-icns,imageio-thumbsdb,imageio-core,imageio-metadata,common-lang,common-io,common-image</includeArtifactIds> -->
                            <outputDirectory>${project.build.directory}/classes</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>


    <dependencies>

        <!-- MigLayout -->



        <!-- Apache Commons -->

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>

        <!-- Logging  -->

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>

        <!-- Twelve Monkeys dependencies -->
        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-bmp</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-jpeg</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-tiff</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-pnm</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-psd</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-iff</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-pcx</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-pict</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-sgi</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-tga</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-icns</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-thumbsdb</artifactId>
            <version>3.1.1</version>
        </dependency>

    </dependencies>

</project>

And, here is my function:

private static void convertToJpg(File file) {
    try {
        BufferedImage image = ImageIO.read(file);

        int width = 300, height = 200; // new width/height

        BufferedImageOp resampler = new ResampleOp(width, height, ResampleOp.FILTER_LANCZOS); // A good default filter, see class documentation for more info
        BufferedImage thumbnailImg = resampler.filter(image, null);

        FileImageOutputStream fios = new FileImageOutputStream(new File(file.getAbsolutePath() + ".png"));

        if (!ImageIO.write(thumbnailImg, "PNG", fios)) {
            System.out.println("ERROR: Unable to convert image " + file.getAbsolutePath());
        } else {
            System.out.println("SUCCESS: Image " + file.getAbsolutePath() + ".png converted successfully");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Here is the exception I am getting:

java.lang.NullPointerException: Input == null
    at com.twelvemonkeys.image.ResampleOp.filter(Unknown Source)

If anybody have any idea of how might be solved, please state.


Solution

  • To sum it up, for future readers, the problem is that each ImageIO plugin JAR contains multiple resources under META-INF/services. These resources are needed for automatic discovery of the ImageIO plugins. They are:

    META-INF/services/javax.imageio.spi.ImageReaderSpi
    META-INF/services/javax.imageio.spi.ImageWriterSpi
    META-INF/services/javax.imageio.spi.ImageInpuStreamSpi
    META-INF/services/javax.imageio.spi.ImageOutputStreamSpi
    

    There might be more, but these are not used by TwelveMonkeys.

    For the interested you can read more about the Service Provider Interface mechanism and the ServiceRegistry class in particular.

    When you unpack all the JAR files into a single folder, these will be overwritten for each JAR. Instead, the resources with the same name needs to be merged into a new, single resource.

    The Maven Shade plugin provides a solution for this, see Resource transformers, especially the ServicesResourceTransformer.