0

I'm trying to move a tomcat server that was run on a CentOS 7 operating system into a docker container. However, I got Could not initialize class javax.imageio.ImageIO error after moving it into the docker container.

enter image description here

Here is an ant project that creates a helloworld.war file for reproducing my problem.

I've tried the following tomcat docker tags in dockerhub, but all of them create the ImageIO error.

  • 8-jdk8
  • 8.5.43-jdk13-openjdk-oracle
  • 8.5.43-jdk8-adoptopenjdk-hotspot
  • 7.0.94-jre8
  • 7.0.96-jdk8-openjdk
  • 8.5.43-jdk13-openjdk-oracle

The tomcat installed by yum install tomcat on my CentOS 7 doesn't have the ImageIO error.

Why does this happen?

The java and tomcat version on my CentOS 7 are

openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)

and

Apache Tomcat/7.0.76

Another fact that I found is setting JAVA_OPTS as "-Djava.awt.headless=true" instead of "-Djava.awt.headless=true -server" can avoid the problem.

Is it possible to run the tomcat service in a docker container with JAVA_OPTS="-Djava.awt.headless=true -server" and without Could not initialize class javax.imageio.ImageIO error?

The way I pass value to JAVA_OPTS is by setting

environment:
    - JAVA_OPTS="-Djava.awt.headless=true -server"`

in the docker-compose.yml file

I've run ps aux | grep java to verify that the java program inside the docker container has java.awt.headless value set.

This post says you can set JAVA_OPTS="-Djava.awt.headless=true -Dawt.toolkit=sun.awt.HToolkit" to avoid Could not initialize class javax.imageio.ImageIO problem.

The full log is as the following:

SEVERE: Servlet.service() for servlet [mypackage.HelloworldServlet] in context with path [/helloworld] threw exception [Servlet execution threw an exception] with root cause
java.lang.NoClassDefFoundError: Could not initialize class javax.imageio.ImageIO
        at mypackage.HelloworldServlet.doGet(Unknown Source)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:444)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:1025)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1137)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
        at org.apache.tomcat.util.net.AprEndpoint$SocketWithOptionsProcessor.run(AprEndpoint.java:2516)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)
Brian
  • 12,145
  • 20
  • 90
  • 153
  • The `-server` option is the [default on 64-bit systems](https://stackoverflow.com/questions/198577/real-differences-between-java-server-and-java-client/198651?noredirect=1#comment59707599_198651) anyway (you almost certainly don't need it). – Elliott Frisch Aug 07 '19 at 05:45
  • When you set `java.awt.headless=true` you explicitly say that you do not want awt classes to be used. I think your problem is that you are passing JAVA_OPTS in a wrong way. And actually the value of `java.awt.headless` is resolved to `true -server` and not `true`. Please show where and how you are passing JAVA_OPTS to the container/image. – Michał Krzywański Aug 07 '19 at 05:53
  • try passing the parameters in JAVA_OPTS in reversed order `JAVA_OPTS="-server -Djava.awt.headless=true"` – Michał Krzywański Aug 07 '19 at 06:40
  • `JAVA_OPTS="-server -Djava.awt.headless=true"` doesn't work. I got the same error. – Brian Aug 07 '19 at 06:42
  • What is the full stack trace from the logs? That might help. As @michalk says, `-server` is not required. The `headless` option is often necessary. You are a bit far back in Tomcat versions; consider upgrading (though this has nothing to do with your error). – Christopher Schultz Aug 08 '19 at 14:25
  • Hi, @ChristopherSchultz, I've added the full log to the end of my question. – Brian Aug 08 '19 at 14:44
  • No "caused by" after what you have posted? Usually "Could not initialize class *Foo*" has some more explanation. – Christopher Schultz Aug 09 '19 at 01:39

1 Answers1

0

I had the same problem when trying to move Tomcat server on Windows into docker container. java.awt.headless=true did not help. I could solve this problem by replacing the mcr.microsoft.com/windows/servercore docker image with the official AdoptOpenJDK docker image.