You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Apache Wiki <wi...@apache.org> on 2010/02/26 15:32:06 UTC

[Tomcat Wiki] Update of "HowTo" by DanielBerg

Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Tomcat Wiki" for change notification.

The "HowTo" page has been changed by DanielBerg.
http://wiki.apache.org/tomcat/HowTo?action=diff&rev1=84&rev2=85

--------------------------------------------------

  '''Originally taken from: http://wiki.apache.org/jakarta-tomcat/Tomcat/Howto  '''
+ 
  ----
- '''Contents'''
- <<TableOfContents>>
+ '''Contents''' <<TableOfContents>>
+ 
  ----
  
  == How do I add a question to this page? ==
- 
  Anyone may edit this page to add their own content. That is why this page is part of a Wiki and not a hardcoded static file in the FAQ.
  
  However, ''do not'' add questions without answers to this page. If you have a question about how to do something in Tomcat which has not been addressed yet, ask the [[http://jakarta.apache.org/tomcat/faq/tomcatuser.html|tomcat-user list]]. Once you've figured out how to fix your problem, come back and update the Wiki to allow the rest of us to benefit from what you've learned!
  
- 
  == How do I set up and run Tomcat on Macintosh OS X? ==
- 
  See [[TomcatOnMacOS]]
+ 
+ == How do I set up and run Tomcat on Solaris 10? ==
+ See TomcatOnSolaris10
  
  == How do I set up multiple sites sharing the same war application/war file? ==
  See CreateVirtualHosts
@@ -24, +25 @@

  See AntDeploy
  
  == How do I load a properties file? ==
- 
  Here are the two most popular ways::
  
   * Use a `ResourceBundle`. See the Java docs for the specifics of how the `ResourceBundle` class works. Using this method, the properties file must go into the `WEB-INF/classes` directory or in a jar file contained in the `WEB-INF/lib` directory.
@@ -40, +40 @@

  p.load(is);
  is.close();
  }}}
- 
- 
  == How do I log requests ? ==
  See AccessLogValve
  
  == Can I set Java system properties differently for each webapp? ==
- 
  No.  If you can edit Tomcat's startup scripts, you can add "-D" options to Java.  But there is no way to add such properties in web.xml or the webapp's context.
  
  == How do I use log4j for all Tomcat log output? ==
- 
  To have Tomcat use log4j universally, place both `log4j.jar` and the Jakarta `commons-logging.jar` into the `$TOMCAT_HOME/common/lib` directory.  Create your log4j properties file as `$TOMCAT_HOME/common/classes/log4j.properties` and configure the root logger.  Here is the basic `log4j.properties` that I used to do this myself:
+ 
  {{{
  log4j.rootLogger=info, R
  log4j.appender.R=org.apache.log4j.ConsoleAppender
  log4j.appender.R.layout=org.apache.log4j.PatternLayout
  log4j.appender.R.layout.ConversionPattern=%-5p %-30.30c{1} %x - %m%n
  }}}
- 
  If you only need to use log4j in your own web app, just include log4j (and any log4j properties file) in your WAR file.
  
- 
- 
  == How do I configure Tomcat Connectors? ==
- 
  On the Tomcat FAQ, there is a list of Other Resources which should have information pointing you to the relevant pages.
  
  Each connector has its own configuration, and its own set up.  Check them for more information.
@@ -75, +68 @@

   * [[http://jakarta.apache.org/tomcat/connectors-doc/faq.html|Tomcat Connectors FAQ]]
   * [[http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jk2/config/apache.html|Configuring Tomcat Connectors for Apache]]
  
- The following '''excellent''' article was written by Mladen Turk. He is a Developer and Consultant for JBoss Inc in Europe, where he is responsible for native integration. He is a long time commiter for Jakarta Tomcat Connectors, Apache Httpd and Apache Portable Runtime projects. 
+ The following '''excellent''' article was written by Mladen Turk. He is a Developer and Consultant for JBoss Inc in Europe, where he is responsible for native integration. He is a long time commiter for Jakarta Tomcat Connectors, Apache Httpd and Apache Portable Runtime projects.
  
-     ''Fronting Tomcat with Apache or IIS - Best Practices''
+  . ''Fronting Tomcat with Apache or IIS - Best Practices''
-     * http://people.apache.org/~mturk/docs/article/ftwai.html 
+  * http://people.apache.org/~mturk/docs/article/ftwai.html
  
  John Turner has an excellent page about [[http://johnturner.com/howto/apache-tomcat-howto.html|Using Apache HTTP with Apache Tomcat]].  Several different connectors have been built, and some connector projects have been abandoned (so beware of old documentation).
  
  == How do I configure Tomcat to work with IIS and NTLM? ==
- 
  See [[TomcatNTLM]]
  
  == Tomcat crashed! What do I do now? ==
- 
  These steps are in no particular order ...
  
-  1.#0 Read the Tomcat FAQ
+  1. Read the Tomcat FAQ
   1. Read the Tomcat RELEASE NOTES - there is something about Linux in it
   1. First look at the stack traces. I hope a stack trace was produced before the failure aborted the JVM process. After you get a few stack traces, see if a pattern appears. Trace back to source code if needed.
   1. Patch (or ''unpatch''!) the operating system as needed.
@@ -104, +95 @@

   1. Tweak JVM memory parameters. Setting memory too high can be as bad as having memory too low. If your memory settings are set too high, Java 1.3 JVMs may freeze while waiting for the entire garbage collection to finish. Also if the JVM has too much memory, if may be starving other resources on the machine which are needed which may be causing unforeseen exceptions. In a nutshell, throwing more memory doesn't always solve the problem!
   1. Turn off the Java JIT compiler. See the Java Docs on how to do this.
  
- 
- 
  == How do I share sessions across web apps? ==
+ You cannot share sessions directly across web apps, as that would be a violation of the Servlet Specification.  There are workarounds, including using a singleton class loaded from the common classloader repository to hold shared information, or putting some of this shared information in a database or another data store.  Some of these approaches have been discussed on the [[http://jakarta.apache.org/tomcat/faq/tomcatuser.html|tomcat-user mailing list]], whose archives you should search for more information.
  
- You cannot share sessions directly across web apps, as that would
- be a violation of the Servlet Specification.  There are workarounds,
- including using a singleton class loaded from the common classloader
- repository to hold shared information, or putting some of this shared
- information in a database or another data store.  Some of these approaches have been discussed on the [[http://jakarta.apache.org/tomcat/faq/tomcatuser.html|tomcat-user mailing list]], whose archives you should search for more information.
- 
- Sharing sessions across containers for clustering or replication purposes is
+ Sharing sessions across containers for clustering or replication purposes is a different matter altogether.
- a different matter altogether.
- 
  
  == Why doesn't the NetBeans example build for me? ==
+ I have found two issues with the build.xml provided here: http://jakarta.apache.org/struts/faqs/netbeans.html
- 
- I have found two issues with the build.xml provided here:
- http://jakarta.apache.org/struts/faqs/netbeans.html
  
  First, add this to the top of your properties:
  
  {{{
  <property environment="env" />
  }}}
- 
  Next find this line in the "war" target:
  
  {{{
  <classes dir="${build.dir}" includes="**/*.properties" />
  }}}
- 
  Change it so it reads like this:
  
  {{{
  <classes dir="${src.dir}" includes="**/*.properties" />
  }}}
- 
  Now it will work!
  
- 
  == I'm encountering classloader problems when using JNI under Tomcat ==
- 
  The important thing to know about using JNI under Tomcat is that one cannot place the native libraries OR their JNI interfaces under the WEB-INF/lib or WEB-INF/classes directories of a web application and expect to be able to reload the webapp without restarting the server. The class that calls System.loadLibrary(String) must be loaded by a classloader that is not affected by reloading the web application itself.
  
  Thus, if you have JNI code that follows the convention of including a static initilaizer like this:
@@ -159, +134 @@

      native void doFoo();
    }
  }}}
- 
  then both this class and the shared library should be placed in the `$CATALINA_HOME/shared/lib` directory.
  
  ''Note that under Windows, you'll also need to make sure that the library is in the {{{java.library.path}}}.  Either add {{{%CATALINA_HOME%\shared\lib}}} to your Windows PATH environment variable, or place the DLL files in another location that is currently on the {{{java.library.path}}}.  There may be a similar requirement for UNIX based system (I haven't checked), in which case you'd also have to add {{{$CATALINA_HOME/shared/lib}}} to the PATH environment variable.  (Note: I'm not the original author of this entry.)''
  
  The symptom of this problem that I encountered looked something like this -
+ 
  {{{
  java.lang.UnsatisfiedLinkError: Native Library WEB-INF/lib/libfoo.so already loaded in another classloader
          at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1525)
  }}}
- 
  If the `UnsatisfiedLinkError` is intermittent, it may be related to Tomcat's default session manager.  It restored previous sessions at startup.  One of those objects may load the JNI library.  Try stopping the Tomcat JVM, deleting the SESSIONS.ser file, then starting Tomcat.  You may consider changing the session persistence manager at this time.
  
+ Note that Tomcat 6.0.14 the $CATALINA_HOME/shared/lib directory does not exist. You will need to add this and you will need to edit $CATALINA_HOME/conf/catalina.properties so that the shared.loader line looks like this shared.loader=$CATALINA_HOME/shared/lib
- Note that Tomcat 6.0.14 the $CATALINA_HOME/shared/lib directory does not exist.
- You will need to add this and you will need to edit $CATALINA_HOME/conf/catalina.properties
- so that the shared.loader line looks like this shared.loader=$CATALINA_HOME/shared/lib
  
  == How can I access members of a custom Realm or Principal? ==
- 
  When you create a custom subclass of `RealmBase` or `GenericPrincipal` and attempt to use those classes in your webapp code, you'll probably have problems with `ClassCastException`.  This is because the instance returned by `request.getUserPrincipal()` is of a class loaded by the server's classloader, and you are trying to access it through you webapp's classloader.  While the classes maybe otherwise exactly the same, different (sibling) classloaders makes them different classes.
  
  This assumes you created a `MyPrincipal` class, and put in Tomcat's server/classes (or lib) directory, as well as in your webapp's webinf/classes (or lib) directory.  Normally, you would put custom realm and principal classes in the server directory because they depend on other classes there.
  
  Here's what you would like to do, but it throws `ClassCastException`:
+ 
  {{{
  MyPrincipal p = request.getUserPrincipal();
  String emailAddress = p.getEmailAddress();
  }}}
- 
  Here are 4 ways you might get around the classloader boundary:
  
  1) ''Reflection''
+ 
  {{{
  Principal p = request.getUserPrincipal();
  String emailAddress = p.getClass().getMethod("getEmailAddress", null).invoke(p, null);
  }}}
- 
  2) ''Move classes to a common classloader''
  
  You could put your custom classes in a classloader that is common to both the server and your webapp - e.g., either the "common" or bootstrap classloaders.  To do this, however, you would also need to move the classes that your custom classes depend on up to the common classloader, and that seems like a bad idea, because there a many of them and they a core server classes.
@@ -223, +194 @@

  ...
  }
  }}}
- 
  ''Notice that this method gives you pretty much the webapp code you wanted in the first place''
  
  4) ''Serializing / Deserializing''
  
- You might want to try serializing the response of 'request.getUserPrincipal()' and deserialize it to an instance of [webapp]My``Principal.
+ You might want to try serializing the response of 'request.getUserPrincipal()' and deserialize it to an instance of [webapp]MyPrincipal.
- 
- 
- 
  
  == Setting up SSL ==
- 
  Threads from the [[http://jakarta.apache.org/tomcat/faq/tomcatuser.html|tomcat-user list]]
  
- Using Veri``Sign:
+ Using VeriSign:
  
   * http://marc.theaimsgroup.com/?l=tomcat-user&m=106285452711698&w=2
   * http://marc.theaimsgroup.com/?l=tomcat-user&m=107584265122914&w=2
@@ -253, +219 @@

   * http://marc.theaimsgroup.com/?l=tomcat-user&m=106692394104667&w=2
  
  == HowTo SSL Client Authentication with Fallback to FORM Authentication ==
- 
  See [[SSLWithFORMFallback]]
  
  == How do I set up another tomcat service on Windows, sharing the same Tomcat Home ? ==
+ This script sets up a a tomcat base directory and calls tomcat5.exe to create a windows service which will use the tomcat home given for the binaries and tomcat base you create See TomcatCreateWindowsService
- This script sets up a a tomcat base directory and calls tomcat5.exe to create a windows service which will use
- the tomcat home given for the binaries and tomcat base you create
- See [[TomcatCreateWindowsService]]
  
  == How do I install Tomcat as a service under Unix? ==
- 
  Create a shell program to start Tomcat automatically.  Each UNIX varies in how it starts up automatic services, but there are two main variants:
  
  BSD::In a typical BSD system, there are a series of start up scripts in {{{/etc}}} starting with {{{rc.}}}.  Look for, or create, a file called {{{/etc/rc.local}}} and enter the appropriate instructions to start up Tomcat there as a shell script.
@@ -271, +233 @@

  
  For more information on each, check your system documentation.
  
-  (!) It also makes a lot of sense to use the JavaServiceWrapper.
+  . (!) It also makes a lot of sense to use the JavaServiceWrapper.
  
  == How do I get direct access to a Tomcat Realm? ==
- 
  Credit: This code is from a post by Yoav Shapira http://www.yoavshapira.com in the user list
  
  Sometimes access directly into the Tomcat realm object is needed; to do, this the following code can be used.  Be aware, however, that by using this, your application is relying on a Tomcat extension and is therefore non-standard.
@@ -291, +252 @@

  Context context = (Context) host.findChild("myContext");
  Realm realm = context.getRealm();
  }}}
- 
- 
  == How do I make Tomcat startup faster? ==
- See [[HowTo/FasterStartUp]]
+ See HowTo/FasterStartUp
- 
  
  == How do I contribute to Tomcat's documentation? ==
- 
  - Download the source bundle or grab the source XML file from CVS.  The docs are in the jakarta-tomcat-catalina CVS module, in the webapps/docs subdirectory.  They are in XML format and get processed into the HTML documentation as part of the Tomcat release.
  
  - Edit the documentation XML file(s) as you wish.  The xdocs format is self-explanatory: use normal HTML markup, and add <section> or <subsection> tags as you see fit.  Look at the existing docs as examples.  Make sure you use valid XML markup.
@@ -311, +268 @@

  
  - If you're not familiar with how to grab files from CVS, see http://www.apache.org/dev/contributors.html.
  
- 
  == How do I override the default home page loaded by Tomcat? ==
- 
  After successfully installing Tomcat, you usually test it by loading http://localhost:8080 . The contents of that page are compiled into the `index_jsp` servlet. The page even warns against modifying the `index.jsp` files for this reason. Luckily, it is quite easy to override that page. Inside {{{$TOMCAT_HOME/conf/web.xml}}} there is a section called `<welcome-file-list>` and it looks like this:
  
  {{{
@@ -323, +278 @@

          <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
  }}}
- 
  The default servlet attempts to load the `index.*` files in the order listed. You may easily override the `index.jsp` file by creating an index.html file at `$TOMCAT_HOME/webapps/ROOT`. It's somewhat common for that file to contain a new static home page or a redirect to a servlet's main page. A redirect would look like:
  
  {{{
@@ -338, +292 @@

  
  </html>
  }}}
- 
  This change takes effect immediately and does not require a restart of Tomcat.
  
  == How do I edit the default JSP home page loaded by Tomcat? ==
- 
  See [[EditDefaultJSPPage]]
  
  == How do I redirect System.out and System.err to my web page? ==
+ I have met a situation where I needed to redirect a portion of standard ouput (`System.out`, STDOUT) and standard error (`System.err`, STDERR) to my web page instead of a log file. An example of such an application is a compiler research platform that our resarch team is putting online for anybody to be able to quickly compile-test their programs on line. Naturally, the compilers dump some of their stuff to STDERR or STDOUT and they are not web application `.jar`. Thus, I needed badly these streams related to the compiler output to be redirected to my web editor interface. Having found no easy instructions on how to do that lead me writing up this quick HOWTO. The HOWTO is based on Servlets, but similar arrangements can be done for JSPs. The below example shows the essentials, with most non-essentials removed.
- 
- I have met a situation where I needed to redirect a portion of standard ouput (`System.out`, STDOUT)
- and standard error (`System.err`, STDERR) to my web page instead of a log file. An example of such
- an application is a compiler research platform that our resarch team is putting online for anybody
- to be able to quickly compile-test their programs on line. Naturally, the compilers dump some of their
- stuff to STDERR or STDOUT and they are not web application `.jar`. Thus, I needed badly these streams
- related to the compiler output to be redirected to my web editor interface. Having found no easy
- instructions on how to do that lead me writing up this quick HOWTO. The HOWTO is based on Servlets,
- but similar arrangements can be done for JSPs. The below example shows the essentials, with most
- non-essentials removed.
  
  {{{
  public class WebEditor
  extends HttpServlet
  {
   ...
- 	public void doGet
+         public void doGet
- 	(
+         (
- 		HttpServletRequest poHTTPRequest,
+                 HttpServletRequest poHTTPRequest,
- 		HttpServletResponse poHTTPResponse
+                 HttpServletResponse poHTTPResponse
- 	)
+         )
- 	throws IOException, ServletException
+         throws IOException, ServletException
- 	{
+         {
- 		poHTTPResponse.setContentType("text/html");
+                 poHTTPResponse.setContentType("text/html");
  
- 		ServletOutputStream out = poHTTPResponse.getOutputStream();
+                 ServletOutputStream out = poHTTPResponse.getOutputStream();
  
- 		out.println("<html>");
- 		out.println("<body>");
- 		out.println("<head>");
+                 out.println("<html>");
+                 out.println("<body>");
+                 out.println("<head>");
- 		out.println("<title>WebEditor Test $Revision: 1.6 $</title>");
+                 out.println("<title>WebEditor Test $Revision: 1.6 $</title>");
- 		out.println("</head>");
- 		out.println("<body>");
+                 out.println("</head>");
+                 out.println("<body>");
- 		out.println("<h3>WebEditor Test $Revision: 1.6 $</h3>");
+                 out.println("<h3>WebEditor Test $Revision: 1.6 $</h3>");
- 		out.println("<hr />");
+                 out.println("<hr />");
  
- 		// Backup the streams
+                 // Backup the streams
- 		PrintStream oStdOutBackup = System.out;
+                 PrintStream oStdOutBackup = System.out;
- 		PrintStream oStdErrBackup = System.err;
+                 PrintStream oStdErrBackup = System.err;
  
- 		// Redired STDOUT and STDERR to the ServletOuputStream
+                 // Redired STDOUT and STDERR to the ServletOuputStream
- 		System.setOut(new PrintStream(out));
+                 System.setOut(new PrintStream(out));
- 		System.setErr(new PrintStream(out));
+                 System.setErr(new PrintStream(out));
  
  
- 		try
- 		{
- 			// ... call compiler here that produces
- 			// tons of STDOUT/STDERR messages ...
- 		}
- 		catch(Exception e)
- 		{
- 			out.println(e.toString());
- 		}
+                 try
+                 {
+                         // ... call compiler here that produces
+                         // tons of STDOUT/STDERR messages ...
+                 }
+                 catch(Exception e)
+                 {
+                         out.println(e.toString());
+                 }
  
- 		// Restore original STDOUT and STDERR
+                 // Restore original STDOUT and STDERR
- 		System.setOut(oStdOutBackup);
+                 System.setOut(oStdOutBackup);
- 		System.setErr(oStdErrBackup);
+                 System.setErr(oStdErrBackup);
  
- 		out.println("<hr />");
- 		out.println("</body>");
- 		out.println("</html>");
- 	}
+                 out.println("<hr />");
+                 out.println("</body>");
+                 out.println("</html>");
+         }
  }
  }}}
+ A few caveats arise, as for instance while the `System.out` and `System.err` are redirected as per above, no logging of these is done to files. You will need more legwork to do to make the additional logging. It is important to backup and restore the original streams as the above example does. Also, notice the use of `getOutputStream()`: when this method is called, the `getWriter()` method can no longer be used in the same response object.
- 
- A few caveats arise, as for instance while the `System.out` and `System.err` are redirected
- as per above, no logging of these is done to files. You will need more legwork to do
- to make the additional logging. It is important to backup and restore the original
- streams as the above example does. Also, notice the use of `getOutputStream()`:
- when this method is called, the `getWriter()` method can no longer be used
- in the same response object.
  
  Corrections and comments are most welcome!
  
  == How to run Tomcat without root privileges? ==
- 
  The best way is to use jsvc, available as part of the [[http://commons.apache.org/daemon/jsvc.html|commons-daemon]] project.
  
  ----
- 
- Is there a way to allow normal user(non-root) to start/stop the tomcat server. Tried assigning permission, did not work. Read thru some articles, stated that only root has permission to port below 1025.
+ Is there a way to allow normal user(non-root) to start/stop the tomcat server. Tried assigning permission, did not work. Read thru some articles, stated that only root has permission to port below 1025. How can i allow a non-root user to do so ? thks in adv. :)
- How can i allow a non-root user to do so ? thks in adv. :)
  
- - malathi ranjit singh----
+ - malathi ranjit singh
  
+ ----
  One way is to put Apache httpd with mod_jk before your Tomcat servers, and use ports >=1024 in the Tomcat(s). Since we do it that way, it's the only way I know.
  
  BTW, you should read the 1st howto. ;)
  
- 
  Another method is to use SetUID scripts (assuming you have the capability) to do this.  Here's how I do it.
  
  Create a file called foo.c with this content (replace "/path/startupscript" with the tomcat startup script):
  
+ #include <unistd.h> #include <stdlib.h>
- #include <unistd.h>
- #include <stdlib.h>
  
- int main( int argc, char *argv[] )
+ int main( int argc, char *argv[] ) {
- {
-         if ( setuid( 0 ) != 0 ) perror( "setuid() error" );
  
+  . if ( setuid( 0 ) != 0 ) perror( "setuid() error" ); printf( "Starting ${APPLICATION}\n" ); execl( "/bin/sh", "sh", "/path/startupscript", 0 ); return 1;
+ 
- 	printf( "Starting ${APPLICATION}\n" );
- 	execl( "/bin/sh", "sh", "/path/startupscript", 0 );
- 	return 1;
  }
  
  Run the following as root (replacing tmp with whatever you want the startup script to be and replacing XXXXX with whatever group you want to be able to start and stop tomcat:
  
+ gcc tmp.c -o tmp chown root:XXXXX tmp chmod ugo-rwx tmp chmod u+rwxs,g+rx tmp
- gcc tmp.c -o tmp
- chown root:XXXXX tmp
- chmod ugo-rwx tmp
- chmod u+rwxs,g+rx tmp
  
  Now members of the tomcat group should be able to start and stop tomcat.  One caveat though, you need to ensure that that your tomcat startup script is not writable by anyone other than root, otherwise your users will be able to insert commands into the script and have them run as root (very big security hole).
- 
- 
  
  ----
  - A another way is to use Iptables to redirect Port 80 and 443 to user ports (>1024)
@@ -479, +404 @@

  
  ----
  BSD-based Unix systems such as Mac OS X use a tool similar to iptables, called ipfw (for Internet Protocol Fire Wall). This tool is similar in that it watches all network packets go by, and can apply rules to affect those packets, such as "port-forwarding" from port 80 to some other port such as Tomcat's default 8080. The syntax of the rules is different than iptables, but the same idea. For more info, google and read the man page. Here is one possible rule to do the port-forwarding:
+ 
  {{{
  sudo ipfw add 100 fwd 127.0.0.1,8080 tcp from any to any 80 in
  }}}
- 
  == How do I debug a Tomcat application? ==
- 
  There is nothing magical about debugging a Tomcat application. All you need is an IDE and two environment variables.
  
-    * If you have not already done so begin by creating a new Tomcat context for your application. Navigate to '''TOMCAT_HOME\conf\Catalina\localhost''' and create a new file, say, myapp.xml. This will become part of your url, so to access your app you'll have to type '''http://localhost:8080/myapp'''.
+  * If you have not already done so begin by creating a new Tomcat context for your application. Navigate to '''TOMCAT_HOME\conf\Catalina\localhost''' and create a new file, say, myapp.xml. This will become part of your url, so to access your app you'll have to type '''http://localhost:8080/myapp'''.
-    * Enter the following in myapp.xml:
+  * Enter the following in myapp.xml:
  
  {{{
  <Context docBase="c:/worskpace/myapp/WebRoot" path="/HelloWorld"/>
  }}}
- 
-       This assumes you have a web application containing WEB-INF in '''c:/workspace/myapp/WebRoot'''
+  . This assumes you have a web application containing WEB-INF in '''c:/workspace/myapp/WebRoot'''
+ 
-    * Create two environment variables:
+  * Create two environment variables:
  
  {{{
  C:\>set JPDA_ADDRESS=1044
  C:\>set JPDA_TRANSPORT=dt_socket
  }}}
- 
-    * Now, you can launch Tomcat with these debug options:
+  * Now, you can launch Tomcat with these debug options:
  
  {{{
  TOMCAT_HOME\bin\>catalina jpda start
  }}}
- 
-    * Use your IDE to connect to Tomcat through port 1044
+  * Use your IDE to connect to Tomcat through port 1044
  
  If Eclipse happens to be your IDE of choice, you can get more information at [[http://www.jacoozi.com/index.php?option=com_content&task=view&id=119&Itemid=134|Remote Debugging with Eclipse (Jacoozi Article)]].
  
  == How do I debug a Tomcat application when Tomcat is run as a Windows service ? ==
  You can debug the tomcat service by editing the service parameters as follows.
  
-    * Launch a command prompt
+  * Launch a command prompt
  
-    * Set the proper CATALINA_HOME environment variable : pointing to tomcat home
+  * Set the proper CATALINA_HOME environment variable : pointing to tomcat home
  
-    * Run the following command:
+  * Run the following command:
  
  {{{
  %CATALINA_HOME%\bin\tomcat6w.exe //ES//tomcat6
  }}}
- 
-    * Select the Java tab in the properties dialog box,
+  * Select the Java tab in the properties dialog box,
  
-    * Add the following two lines to the Java Options text box:
+  * Add the following two lines to the Java Options text box:
  
  {{{
  -Xdebug
  -Xrunjdwp:transport=dt_socket,address=127.0.0.1:1044,server=y,suspend=n
  }}}
- 
  If you want to allow remote debugging, replace 127.0.0.1 by your server IP address.
+ 
-    * Click on "Apply" and close the dialog by clicking on "OK"
+  * Click on "Apply" and close the dialog by clicking on "OK"
  
-    * Restart the Apache Tomcat service
+  * Restart the Apache Tomcat service
  
-    * Use your IDE to connect to Tomcat through port 1044
+  * Use your IDE to connect to Tomcat through port 1044
  
+ If Eclipse happens to be your IDE of choice, you can get more information at [[http://www.jacoozi.com/index.php?option=com_content&task=view&id=119&Itemid=134|Remote Debugging with Eclipse (Jacoozi Article)]]. For IntelliJ IDEA you choose a remote debug target and set transport to "socket" and mode to "attach" , then you specify the host (127.0.0.1) and port (1044)
- If Eclipse happens to be your IDE of choice, you can get more information at [[http://www.jacoozi.com/index.php?option=com_content&task=view&id=119&Itemid=134|Remote Debugging with Eclipse (Jacoozi Article)]].
- For IntelliJ IDEA you choose a remote debug target and set transport to "socket" and mode to "attach" , then you specify the host (127.0.0.1) and port (1044)
  
  == How do I enable Server Side Includes (SSI)? ==
- 
  two things have to be done for tomcat to aknowledge SSI scripts:
  
  1.  Rename $CATALINA_BASE/server/lib/servlets-ssi.renametojar to $CATALINA_BASE/server/lib/servlets-ssi.jar.
@@ -577, +496 @@

          <load-on-startup>4</load-on-startup>
      </servlet>
  }}}
+ additional information can be found at: http://tomcat.apache.org/tomcat-5.5-doc/ssi-howto.html
- 
- additional information can be found at:
- [[http://tomcat.apache.org/tomcat-5.5-doc/ssi-howto.html]]
- 
  
  == How do I connect to a Websphere MQ (MQ Series) server using JMS and JNDI? ==
- 
- Basically, this works just as described in 
- [[http://tomcat.apache.org/tomcat-5.5-doc/jndi-resources-howto.html]]: Within your application, you are using the standard JNDI and JMS API calls. In web.xml (the container independent application descriptor), you specify resource references (stub resources). And in context.xml (the container specific application descriptor), you are actually configuring the JMS connection.
+ Basically, this works just as described in  http://tomcat.apache.org/tomcat-5.5-doc/jndi-resources-howto.html: Within your application, you are using the standard JNDI and JMS API calls. In web.xml (the container independent application descriptor), you specify resource references (stub resources). And in context.xml (the container specific application descriptor), you are actually configuring the JMS connection.
  
  More to the point. Here's some example code, which might be added to a Servlet. The example is sending a message to an MQ server:
  
@@ -613, +527 @@

      qs.close();
      qc.close();
  }}}
- 
  Note the following:
  
  1.  I have intentionally omitted proper resource handling. For example, one ought to ensure that qc.close() is always called by using a try { .. } finally { ..} block.
@@ -637, +550 @@

              +--- geronimo-j2ee-management_1.0_spec-1.0.jar
              +--- geronimo-jms_1.1_spec-1.0.jar
  }}}
- 
  The application descriptor web.xml looks just the same as usual, with the exception of the following lines:
  
  {{{
@@ -651, +563 @@

      <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
    </resource-env-ref>
  }}}
- 
  This is simply telling, that the items "jms/MyQCF", and "jms/MyQ" exist, and are instances of QueueConnectionFactory, and Queue, respectively. The actual configuration is in context.xml:
  
  {{{
@@ -674, +585 @@

        description="JMS Queue for receiving messages from Dialog"
        QU="<myqueue>"/>
  }}}
- 
  Basically, you just have to enter your values for <myqserver> (the WebSphere MQ servers host name), <mychannel> (the channel name), <myqueuemanager> (the queue manager name), and <myqueue> (the queue name). Both these values, the associated names (HOST, PORT, CHAN, ...), and their collection is truly MQ specific. For example, with ActiveMQ, you typically have a broker URL, and a broker name, rather than HOST, PORT, CHAN, ...
  
  The main thing to know (and the reason why I am writing this, because it took me some hours to find out): How do I know the property names, their meaning, and possible values? Well, there is an excellent manual, called "WebSpere MQ Using Java". It should be easy to find by entering the title into Google. The manual contains a section, called "Administering JMS objects", which describes the objects being configured in JNDI. But the most important part is the subsection on "Properties", which contains all the required details.
  
- 
  == How do I use DataSources with Tomcat? ==
- 
  See UsingDataSources
  
  == How do I install the Administration web app? ==
- 
- If you install Tomcat 5.5 binaries, the Administration web app is not bundled with it; this describes how to add the Administration web app to your Tomcat 5.5 installation.  (Tomcat 4.1 comes with the Administration web app as part of the binary).  
+ If you install Tomcat 5.5 binaries, the Administration web app is not bundled with it; this describes how to add the Administration web app to your Tomcat 5.5 installation.  (Tomcat 4.1 comes with the Administration web app as part of the binary).
  
  The following refers to a Tomcat 5.5 set up on Windows 2000, so your path names will be different on *nix platforms.  In this example, Tomcat 5.5.17 in installed in ''c:\Program Files\Apache Software Foundation\Tomcat 5.5'' (this is my '''CATALINA_HOME''').
  
-   1. Unzip or untar (be careful to use GNU tar) the file containing the administration web app files (eg. ''apache-tomcat-5.5.17-admin.zip'') to a temporary directory, eg. ''c:\temp''.
+  1. Unzip or untar (be careful to use GNU tar) the file containing the administration web app files (eg. ''apache-tomcat-5.5.17-admin.zip'') to a temporary directory, eg. ''c:\temp''.
  
- 
-   1. Copy ''c:\temp\apache-tomcat-5.5.17\conf\Catalina\localhost\admin.xml'' to the directory ''c:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\Catalina\localhost''.
+  1. Copy ''c:\temp\apache-tomcat-5.5.17\conf\Catalina\localhost\admin.xml'' to the directory ''c:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\Catalina\localhost''.
  
-   1. Copy the entire directory tree ''c:\temp\apache-tomcat-5.5.17\server\webapps\admin''
+  1. Copy the entire directory tree ''c:\temp\apache-tomcat-5.5.17\server\webapps\admin''
+ 
  to the directory ''c:\Program Files\Apache Software Foundation\Tomcat 5.5\server\webapps''.  This is an overlay, so \server\webapps is just pointing you to the \server\webapps, and the admin directory with its contents will be the only thing you see added there.
  
-   1. Add a line to your ''c:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\tomcat-users.xml'' file so that you have a user who has '''admin''' role.  For example, add this line   just before the last line (containing '''</tomcat-users>''') of the file:
+  1. Add a line to your ''c:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\tomcat-users.xml'' file so that you have a user who has '''admin''' role.  For example, add this line   just before the last line (containing '''</tomcat-users>''') of the file:
- 
-     <user username="admin" password="makesomethingup" roles="admin,manager"/>
+   . <user username="admin" password="makesomethingup" roles="admin,manager"/>
  
-   1. Restart Tomcat.
+  1. Restart Tomcat.
  
-   1. Now when you visit ''http://localhost:8080/admin'' you should see a page that asks for a user name and password.  If you still see the "no longer loaded" error message in your browser, you must either force a full reload of the web page (in Firefox, hold down Shift key while clicking on the Reload button) or just restart your browser completely.
+  1. Now when you visit ''http://localhost:8080/admin'' you should see a page that asks for a user name and password.  If you still see the "no longer loaded" error message in your browser, you must either force a full reload of the web page (in Firefox, hold down Shift key while clicking on the Reload button) or just restart your browser completely.
  
  == How do I add JARs or classes to the common classloader without adding them to $CATALINA_HOME/common/lib? ==
  Edit the file ''catalina.properties'' under $CATALINA_BASE/conf; there is a property called ''common.loader'' to which you can add additional paths to find JARs or classes for the common classloader.
  
- 
  == How do I get Tomcat to start when it says it can't find the file 'setclasspath.sh'? ==
- 
  If Tomcat was working fine the first few times after installation but suddenly refuses to start up and gives the following error message:
  
  {{{
@@ -719, +623 @@

  Cannot find /path/to/tomcat/bin/setclasspath.sh
  This file is needed to run this program
  }}}
- 
- Then all you need to do is to include the complete paths for the BASEDIR and CATALINA_HOME variables in the files setclasspath.sh and catalina.sh respectively.  
+ Then all you need to do is to include the complete paths for the BASEDIR and CATALINA_HOME variables in the files setclasspath.sh and catalina.sh respectively.
  
  This should be done even if CATALINA_HOME has been defined and exported previously on the command line and/or in /etc/profile as well.  Moreover, this error message persists even though the file setclasspath.sh is present in Tomcat's bin directory.
  
@@ -728, +631 @@

  $ echo "BASEDIR=/path/to/tomcat" >> setclasspath.sh
  $ echo "CATALINA_HOME=/path/to/tomcat" >> catalina.sh
  }}}
- 
  == How do I authenticate Manager access via JNDI to Active Directory for multiple Tomcat instances? ==
- 
  ADS insists that the CN of every group be unique, but the Manager app. always uses the group CN=manager.  The default can be changed, but it's hard to find and you have to do it over every time you upgrade.  Instead, pick an attribute other than the common name -- for example, "description" -- that doesn't have to be unique, name it as the `RoleName` attribute of the `Realm` (in server.xml, which you'll be editing anyway), and set that  attribute to "manager" in each group you create.  Create an OU for each Tomcat instance's groups and give that OU's DN as the `RoleBase` in that instance's server.xml.  Create a uniquely-named group in each instance's OU with the chosen attribute ("description" for example) set to "manager".
  
- 
  == How do I check whether Tomcat is UP or DOWN? There is no status command ==
- 
- Unfortunately, the `org.apache.catalina.util.ServerInfo` class does not determine if Tomcat is UP or DOWN. It is possible to do an HTTP GET on the root url but this is not accurate. In my case I sometimes use a regular Apache HTTPd to display a maintainence message while upgrading, etc. and using that method would give false positives. 
+ Unfortunately, the `org.apache.catalina.util.ServerInfo` class does not determine if Tomcat is UP or DOWN. It is possible to do an HTTP GET on the root url but this is not accurate. In my case I sometimes use a regular Apache HTTPd to display a maintainence message while upgrading, etc. and using that method would give false positives.
  
  The correct way to do determine status is to parse the admin port from server.xml and see if we can connect to it. If we can then the Tomcat is UP otherwise it is DOWN.
  
  Here is my code to do this. Consider it public domain and use it as you see fit. Tomcat makes a note of this connection with something like this on the console.
+ 
  {{{
  May 1, 2007 5:10:35 PM org.apache.catalina.core.StandardServer await
  WARNING: StandardServer.await: Invalid command '' received
  }}}
- Ideally this should be incorporated into `org.apache.catalina.util.ServerInfo` by some committer. In addition to the shutdown command they should add commands like status (UP or DOWN) and uptime in the await method of `org.apache.catalina.core.StandardServer` 
+ Ideally this should be incorporated into `org.apache.catalina.util.ServerInfo` by some committer. In addition to the shutdown command they should add commands like status (UP or DOWN) and uptime in the await method of `org.apache.catalina.core.StandardServer`
  
  {{{
- 
  import java.io.File;
  import java.io.IOException;
  import java.io.OutputStream;
@@ -891, +790 @@

      }
    }
  }
- 
  }}}
- 
  == Where and how do I set memory related settings to improve Tomcat performance? ==
- When your web application is using large memory as this memory size default setting can be too small, 64MB by default,thus the application becomes slower because the garbage collector is invoked more often, and it can even run out of memory (outofmemory / heap space error ).
- One way to address this problem is to set a larger heap size . In Windows system, this can be done by editing / adding JAVA_OPTS variable (should be early in the file) in CATALINA_HOME/bin/catalina.bat or catalina.sh for Linux/Unix systems.Parameters to be added are , let say you want to increase it to 256 MB (as you required but make sure you have enough amount of physical memory/RAM and for 32bit system , use no more than 1-1.1 GB heap space size ) , use '-Xms256m -Xmx256m' .In some cases , it is better to set slightly lower size for -Xms . There are other parameters can be added , some of them :{{{'-XX:MaxNewSize -XX:NewSize -XX:MaxPermSize'}}} , depending on your application and requirements .
+ When your web application is using large memory as this memory size default setting can be too small, 64MB by default,thus the application becomes slower because the garbage collector is invoked more often, and it can even run out of memory (outofmemory / heap space error ). One way to address this problem is to set a larger heap size . In Windows system, this can be done by editing / adding JAVA_OPTS variable (should be early in the file) in CATALINA_HOME/bin/catalina.bat or catalina.sh for Linux/Unix systems.Parameters to be added are , let say you want to increase it to 256 MB (as you required but make sure you have enough amount of physical memory/RAM and for 32bit system , use no more than 1-1.1 GB heap space size ) , use '-Xms256m -Xmx256m' .In some cases , it is better to set slightly lower size for -Xms . There are other parameters can be added , some of them :{{{'-XX:MaxNewSize -XX:NewSize -XX:MaxPermSize'}}} , depending on your application and requirements .
  
- For catalina.bat there now should be a line in the file that looks like this: 
+ For catalina.bat there now should be a line in the file that looks like this:  {{{ set JAVA_OPTS=-Xms256m -Xmx256m }}}
- {{{ set JAVA_OPTS=-Xms256m -Xmx256m }}}
  
- For catalina.sh: 
- {{{ JAVA_OPTS='-Xms256m -Xmx256m' }}}
+ For catalina.sh:  {{{ JAVA_OPTS='-Xms256m -Xmx256m' }}}
  
+ For other parameters , go to * http://wiki.apache.org/tomcat/FAQ/Memory * http://wiki.apache.org/tomcat/OutOfMemory
+ 
- For other parameters , go to
- * http://wiki.apache.org/tomcat/FAQ/Memory
- * http://wiki.apache.org/tomcat/OutOfMemory
-  
  and Google and Yahoo are your friends.
  
  == How do I make my web application be the Tomcat default application ? ==
- 
- Congratulations.  You have created and tested a first web application (traditionally called "mywebapp"), users can access it via the URL "http://myhost.company.com/mywebapp".  You are very proud and satisfied.  
+ Congratulations.  You have created and tested a first web application (traditionally called "mywebapp"), users can access it via the URL "http://myhost.company.com/mywebapp".  You are very proud and satisfied.   But now, how do you change the setup, so that "mywebapp" gets called when the user enters the URL "http://myhost.company.com" ?
- But now, how do you change the setup, so that "mywebapp" gets called when the user enters the URL "http://myhost.company.com" ?
  
+ The pages and code of your "mywebapp" application currently reside in (CATALINA_BASE)/webapps/mywebapp/. In a standard Tomcat installation, you will notice that under the same directory (CATALINA_BASE)/webapps/, there is a directory called ROOT (the capitals are important, even under Windows).  That is the residence of the ''current'' Tomcat default application, the one that is called right now when a user calls up "http://myhost.company.com[:port]". The trick is to put your application in it's place.
- The pages and code of your "mywebapp" application currently reside in (CATALINA_BASE)/webapps/mywebapp/.
- In a standard Tomcat installation, you will notice that under the same directory (CATALINA_BASE)/webapps/, there is a directory called ROOT (the capitals are important, even under Windows).  That is the residence of the ''current'' Tomcat default application, the one that is called right now when a user calls up "http://myhost.company.com[:port]".
- The trick is to put your application in it's place.
  
- First stop Tomcat.<<BR>>
- Then before you replace the current default application, it may be a good idea to make a copy of it somewhere else.<<BR>>
- Then delete everything under the ROOT directory, and move everything that was previously under the (CATALINA_BASE)/webapps/mywebapp/ directory, toward this (CATALINA_BASE)/webapps/ROOT directory. In other words, what was previously .../mywebapp/WEB-INF should now be .../ROOT/WEB-INF (and not .../ROOT/mywebapp/WEB-INF).
+ First stop Tomcat.<<BR>> Then before you replace the current default application, it may be a good idea to make a copy of it somewhere else.<<BR>> Then delete everything under the ROOT directory, and move everything that was previously under the (CATALINA_BASE)/webapps/mywebapp/ directory, toward this (CATALINA_BASE)/webapps/ROOT directory. In other words, what was previously .../mywebapp/WEB-INF should now be .../ROOT/WEB-INF (and not .../ROOT/mywebapp/WEB-INF).
  
  Just by doing this, you have already made you webapp into the Tomcat ''default webapp''.
  
@@ -938, +824 @@

          <url-pattern>/*</url-pattern>
      </servlet-mapping>
  }}}
+ Restart Tomcat and you're done.<<BR>> Call up "http://myhost.company.com/" and enjoy.
- 
- Restart Tomcat and you're done.<<BR>>
- Call up "http://myhost.company.com/" and enjoy.
  
  '''Addendum 1 : If you are deploying your application as a war file..'''
  
+ The above instructions relate to the situation where you are "manually" deploying your application as a directory-and-files structure under the /webapps directory.  If instead you are using the "war" method to deploy your application, the principle is about the same :<<BR>> - delete the ROOT directory<<BR>> - name your war file "ROOT.war" (capitals mandatory)<<BR>> - drop the ROOT.war file directly in the /webapps directory.<<BR>> Tomcat will automatically deploy it.
- The above instructions relate to the situation where you are "manually" deploying your application as a directory-and-files structure under the /webapps directory.  If instead you are using the "war" method to deploy your application, the principle is about the same :<<BR>>
- - delete the ROOT directory<<BR>>
- - name your war file "ROOT.war" (capitals mandatory)<<BR>>
- - drop the ROOT.war file directly in the /webapps directory.<<BR>>
- Tomcat will automatically deploy it.
  
+ For more information about this topic in general, consult this page :  [[http://tomcat.apache.org/tomcat-6.0-doc/config/context.html|The Context Container]]
- For more information about this topic in general, consult this page : 
- [[http://tomcat.apache.org/tomcat-6.0-doc/config/context.html|The Context Container]]
  
  '''Addendum 2 : If for some reason you want another method..'''
  
- If, for some reason, you do not want to deploy your application under the CATALINA_BASE/webapps/ROOT subdirectory, or you do not want to name your war-file "ROOT.war", then read on.  But you should first read this :
+ If, for some reason, you do not want to deploy your application under the CATALINA_BASE/webapps/ROOT subdirectory, or you do not want to name your war-file "ROOT.war", then read on.  But you should first read this : [[http://tomcat.apache.org/tomcat-6.0-doc/config/context.html|The Context Container]] and make sure you understand the implications.
- [[http://tomcat.apache.org/tomcat-6.0-doc/config/context.html|The Context Container]]
- and make sure you understand the implications.
  
  The method described above is the simple method.  The two methods below are more complex, and the second one has definite implications on the way you manage and run your Tomcat.
  
  '''Method 2.1'''
  
- - Place your war file outside of CATALINA_BASE/webapps (it '''must''' be outside to prevent double deployment).<<BR>>
- - Place a context file named ROOT.xml in CATALINA_BASE/conf/<engine name>/<host name>.  The single <Context> element in this context file MUST have a '''docBase''' attribute pointing to the location of your war file. The path element should not be set - it is derived from the name of the .xml file, in this case ROOT.xml. See the Context Container above for details.
+ - Place your war file outside of CATALINA_BASE/webapps (it '''must''' be outside to prevent double deployment).<<BR>> - Place a context file named ROOT.xml in CATALINA_BASE/conf/<engine name>/<host name>.  The single <Context> element in this context file MUST have a '''docBase''' attribute pointing to the location of your war file. The path element should not be set - it is derived from the name of the .xml file, in this case ROOT.xml. See the Context Container above for details.
  
  '''Method 2.2'''
  
  If you really know what you are doing..
  
+ - leave your war file in CATALINA_BASE/webapps, under its original name<<BR>> - turn off autoDeploy '''and''' deployOnStartup in your Host element in the server.xml file.<<BR>> - explicitly define '''all''' application Contexts in server.xml, specifying both path and docBase. You must do this, because you have disabled all the Tomcat auto-deploy mechanisms, and Tomcat will not deploy your applications anymore unless it finds their Context in the server.xml.
- - leave your war file in CATALINA_BASE/webapps, under its original name<<BR>>
- - turn off autoDeploy '''and''' deployOnStartup in your Host element in the server.xml file.<<BR>>
- - explicitly define '''all''' application Contexts in server.xml, specifying both path and docBase. You must
- do this, because you have disabled all the Tomcat auto-deploy mechanisms, and Tomcat will not deploy your applications anymore unless it finds their Context in the server.xml. 
  
  Note that this last method also implies that in order to make any change to any application, you will have to stop and restart Tomcat.
  
  == How do I obtain a thread dump of my running webapp ? ==
- 
  You can only get a thread dump of the entire JVM, not just your webapp. This shouldn't be a big deal, but should be made clear: you are getting a dump of all JVM threads, not just those "for your application", whatever that means.
  
  Getting a thread dump depends a lot on your environment. Please choose the section below that matches your environment best. The more universal and convenient options are presented first, while the more difficult ones or those for specific setups are provided later. Generally, you should start at the top of the list and work your way down until you find a technique that works for you.
  
  === If you are running Sun JDK 1.6 or higher ===
- 
  Sun's JDK (not the JRE) ships with a program called ''jstack'' (or ''jstack.exe'' on Microsoft Windows) which will give you a thread dump on standard output. Pipe the output into a file and you have your thread dump. You will need the process id ("pid") of the process to dump. Use of the program ''jps'' (''jps.exe'' on Microsoft Windows) can help you determine the pid of a specific Java process.
  
  === If you are on *NIX running Sun JDK ===
- 
  Sun provides ''jstack'' on *nix systems from version 1.4 onward. See the above tip if you have such an environnment.
  
  === If you are running on *NIX ===
- 
  Send a SIGQUIT to the process. The thread dump will be sent to stdout which is likely to be redirected to CATALINA_BASE/logs/catalina.out.
  
  To send a SIGQUIT, use ''kill -3 <pid>'' from the command line.
  
  === If you are running Tomcat as a service on Microsoft Windows ===
- 
  Edit your service to add the "//MS//" option to the command line. This enabled the "Monitor Service" which puts an icon in the system tray while Tomcat is running. Right-clicking the Tomcat monitor in the system tray allows you to produce a thread dump in stdout.
  
  === If you have Tomcat running in a console ===
- 
- *NIX: Press CRTL-\
- Microsoft Windows: press CRTL-BREAK
+ *NIX: Press CRTL-\ Microsoft Windows: press CRTL-BREAK
  
  This will produce a thread dump on standard output, but may not be possible to capture to a file.
  

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org