Tomcat Part I


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 tag for that web application.
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:
/WEB-INF/classes
Create the folder, restart tomcat, all should be well.
6) How do I make Tomcat 3.1 invoke my servlets via the url /servlets/ instead of /servlet/ that it's doing now?
Change the url-pattern of the default servlet invoker located in the "deployment descriptor" for your web application. This file us usually located in /WEB-INF/web.xml file. Replace:
/servlet/*
with:
/servets/*
Also note that in Tomcat 3.1, web applications begin with the default "deployment descriptor" located in /conf/web.xml. You can change the "default" for all web applications there.
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 directive to indicate to Apache that your specific servlet URL or servlet URL prefix (for multiple servlets) can be accessed only by authenticated users. The following template should be added to one of the Apache configuration files (such as http.conf) with appropriate substitutions for your system:

AuthName "your realm"
AuthType Basic
AuthUserFile /your/user/file
require valid-user

This directive tells Apache to restrict access to the specified URL, so don't use the filesystem path to your servlet. Use the servlet's URL.
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. 4. debug="0" reloadable="true" >
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( "" +
" TestServlet " +
"Hello there from TestServlet ----- " +
"Revision number: 18" +
"" );
}
}
11) What is Tomcat?
Tomcat is the code name for the flagship product of the Jakarta Project . It is a commercial-quality, open-source implementation of the Java Servlet 2.2 and JavaServer Pages 1.1 Specifications that runs either standalone or integrated with a web server. It is also the official Reference Implementation for those specifications (sanctified by Sun).
12) With regard to automatic servlet reloading in Tomcat 3.1, what happens if one servlet makes references to other servlets in the same webapp? Will automatic reloading get enabled for all such servlets?
The short answer to the question is: No.
Let's say that a webapp for which automatic reload has been enabled consists of a group of mutually referencing servlets. Let's also say that you have modified and recompiled all the servlets. When you hit the reload button on the browser, only one servlet -- the servlet that the browser is pointing to -- will be automatically reloaded by the container. Hitting the reload button on the browser for the other servlets will not cause their reload into the container and you will only see their older versions. If you want the newer versions of the other servlets to be reloaded into the container, in general you'd need to shutdown and restart the servlet container.
This behavior of Tomcat 3.1 is in keeping with the following statement that appears in Tomcat 3.1 release notes:
"...... changes to classes other than the servlet you are requesting do not trigger class reloads -- you will need to restart Tomcat to reflect changes in those classes."
In the rest of this posting, I will explain this property of Tomcat 3.1 with the help an example. The reader is also referred to a posting by Costin Manolache on this aspect of automatic class reloading in Tomcat 3.1.
To demonstrate this behavior of Tomcat 3.1, I have constructed the following example that consists of two simple mutually referencing servlets called TestServlet_1 and TestServlet_2. In my Tomcat 3.1 container, both these servlets are in a webapp called test-suite and reside 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:

Let's say that after starting the servlet container, you point your browser to the following URL:
http://localhost:8080/test-suite/servlet/TestServlet_1
the servlet container will load TestServlet_1 into the container, which will cause the browser to display a "Hello..." message. If you click inside this message where indicated, the browser will make a request for TestServlet_2 and it will be loaded into the container.
Now suppose you make changes to both the servlets by altering, say, the value of "Revision number: ". If your browser is pointing to TestServlet_1 and you hit reload button, the servlet container will automatically reload TestServlet_1. But the container will NOT reload TestServlet_2 even if you hit the reload button on the browser when the browser is pointing to TestServlet_2.
To see the newer version of TestServlet_2, you have two choices: 1) Recompile the classes and this time start out by pointing your browser to TestServlet_2. Or, 2) Shutdown and restart the servlet container.
Here is the code for the two servlets:

////////// file: TestServlet_1.java //////////

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;


public class TestServlet_1 extends HttpServlet {

public void init() throws ServletException
{
System.out.println("TestServlet_1 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( "" +
" TestServlet_1 " +
"Hello there from TestServlet_1 ------- " +
"To see the hello message from TestServlet_2," +
" click here ------ " +
"Revision number: 17" +
"" );
}
}



////////// file: TestServlet_2.java //////////

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;


public class TestServlet_2 extends HttpServlet {

public void init() throws ServletException
{
System.out.println("TestServlet_2 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( "" +
" TestServlet_2 " +
"TestServlet_2 saying hello ------- " +
"To see the hello message from TestServlet_1," +
" click here ------ " +
"Revision number: 17" +
"" );
}
}

13) Is there any way to tell Tomcat (or any servlet engine) never to use cookies for session management?
I'm not sure about Tomcat but in WebLogic (from 4.0.2 to 5.1 versions) there is parameter in the weblogic.properties file which can enable (or disable) cookies.
The parameter line is:
weblogic.httpd.session.cookies.enable=true
or
weblogic.httpd.session.cookies.enable=false
14) Is it possible to use a TagLib without defining a web app using Tomcat? [I'm using .jsp without webapps and everything's ok, but I can't make it work with taglibs]
When using taglibs with an application you specify the location of a tag library in the web.xml file, web.xml resides in TOMCAT_ROOT/webapps/APPNAME/WEB-INF. The taglib entries in web.xml look like:


blahblah


/WEB-INF/jsp/BlahBlah.tld


There is another web.xml which seems to be a global one: TOMCAT_ROOT/conf/web.xml Simply place the above XML there, the last entry in my conf/web.xml was a "welcome-file-list" entry, the taglib xml can be placed after that. I don't know where the .tld file should be placed, maybe under TOMCAT_ROOT/webapps/ROOT/WEB-INF/jsp ?
15) Does Tomcat support EJB?
No, Tomcat does not support EJB. It is a Servlet/JSP container, not an EJB container.
The Jakarta Project provides an implementation of the Servlets API called Tomcat, and an implementation of JavaServer Pages called Jasper. These are bundled together in the Tomcat release.
However, the J2EE Reference Implementation, which supports EJB, is bundled with an old version of Tomcat. This adds Tomcat's support for Servlets and JSP to the J2EE product.
16) How do I deploy a WAR file in Tomcat?
Currently (as of version 3.2) the procedure for deploying a new WAR file is:
1. Stop Tomcat.
2. Delete existing deployment. If you have previously deployed "foo.war" in TOMCAT_HOME/webapps, then it has been unpacked into webapps/foo/... You must delete this directory and all its contents. On Unix, this can be done with
rm -r $TOMCAT_HOME/webapps/foo
3. Copy WAR file to TOMCAT_HOME/webapps/.
4. Start Tomcat.
This process may become easier in the future. A "deploy tool" is on the Tomcat "to-do" list.
Note that if you deploy a WAR file in this manner, you do not need to make any changes to server.xml -- it will automatically be recognized and activated. However, if you wish to specify non-default options for this webapp, you may do so by adding an element like
to server.xml.
17) What is the difference between JServ and Tomcat? And what's up with mod_jserv and mod_jk?
JServ was one of the very first servlet engines. It is now an open source project, consisting of two parts: a pure-java servlet engine, compliant with the Servlet spec version 2.0, and an Apache module written in C called mod_jserv that allows Apache to send servlet requests to the JServ JVM.
Tomcat is a completely separate product, originally written by Sun, that is now also open-source and administered by Apache. It supports the Servlet spec version 2.2, and the JSP spec version 1.1. It also contains a pure Java servlet engine, and a number of connectors for several commercial web servers.
Here's the confusing part: originally, when it was time to write a connector from Apache to Tomcat, they started with the code base of mod_jserv. Although it has been rewritten and revised to the point where it is no longer compatible with the mod_jserv that comes with JServ, unfortunately, it is still called mod_jserv. This means that if you have the JServ mod_jserv installed, it will not work with Tomcat, and vice versa.
Fortunately, the latest version of Tomcat comes with a new connector for Apache, called mod_jk. This connector supports Tomcat but not JServ. It is also more advanced, in that it supports Tomcat-style load balancing, and also supports SSL authentication (though this latter functionality is still a bit rough and may have bugs in actually *reporting* that the connection is secure).
So if you just use mod_jk and Tomcat, you should have no problems (at least as far as this connector issue is concerned).
18) I am runing Tomcat on Apache for NT. When I put a \ after the the jsp page, e.g. "http://www.myserver.com/includes/top_nav.jsp\", it shows the code, i.e. the java embedded in the HTML. How do I resolve this issue?
This is a bug. AFAIK it has been fixed in the latest version (3.2) of Tomcat.
19) Why do I get a "java.net.BindException:Address in use" error?
Probably because the address is in use :-)
You're already running an instance of your servlet engine, or another service is running on its port. Make sure the other service is fully stopped before launching another one.
29) What are the contents of WEB-INF?
The contents of the WEB-INF directory are:
 /WEB-INF/web.xml deployment descriptor
 /WEB-INF/classes/* directory for servlet and utility classes. The classes in this directory are used by the application class loader to load classes from.
 /WEB-INF/lib/*.jar area for Java ARchive files which contain servlets, beans, and other utility classes useful to the web application. All such archive files are used by the web application class loader to load classes from.

Sample Web Application Directory Structure


Illustrated here is a listing of all the files in a sample web application:
/index.html
/howto.jsp
/feedback.jsp
/images/banner.gif
/images/jumping.gif
/WEB-INF/web.xml
/WEB-INF/lib/jspbean.jar
/WEB-INF/classes/com/mycorp/servlets/MyServlet.class
/WEB-INF/classes/com/mycorp/util/MyUtils.class
30) What is a WAR file and how do I create one?
A WAR (or "web archive") file is simply a packaged webapp directory. It is created using the standard Java jar tool. For example:
cd /home/alex/webapps/mywebapp
jar cf ../mywebapp.war *
31) How are initialization parameters passed to a servlet under Servlet API version 2.2?
Through the webapp deployment descriptor, which is the web.xml file in the directory WEB-INF.
Note that there are two different types of web.xml files in Tomcat 3.x: There is a web.xml that sits in the top-level configuration directory TOMCAT_HOME/conf and then there can be a separate web.xml for each webapp in the directory WEB-INF for that webapp. You would want to keep webapp specific deployment information, such as initialization parameters and their values, in the web.xml specific to that webapp.
The best on-line example that illustrates servlet initialization through a webapp's deployment descriptor is, I believe, the ServletParam servlet in the test webapp in your Tomcat software package. This servlet can be called with two different canonical names, as for example in
http://localhost:8080/test/servlet/servletParam1
and
http://localhost:8080/test/servlet/servletParam2
The deployment descriptor maps the canonical names servletParam1 and servletParam2 to the actual servlet ServletParam but with different values of the initialization parameters. When the servlet ServletParam is called with the name servletParam1, the initialization parameter-value pairs are
param1 value1
param2 value2
and when the same servlet is called with the name servletParam2, the parameter-value pairs are
param3 value3
param4 value4
The following constitutes a sufficient deployment descriptor for this example:









servletParam1


ServletParam


param1
value1


param2
value2





servletParam2


ServletParam


param3
value3


param4
value5000




The first half of the web.xml file associates the servlet ServletParam with the name servletParam1 and then goes on to declare its parameter-value pairs. The second half does the same for the name servletParam2.
32) Is it possible to bind Tomcat to one specific IP address on a multi-homed host (for virtual hosting)?
Yes, from version 3.1 you can a virtual host bind to one of the ip adresses owned by the machine, if you add something like the following to server.xml:

docBase="webapps/examples" />
docBase="webapps/ROOT" />


as you can see you can put a IP adress for the Virtual Host name, ergo you can have a Virtual Host pointed to any particular IP configured in your machine.
33) Can I use the latest version of Tomcat inside Sun's J2EE implementation?
The J2EE reference implementation ships with Tomcat. The classes for Tomcat are located inside the \lib\j2ee.jar. If you wanted to use the latest version of Tomcat you would have to replace the classes in this archive.
This would of course not be supported.
34) What are the advantages/disadvantages of using Tomcat's built-in HTTP server instead of, say, Apache?
Regarding Tomcat's disadvantages when used as a stand-alone server, here is a list reproduced from the Tomcat-Apache HOWTO page:
1. Tomcat is not as fast as Apache when it comes to static pages.
2. Tomcat is not as configurable as Apache.
3. Tomcat is not as robust as Apache.
4. There are many sites with long time investment in certain web servers, for example, sites that are using CGI scripts/Server API modules/perl/php. We cannot assume that all of them will want to ditch this legacy.
The page further says that " For all these reasons it is recommended that real world sites use an industrial strength web server, such as Apache, for serving the static content of the site, and use Tomcat as a Servlet/JSP add-on."
The main thing that Tomcat has going for it is that it the official reference implementation of the Java Servlet 2.2 and JavaServer Pages 1.1 technologies developed under the Apache license by some of the best developers around the world.
35) What is an invoker servlet in a Tomcat servlet container?
The "invoker servlet" is a system-supplied servlet that extracts the name of the requested servlet class from the portion of the URL that comes after "/servlet". The invoker servlet then loads the requested servlet into the container and executes it.
If you look at the contents of the webapp deployment descriptor file, web.xml, in the TOMCAT_HOME/conf directory, you will find the following servlet element at the beginning:



invoker


org.apache.tomcat.servlets.InvokerServlet



which declares the name and the place of the system-supplied invoker servlet. Shortly thereafter appears the following servlet-mapping element:



invoker


/servlet/*



which tells the container that all requests that begin with "/servlet" (relative to root of the webapp specified by the name that comes before "/servlet") are to be sent to the invoker servlet.
1) When I recompile a servlet which is already loaded by the container, it is automatically reloaded. However the destroy() method of the servlet does not get called. Does this mean that the servlet is not unloaded before reloading?
The observation you make does not apply to the version of Tomcat 3.1 that is currently available for download from the Jakarta-Tomcat site. However, it does apply to Tomcat 3.2 beta 4. More on 3.2 later in this posting. First, I'd like to say a few words about what I am basing my 3.1 answer on.
The test servlet for which I show code below has both an init() method and a destroy() method. When the init() method is invoked, it prints out the following message in the Tomcat window:

TestServlet being loaded into the container

and when the destroy() method is invoked, it prints out the following message in the Tomcat window:

TestServlet about to be unloaded

Note that the init() method will only be invoked when the servlet class is loaded into the container and its instance created. The destroy() method will only be invoked just prior to the container unloading the servlet.
If I carry out the following steps in the sequence indicated:
1. request the servlet through a client browser
2. recompile the servlet
3. hit the reload button on the browser
I get the following sequence of messages in the Tomcat window:

TestServlet being loaded into the container

TestServlet about to be unloaded

RELOAD!!!

TestServlet being loaded into the container

This shows the servlet is actually unloaded and its destroy() method invoked before the new version of the servlet is automatically loaded in.
Here is the code for the servlet:

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( "" +
" TestServlet " +
"Hello there from TestServlet" +
"" );
out.close();
}


public void destroy()
{
System.out.println( "TestServlet about to be unloaded" );
}
}

Therefore, with regard to automatic loading and unloading, Tomcat 3.1 works as specified in the Servlet 2.1 API. However, the beta 4 version of Tomcat 3.2 seems to have a bug in it. When you do exactly the same thing as described above in Tomcat 3.2, the destroy() method is not invoked, meaning that the old copy of the servlet does not get unloaded.

2) I've setup Tomcat 3.1 with Apache on my web server to serve JSP pages. It works well for Java Servlets and JSP pages. However, this is one issue: if the target JSP page does not exist, the server will send out a File Not Found Error 404 along with the DETAIL PATH, such as "File /usr/local/jakarta-tomcat/webapps/... Not found". How can I stop tomcat from spilling off its own detail file path on the server.
If you look the code of the Tomcat's JSPServlet.java, you will find the following code in the service method:
try{
//look for the jsp file
} catch (FileNotFoundException ex) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
Constants.getString("jsp.error.file.not.found", new Object[] { ex.getMessage() }));
As you can see that the FileNotFoundException directly works with the response object and the message is taken from the messages.properties files to send it directly to the caller (browser). Also I did not find any other mechanism in the Tomcat's configuration to suppress the error messages. So it will not be possible to suppress this message.
39) How is SingleThreadModel implemented in Tomcat? In other containers? [I would assume that Tomcat uses its connection thread pool, and creates a new instance of the servlet for each connection thread, instead of sharing one instance among all threads. Is that true?]
The question mixes together two rather independent aspects of a servlet container: "concurrency control" and "thread pooling".
Concurrency control, such as achieved by having a servlet implement the SingleThreadModel interface, addresses the issue of thread safety. A servlet will be thread-safe or thread-unsafe regardless of whether the servlet container used a thread pool. Thread pooling merely eliminates the overhead associated with the creation and destruction of threads as a servlet container tries to respond to multiple requests received simultaneously. It is for this reason that the specification document for Servlet 2.2 API is silent on the subject of thread pooling -- as it is merely an implementation detail. However, the document does indeed address the issue of thread safety and how and when to use SingleThreadModel servlets.
Section 3.3.3.1 of the Servlet 2.2 API Specification document says that if a servlet implements the SingleThreadModel it is guaranteed "that only one request thread at time will be allowed in the service method." It says further that "a servlet container may satisfy this guarantee by serializing requests on a servlet or by maintaining a pool of servlet instances."
Obviously, for superior performance you'd want the servlet container to create multiple instances of a SingleThreadModel type servlet should there be many requests received in quick succession. Whether or not a servlet container does that depends completely on the implementation. My experiments show that Tomcat 3.1 does indeed create multiple instances of a SingleThreadModel servlet, but only for the first batch of requests received concurrently. For subsequent batches of concurrent requests, it seems to use only one of those instances.
40) Which servlet containers have persistent session support? Specifically, does Tomcat 3.1?

All servlet containers that implement the Servlet 2.2 API must provide for session tracking through either the use of cookies or through URL rewriting. All Tomcat servlet containers support session tracking.
41) How do I write to a log file using JSP under Tomcat? Can I make use of the log() method for this?

Yes, you can use the Servlet API's log method in Tomcat from within JSPs or servlets. These messages are stored in the server's log directory in a file called servlet.log.
42) When Using Tomcat 3.1 with Apache, how do you set up your context and web server index so that a .jsp file is set as the index file?
In Apache, first map the desired jsp filename to the directory index. For example:
In srm.conf [or httpd.conf]:
DirectoryIndex index.jsp
Then in your webapp's web.xml or in your server's web.xml, look at the bottom for the tag. You can add tags to this tag, such as:


desired-index.jsp


43) Can I include two jsp:plugin actions on one JSP page? It does not compile under Tomcat
Yes. Just include an extra set of {}'s around the plugin code:

<% { %>
type="applet"
code="Clock2.class"
codebase="/examples/jsp/plugin/applet"
jreversion="1.2"
width="160"
height="150" >

Plugin tag not supported.


<% } %>
<% { %>
type="applet"
code="Clock2.class"
codebase="/examples/jsp/plugin/applet"
jreversion="1.2"
width="160"
height="150" >

Plugin tag not supported.


<% } %>
44) How do you enable BASIC authentication using Tomcat?
[Question continues: I'm able to get the dialog box requesting the username and password to pop up, however, even though I insert one of the usernames and passwords from the tomcat-users.xml file, I always get an "Authorization failed. Retry?" dialog.]
Make sure that the user has been designated a role in the tomcat-users.xml that matches the role(s) defined in the auth-constraint section of the web.xml:

web.xml:

role1



tomcat-users.xml:



45) How do I set up virtual hosting on Tomcat in standalone mode?
In Tomcat 3.2b6, it is very easy to setup virtual hosts in standalone mode. First, be sure to set the correct port for the HTTP listener (the default is 8080, and you'll probably want to change it to 80). Second, wrap your servlet context definitions (in your server.xml) with a tag, specifying the domain name to work on. Here is an exerpt from a server.xml that is configured for virtual hosting:







46) How do I set up virtual hosting on Tomcat with Apache?
You can configure your Apache server's virtual hosts to map to virtual hosts in a single Tomcat instance. Each virtual host would exist as a separate servlet context.
[For mod_jk instructions, see the user's guide. For mod_jserv...]
First configure Apache with mod_jserv, mapping the appropriate hostnames to Tomcat. Here is a sample from httpd.conf:
ApJServManual on
ApJServSecretKey DISABLED
ApJServMountCopy on
ApJServLogLevel notice

ApJServDefaultProtocol ajpv12
ApJServDefaultPort 8007
ApJServDefaultHost localhost

AddType text/jsp .jsp
AddHandler jserv-servlet .jsp

NameVirtualHost 192.168.0.2


DocumentRoot /var/www/server1
ServerName server1.lokitech.com
ApJServMount /servlet /ROOT

Order allow,deny
Deny from all




DocumentRoot /var/www/server2
ServerName server2.lokitech.com
ApJServMount /servlet /ROOT

Order allow,deny
Deny from all


Second, configure Tomcat for virtual hosts. In your server.xml, you will wrap each servlet context in a . Here is a sample from server.xml:






47) How do you do servlet aliasing with Apache and Tomcat?
Servlet aliasing is a two part process with Apache and Tomcat. First, you must map the request in Apache to Tomcat with the ApJServMount directive, e.g.,
ApJServMount /myservlet /ROOT
Second, you must map that url pattern to a servlet name and then to a servlet class in your web.xml configuration file. Here is a sample exerpt:

myservlet
com.mypackage.MyServlet


myservlet
/myservlet


No comments: