I was trying to run one of my existing web application on recently released Glassfish v31 in Linux environment. This is an early access release that will eventually replace GlassFish 3.0.1 with new clustering and centralized admin features.
In our web application we are using Kaptcha to avoid spamming on few pages, which is really simple to integrate with any java web application. ( A CAPTCHA helps you keep your site clean by automatically blocking spam. CAPTCHA is a contrived acronym for “Completely Automated Public Turing test to tell Computers and Humans Apart.“)
This application works perfectly fine with Tomcat 6, therefore ideally the application should run without any problem on any other JEE application server. We deployed the war file and everything started working except for the Kaptcha image. When we hit the Kaptcha URL (which of format http://host:port/app/kaptcha) directly it throws below error on the browser
HTTP Status 500 - type Exception report message description The server encountered an internal error () that prevented it from fulfilling this request. exception javax.servlet.ServletException: PWC1243: Filter execution threw an exception root cause java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11GraphicsEnvironment note The full stack traces of the exception and its root causes are available in the GlassFish3.1-b05 logs. GlassFish3.1-b05
When we checked the server logs we found this exception stack-trace
[#|2010-06-22T16:55:30.908-0700|WARNING|glassfish3.1|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=143;_ThreadName=Thread-1;|StandardWrapperValve[Kaptcha]: PWC1406: Servlet.service() for servlet Kaptcha threw exception java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11GraphicsEnvironment at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:68) at java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1135) at com.google.code.kaptcha.text.impl.DefaultWordRenderer.renderWord(DefaultWordRenderer.java:41) at com.google.code.kaptcha.impl.DefaultKaptcha.createImage(DefaultKaptcha.java:41) at com.google.code.kaptcha.servlet.KaptchaServlet.doGet(KaptchaServlet.java:82) at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) at javax.servlet.http.HttpServlet.service(HttpServlet.java:844) at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1518) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:339) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:171) at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:651) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:591) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94) at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:87) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:158) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:321) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:222) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:802) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:705) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:986) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:178) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) at com.sun.grizzly.ContextTask.run(ContextTask.java:69) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:526) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:507) at java.lang.Thread.run(Thread.java:619) |#] [#|2010-06-22T16:54:38.458-0700|WARNING|glassfish3.1|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=144;_ThreadName=http-thread-pool-8080(5);|StandardWrapperValve[Kaptcha]: PWC1406: Servlet.service() for servlet Kaptcha threw exception java.lang.InternalError: Can't connect to X11 window server using 'localhost:10.0' as the value of the DISPLAY variable. at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method) at sun.awt.X11GraphicsEnvironment.access$100(X11GraphicsEnvironment.java:52) at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:155) at java.security.AccessController.doPrivileged(Native Method) at sun.awt.X11GraphicsEnvironment.(X11GraphicsEnvironment.java:131) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:68) at java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1135) at com.google.code.kaptcha.text.impl.DefaultWordRenderer.renderWord(DefaultWordRenderer.java:41) at com.google.code.kaptcha.impl.DefaultKaptcha.createImage(DefaultKaptcha.java:41) at com.google.code.kaptcha.servlet.KaptchaServlet.doGet(KaptchaServlet.java:82) at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) at javax.servlet.http.HttpServlet.service(HttpServlet.java:844) at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1518) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:339) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:171) at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:651) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:591) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94) at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:87) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:158) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:321) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:222) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:802) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:705) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:986) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:178) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) at com.sun.grizzly.ContextTask.run(ContextTask.java:69) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:526) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:507) at java.lang.Thread.run(Thread.java:619)
The Root cause
If you look at the log message “Can’t connect to X11 window server using ‘localhost:10.0’ as the value of the DISPLAY variable.” This means the JRE abstract Windows toolkit is not able to initialize the graphics in this environment.
How to resolve this issue ?
To avoid this error we need to set headless JVM option to true in the server startup scripts.
-Djava.awt.headless=true
What is Headless mode?
This is extract from Sun Developer Network page
Headless mode is a system configuration in which the display device, keyboard, or mouse is lacking. Sounds unexpected, but actually you can perform different operations in this mode, even with graphic data.
Many methods in the java.awt.Toolkit and java.awt.GraphicsEnvironment classes, with the exception of fonts, imaging, and printing, require the availability of a display device, keyboard, and mouse. But some classes, such as Canvas or Panel, can be executed in headless mode. Headless mode support has been available since the J2SE 1.4 platform.
How to set Headless=true in Glassfish v31 Admin console?
This can be done from the Glassfish administration console.
- Login to Glassfish Admin console
- Go to – Configurations – Server Config – JVM Settings – JVM Options TAB – Select Add JVM Option
- Add “-Djava.awt.headless=true” in the text field.
- Hit “Save” button.
- Restart the server.
- Now the Captcha images should start working.
How to set Headless=true in Glassfish v31 command line?
This can be easily done using below asadmin commands
##Set the JVM option asadmin create-jvm-options -Djava.awt.headless=true ## Stop the server asadmin stop-domain [mydomain] ## Start the server asadmin start-domain [mydomain]
In general this error can seen on any server and the same solution should be applicable. I hope this post will save you some time on this issue, Let me know if you are facing any problem.