1) How can I debug my servlet?
Hoo boy, that's a tough one.
First off, you should always do your own exception handling. An uncaught exception can silently kill your servlet, and if you don't know where to look in the log files, or if your server has a bug in it whereby it silently swallows certain exceptions, you'll have no idea where the trouble is.
The following code sets up a catch block that will trap any exception, and print its value to standard error output and to the ServletOutputStream so that the exception shows up on the browser (rather than being swallowed by the log file). Chances are that any error is in your code; the exception shows you what line the problem happened at. (If you see "Compiled Code" instead of line numbers in the exception stack trace, then turn off the JIT in your server.)
res.setContentType("text/html");
ServletOutputStream out = res.getOutputStream();
try {
// do your thing here
...
}
catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
out.println("
");
out.print(sw.toString());
out.println("
");
}
Lately, I've started catching all Throwables, just in case. I know this is bad form but what are you gonna do?
Next, you should make liberal use of the log() method, and you should keep your own log files. Again, don't trust the server to do the right thing. Also, printing the log after every request can help debugging because you can immediately see the output of your servlet without going into the server-side log files. (Another problem this avoids is that some servlet engines forget to flush their logs after each request, so even if you go to the server, you won't see the most recent log messages.)
Here's some source code you can add to any HttpServlet that keeps an in-memory log:
StringBuffer logBuffer = new StringBuffer();
public void log(String s) {
s = new Date().toString() + ": " + s;
System.err.println(s);
logBuffer.append(s);
logBuffer.append("\n");
super.log(s);
}
And here's some code that you can add to the end of your doGet or doPost method that prints out the entire log after each request:
out.println("
\n
Error log this session:
\n");
out.println(logBuffer.toString());
out.println("
");
Both of these should be disabled once you actually ship your servlet, but they can be very useful during development and debugging.
You should remember to use servletrunner (renamed "JSDK WebServer" with the JSDK version 2 -- run with the script startserver) to debug your servlet. It's a tool that ships with the JSDK that basically starts up a miniature web server that runs your servlet inside itself. It means you don't have to stop and restart your real web server every time you recompile your servlet. It also affords a more pure environment, so you can make sure your servlet truly conforms to the spec before you try to run it inside a (possibly buggy or nonstandard) servlet engine. (Note that Tomcat does not have a replacement for servletrunner :-(.)
A few IDEs support servlet debugging. Symantec Cafe claims to have a fairly robust system for doing visual source-level debugging of servlets (as well as RMI, CORBA, and EJB objects).
2) Can I use Tomcat or JavaWebServer as a service on Windows NT or Windows 2000?
For Tomcat:
Download jk_nt_service.exe and follow the instructions in the document "NT-Service-howto.html" (on the Jakarta Web site and included in the Tomcat distros). Also see the minimalistic users guide, included with the Tomcat distribution.
For JWS:
Near the end of the installation program you will be asked if you want to have the Java Web Server start automatically on system reboot. (That is, whether you want to install the Java Web Server as an NT Service).
If you click Yes: An entry will be added to the Control Panels -> Services and the JavaWebServer NT Service will be started up automatically every time you restart your system.
If you click No: No entry will be made in the Control Panel's Services panel.
If you change your mind later, the product documentation provides instructions for how to setup the web server to start automatically. For instructions, see the file:
[server_root]\doc\en\administration\server_start_Win.html
3) While I am still making changes to a servlet code, how can I make a servlet reload every time I test it?
It depends on the web server you are using to test your servlet. For instance, with Tomcat, you would replace the WAR file and the server notices the change and loads the new servlet on the next request, without having to restart the server.
[Short answer: for Tomcat, add reloadable="true" to the
Note that there is a bug in Tomcat where replacing the WAR file doesn't work; you also have to delete the unpacked directory under TOMCAT/webapps/foo (for TOMCAT/webapps/foo.war).
If you are not using WAR file deployment, simply replacing the servlet classfile should work, as long as the class file is stored in webapp/WEB-INF/classes, or replacing the JAR file in webapp/WEB-INF/lib/foo.jar.
4) Is there any method to unload a servlet from Web Server memory without restarting the server?
There is no standard method/mechanism to unload a servlet from memory. Some servers, like JWS, provide the means to load and unload servlets from their administration module. Others, like Tomcat, require you to just replace the WAR file.
5) I've just set up Tomcat 3.1, created a context, and when I try and run a sample JSP page, I get: Error: 500, Internal Servlet Error: java.lang.NullPointerException
You probably forgot to create a classes folder located at:
Create the folder, restart tomcat, all should be well.
6) How do I make Tomcat 3.1 invoke my servlets via the url
Change the url-pattern of the default servlet invoker located in the "deployment descriptor" for your web application. This file us usually located in
/servlet/*
with:
/servets/*
Also note that in Tomcat 3.1, web applications begin with the default "deployment descriptor" located in
7) Why doesn't Tomcat shut down when I run shutdown.bat (or shutdown.sh)?
One possibility is that if you disabled the Apj12 connector in your server.xml you have also disabled the mechanism by which Tomcat shutdown is executed -- try putting that back in if you've commented it out
8) Where do I find web.xml and server.xml configuration files?
Note that Tomcat uses the default web.xml file, located in TOMCAT_HOME/conf/web.xml, as the base for all contexts; individual webapps can override specific settings in a custom WEB-INF/web.xml file.
For server.xml, look in the Tomcat distribution, in the directory you unzipped, under /doc/uguide/tomcat_ug.html -- scroll down to the "Tomcat's Configuration Files" section.
9) How do I set init parameters in the servlet engine?
It depends on the servlet engine. Each has its own type of config file in which you can set the names and values of init parameters; these get passed to the servlets (or JSPs) via the getInitParameter() call.
For Tomcat and JSWDK, edit the conf/web.xml file.
1) Is Tomcat robust enough for production use?
IMHO yes.
We are presently running Tomcat (servlet & jsp requests) with Apache (graphics, perl, html) on 9 Solaris/Sparc servers servicing over 10 million servlet/jsp transactions per day.
2) Is there a problem with calling Response.sendRedirect() after Response.addCookie() ?
Yes, there is a bug in Tomcat 3.1 (and possibly other servlet engines). To send a cookie through a redirect, you must set the headers manually.
Cookie long_term = new Cookie(LONG_TERM_COOKIE_NAME, user_name);
long_term.setMaxAge(60*60*24*4);
long_term.setPath("/Blah");
response.addCookie(long_term);
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
response.setHeader("Location",REDIRECT_PAGE);
3) What version of the Servlets or JSP specification is supported by my favorite servlet product? (JSDK, JSWDK, Tomcat, J2EE, etc.)
Product Product Version Servlet spec JSP spec
Tomcat 3.1 2.2 1.1
Tomcat 3.0 2.2 1.1
Sun J2EE Reference Implementation beta 2.2 ?
Sun JSWDK 1.0.1 2.1 1.0.1
Sun JSDK 2.1 2.1 none
Sun JSDK 2.0 2.0 none
Allaire JRun 3.0 2.2 1.1
Sun Java Web Server 2.0 2.1 -
Sun Java Web Server 1.1 2.0 -
Sun/Netscape iPlanet Web Server 4.1 2.2 ?
4) Where should I place my beans and servlets under Tomcat?
Where you place the beans and servlets depends on which "application" it belongs to. Assuming that you are running your JSP pages under the default "examples" application, you should place your servlets under the path
/tomcat/examples/WEB-INF/classes
Your beans should be placed under
/tomcat/examples/WEB-INF/jsp/beans
Both these paths are placed within CLASSPATH by Tomcat's startup script file.
5) Can I configure Tomcat so that the name of the webapp is not used in the URL? E.g. http://localhost/servlet/HelloWorld, instead of http://localhost/examples/servlet/HelloWorld.
You can ... but I'm not sure I'd do this on a live system!
The path you give a context must be unique within the server.xml document. Therefore, all you need to do is change the path of the ROOT webapp (to "/root" for example) and change the path of your webapp to an empty string as below.
6) Can I use Tomcat under Windows 98? Is there anything I have to watch out for during configuration?
Tomcat works very well with win95/win98. Generally there is just one problem, in that, calling startup.bat or tomcat.bat results in very strange outputs. This is related to a space characters problem within the .bat file due to difference in file formats under win95 and winNT.
For all these problems, my standard solution was to copy the file with an editor like MS Word and save to another bat file. If you starts changing bat file yourself, its very confusing.
7) Can I use Basic HTTP Authentication using Apache+JServ?
I recently did this with Apache and Tomcat. Using Basic HTTP Authentication is an Apache function, so this method should work with Apache and any servlet engine. Different web servers will, of course, work differently.
If you haven't already done so, read the Apache FAQ about authentication (section G) at apache.org, especially QA G.2. Also read the Apache Week article referenced there (http://www.apacheweek.com/issues/96-10-18#userauth). These resources will give you a good idea about how Apache can be configured to restrict access to URL's. Neither one explicitly tells you how to use authentication with servlets, so I'll spell it out here.
Use the
AuthName "your realm"
AuthType Basic
AuthUserFile /your/user/file
require valid-user
This
You will also need to create a user file with htpasswd.
8) With regard to version 3.1 of Tomcat, what specifically must be done to enable automatic reloading of servlets?
Automatic reloading of servlets by a servlet container comes in handy during the development phase when you are frequently modifying and recompiling the servlets. Having to constantly shutdown and restart the servlet container each time you modify a servlet class can become tiring very quickly.
Automatic reloading of servlets in Tomcat 3.1 is predicated upon two entries in two different files in the directory TOMCAT_HOME/conf:
1. In the file TOMCAT_HOME/conf/server.xml, you must set the reloadable attribute to true in the context element pertaining to your webapp. For example, I have a webapp named form-processing. So I added the following entry to the file TOMCAT_HOME/conf/server.xml:
2.
3.
5.
6.
7. The file TOMCAT_HOME/conf/tomcat.properties allows you to specify a classpath that is passed on to the JVM. The servlets that you want automatically reloaded must not be in this classpath. Note that this classpath is in addition to the classpath specified in the startup file tomcat.bat in the directory TOMCAT_HOME/bin. For the simple webapp form-processing that I mentioned above, I do not need to specify any additional classpaths in the TOMCAT_HOME/conf/tomcat.properties file.
For those just getting into Tomcat 3.1, I should add the caveat mentioned in the Tomcat readme file that the automatic reload feature in Tomcat 3.1 is not recommended for production applications. At this time, it is an experimental feature that when enabled creates extra overhead in processing servlet requests.
9) I had Tomcat installed on c:\tc\jakarta-tomcat, but need to run .jsp stored on d:\abc\test. How can I accomplish this?
Unless you are using a "J2EE web application" there is no simple way to do this. I would suggest creating a new web application and registering it with tomcat.
A web application is essentially a standardised directory structure containing all of the resources for your application. Using this standardised approach means that you can migrate your application to another JSP 1.1/Servlet 2.2 compatible server in the future very easily.
The examples directory under your tomcat webapps directory (c:\tc\jakarta-tomcat\webapps) is a good example of how to setup a webapp, and the important points to note are the WEB-INF directory and its web.xml file.
Once you've setup your web application, you can register it with tomcat by opening up the server.xml file from the "conf" directory under your tomcat installation. Again, take a look at how the example application is registered and use the same mechanism for registering your new webapp. All you need to do is specify the "docBase" attribute as a fully qualified path.
10) If I enable automatic servlet reloading for a webapp, will the init() method of the servlet get executed for each automatic reload?
Yes.
This question is important because it is possible to misconstrue the community literature dealing with servlets and believe that the init() method of a servlet will get executed only once -- the first time a servlet gets loaded into the container.
The following simple servlet, called TestServlet, can be used to verify the answer to the question. In my Tomcat 3.1 container, this servlet is inside a webapp called test-suite and resides in the directory
TOMCAT_HOME/webapps/test-suite/WEB-INF/classes
In accordance with the jGuru FAQ posting, I have enabled automatic reloading for this webapp by including the following element in the server.xml file in the TOMCAT_HOME/conf directory:
As the following code shows, the servlet contains a line "Revision number: xx" where xx can be edited to create a change in the servlet to trigger automatic reload. Upon each reload, the print statement in the init() method will be printed out in the Tomcat console window. Here is the code for this servlet:
//filename: TestServlet.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class TestServlet extends HttpServlet {
public void init() throws ServletException
{
System.out.println("TestServlet being loaded into the container");
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType( "text/html" );
PrintWriter out = response.getWriter();
out.println( "" +
"
"Hello there from TestServlet ----- " +
"Revision number: 18" +
"