linux中servlet画图问题的解决[September 23, 2004]
前几天,我们的程序员在tomcat中写一个用servlet作图的程序,完成后,在浏览器中运行的时候,出现了错误。以下是错误信息及其解决过程:
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
org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:825)
org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:758)
org.apache.jsp.Imaging_005fToWeb_jsp._jspService(Imaging_005fToWeb_jsp.java:106)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
root cause
java.lang.NoClassDefFoundError
java.lang.Class.forName0(Native Method)
java.lang.Class.forName(Class.java:140)
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:62)
java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1041)
java.awt.image.BufferedImage.getGraphics(BufferedImage.java:1031)
org.apache.jsp.Imaging_005fToWeb_jsp._jspService(Imaging_005fToWeb_jsp.java:79)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
note The full stack trace of the root cause is available in the
Apache Tomcat/5.0.28 logs.
--------------------------------------------------------------------------------
Apache Tomcat/5.0.28
----------Question Index -------------
I am writing an application that runs as a server process and it
needs
to read, write and process images, but there's no need to display
them,
but I find that when I run my application on Solaris or Linux it
needs
an Xserver. What's the problem and what can I do about it?
A The problem is in the implementation of the AWT toolkit. When
its nitialized it expects to find an Xserver, regardless of whether
its needed for actual display.
Although many image operations using the 1.4 Image I/O APIS
(javax.imageio), the JAI optional package, or the non-standard
com.sun.jpeg.codec classes might not have any obvious need for
display, they often invoke code that needs an AWT toolkit resource.
For example, calling getGraphics on a BufferedImage initializes AWT
and causes the problem seen by developers.
There's no way to say that a particular API does or doesn't have
this problem; it depends on what particular operations are being
invoked, and might also depend on what the application does with
the images that isn't strictly related to any of the APIs cited
above.
There are two possible solutions. For releases prior to 1.4 you
can provide a "pseudo X-server" to emulate a display environment
One of these X-server emulators is Xvfb, available for download at
www.x.org.
The preferred solution for release 1.4 and later is to use the
new headless AWToolkit.This new feature allows you to use the
J2SE API in a server-side Java application without requiring you to
have a GUI environment.
To specify the headless environment when using Sun Microsystem's
reference implementation, run your application with this
property:
-Djava.awt.headless=true
If your application isn't a client application, meaning that it
doesn't involve user interaction, then this mode of operation
should probably always be used.
Xvfb does still have one possible use in 1.4: A
server application does display to an Xserver, but requires no user
interaction. The headless toolkit won't support this situation, but
xvfb will. This is a completely hypothetical scenario and it is not
clear if any real world application exhibits such a behaviour.
Headless Support
The bugtraq report that corresponds to this change
is: 4281163.
Many environments, such as mainframe machines and dedicated
servers, do not support a display, keyboard, or mouse. Headless
support is enabled by the new GraphicsEnvironment methods isHeadless and isHeadlessInstance.
These methods indicate whether a display, keyboard, and mouse can
be supported in a graphics environment.
The API changes for headless include:
A new public exception class, java.awt.HeadlessException, is introduced. It is derived from
UnsupportedOperationException, which derives from RuntimeException,
so that existing implementations of methods that throw the new
exception will not require signature changes.
Two new methods, are added to java.awt.GraphicsEnvironment.
public static boolean isHeadless()
The constructors of Applet and all heavyweight components (*)
are changed to throw HeadlessException if a display, keyboard, and
mouse are not supported by the toolkit implementation. All javadoc
tags on all constructors are changed to reflect this
RuntimeException.
The Robot constructor throws an AWTException if a display,
keyboard, and mouse are not supported by the toolkit
implementation.
Many of the methods in Toolkit and GraphicsEnvironment, with the
exception of fonts, imaging, and printing, are changed to throw
HeadlessException if a display, keyboard, and mouse are not
supported. All the javadoc tags on these methods are changed to
reflect this RuntimeException.
Other methods that may be affected by lack of display, keyboard,
or mouse support, are changed to throw HeadlessException.
It should be worth noting that the HeadlessException is thrown
if and only if isHeadless returns true, and that all javadoc
comments should specify this.
(*)Applet, Button, Checkbox, Choice, FileDialog, Label, List,
Menu, MenuBar, MenuComponent, MenuItem, PopupMenu, Scrollbar,
ScrollPane, TextArea, TextComponent, Frame, Window, Dialog,
JApplet, JFrame, JWindow, JDialog, and TextField. Canvas and Panel
do not need to throw this exception since these can be given empty
peers and treated as lightweights.
To run our environment with a headless implementation, the
follow property may be specified at the java command
line:
-Djava.awt.headless=true
Source code should check for headless, so that the exception may
be caught gracefully. For example, see the following pre-headless
implementation of the class Foo:
class Foo {
static Choice c = new Choice(); // could throw
HeadlessException
}
The new and improved implementation of Foo should be placed in a
static block:
class Foo {
static Choice c;
static {
try {
c = new Choice();
catch (HeadlessException e) {
...
}
}
}
但-Djava.awt.headless=true到底该如何配置呢?经过不懈努力,终于解决了。在tomcat的启动的脚本中加入如下橙色字的部分,用这个脚本启动tomcat就可以了:
elif [ "$1" = "start" ] ; then
shift
touch "$CATALINA_BASE"/logs/catalina.out
if [ "$1" = "-security" ] ; then
echo "Using Security Manager"
shift
"$_RUNJAVA" $JAVA_OPTS $CATALINA_OPTS
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath
"$CLASSPATH"
-Djava.security.manager
-Djava.security.policy=="$CATALINA_BASE"/conf/catalina.policy
-Dcatalina.base="$CATALINA_BASE"
-Dcatalina.home="$CATALINA_HOME"
-Djava.io.tmpdir="$CATALINA_TMPDIR"
-Djava.awt.headless=true
org.apache.catalina.startup.Bootstrap "$@" start
>> "$CATALINA_BASE"/logs/catalina.out
2>&1 &
if [ ! -z "$CATALINA_PID" ]; then
echo $! > $CATALINA_PID
fi
else
"$_RUNJAVA" $JAVA_OPTS $CATALINA_OPTS
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath
"$CLASSPATH"
-Dcatalina.base="$CATALINA_BASE"
-Dcatalina.home="$CATALINA_HOME"
-Djava.io.tmpdir="$CATALINA_TMPDIR"
-Djava.awt.headless=true
org.apache.catalina.startup.Bootstrap "$@" start
>> "$CATALINA_BASE"/logs/catalina.out
2>&1 &
if [ ! -z "$CATALINA_PID" ]; then
echo $! > $CATALINA_PID
fi
fi
编辑完成后,重新启动tomcat,然后再运行画图程序,That's OK!
经过测试,在weblogic中也可以采用类似的方法,然后画图的时候也不需要Xserver。具体的做法就是在weblogic的启动脚本startWebLogic.sh的最后部分中加入“-Djava.awt.headless=true”。如下橙色字体所示(只摘抄部分):
....
${JAVA_HOME}/bin/java
${JAVA_VM}
${MEM_ARGS}
${JAVA_OPTIONS}
-Dweblogic.Name=${SERVER_NAME}
-Dweblogic.ProductionModeEnabled=${PRODUCTION_MODE}
-Djava.security.policy="${WL_HOME}/server/lib/weblogic.policy"
-Djava.awt.headless=true weblogic.Server
然后重新启动weblogic server即可。^_^