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