Error description
When uploading a picture, our project needs to do some post-upload processing. However, running the code after upload a JPEG file
BufferedImage bImg = ImageIO.read(file);
triggers the exception:
Caused by: java.lang.NoClassDefFoundError: com/twelvemonkeys/imageio/util/ProgressListenerBase
at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReaderSpi.createReaderInstance(JPEGImageReaderSpi.java:126)
at javax.imageio.spi.ImageReaderSpi.createReaderInstance(ImageReaderSpi.java:320)
at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:529)
at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:513)
at javax.imageio.ImageIO.read(ImageIO.java:1443)
at javax.imageio.ImageIO.read(ImageIO.java:1308)
Everything works well when uploading a PNG file.
Project configuration
Our Java EE 7 project initially requires TwelvesMonkeys to handle CMYK-encoded JPG images. The EAR is composed of:
- project-common (JAR)
- project-ejb (EJB) => depends on project-common
- project-web (WAR) => depends on project-common and project-ejb
- project-rest (WAR) => depends on project-common and project-ejb
project-common
has the TwelveMonkeys dependencies:
<!-- Image IO -->
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-bmp</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.3.2</version>
</dependency>
which are forwarded to the other components by transitivity. We only handled .jp(e)g
and .png
. We also use Thumbnailator along with TwelveMonkeys.
Troubleshooting
Following the documentation and this SO question, I have added the listener in
project-web
:<listener> <display-name>ImageIO service provider loader/unloader</display-name> <listener-class>com.twelvemonkeys.servlet.image.IIOProviderContextListener</listener-class> </listener>
Under Netbeans, the
com/twelvemonkeys/imageio/util/ProgressListenerBase
is present inproject-ejb
andproject-web
so I don't understand why the class is not foundRegardless if the
ImageIO.read(file)
is called inproject-ejb
orproject-web
, the error is the sameI tried adding
ImageIO.scanForPlugins()
beforeImageIO.read(file)
, the error is the same
Workaround
Following
Another safe option, is to place the JAR files in the application server's shared or common lib folder.
I have manually put the dependencies
# common dependencies:
> common-image-3.3.2.jar
> common-io-3.3.2.jar
> common-lang-3.3.2.jar
# shared dependencies:
> imageio-core-3.3.2.jar
> imageio-metadata-3.3.2.jar
# TwelveMonkeys dependencies:
> imageio-jpeg-3.3.2.jar
> imageio-bmp-3.3.2.jar
# Servlet
> servlet-3.3.2.jar
in {PAYARA_DIR}\glassfish\domains\{DOMAIN_NAME}\lib
folder without removing the listener. I changed the dependencies scope to<scope>provided</scope>
as it is not embedded in the application.
I put it as a workaround because I understand that adding the listener should have been enough so that manually adding the dependencies seems overkill. Moreover, even if we don't change our dependencies version that often, changing TwelveMonkeys dependencies means that theses dependencies need to be manually updated and replaced.
Question: is this workaround only solution or where did I messed up?