Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Changed formatting, fixed spelling errors, rewrote UNIX startup & JK sections

...

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.

Wiki MarkupBut 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 tomcat-user list: \[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 tomcat-user list: http://jakarta.apache.org/tomcat/faq/tomcatuser.html \] . 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?

Wiki Markup
\[wiki:Self:TomcatOnMacOS Running Tomcat on MacOS X\]

...

How do I load a properties file?

Here are 2 the two most popular ways::

1) Use a ResourceBundle. See the java 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.

2) Another way is to use the method getResourceAsStream() from the ServletContext class. This allows you update the file without having to reload the webapp as required by the first method. Typical Here is an example code snippet, without all the try catchesany error trapping:

No Format
    // Assuming you are in a Servlet extending HttpServlet 
    // This will look for a file called "/more/cowbell.properties" relative 
    // to your servlet Root Context 
    InputStream is = getServletContext().getResourceAsStream("/more/cowbell.properties"); 
    Properties  p  = new Properties(); 
    p.load(is); 
    is.close();  

...

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 for to do this myself:

No Format
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 the Connectors?

On the Tomcat FAQ there are links to , there is a list of Other Resources which should have a relevant link to your config. If not, there are the JK docs. The JK docs for 3, 4, and 5 are all virtually the same. JK2 is not quite ready for production.

Tomcat Crashed What do I do?

These steps are in no particular order ...

...

information pointing you to the relevant pages.

Each connector has its own configuration, and its own set up. Check them for more information.

In particular, here are a number of locations for Tomcat Connectors:

Wiki Markup
\[http://jakarta.apache.org/tomcat/connectors-doc/index.html Tomcat Connectors Documentation\]

Wiki Markup
\[http://jakarta.apache.org/tomcat/connectors-doc/faq.html Tomcat Connectors FAQ\]

Wiki Markup
\[http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jk2/config/apache.html Configuring Tomcat Connectors for Apache\]

...

Tomcat crashed! What do I do now?

These steps are in no particular order ...

  • 0. Read the Tomcat FAQ
  • 1. Read the Tomcat RELEASE NOTES - there is something about Linux in it
  • 2. 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.
  • 3. Patch (or unpatch!) the operating system as needed.
  • 4. Patch (or unpatch!) the JVM (Java Virtual Machine).
  • 5. Linux Problem? - read the RELEASE NOTES!
  • 6. Look at commercial vendor support for other servlet engines. Sometimes the problem is universal regardless of servlet engine and may be a JVM/OS/application code issue
  • 7. Search Google for web pages - maybe someone else had this problem. I'll bet they did.
  • 8. Search Google news groups
  • 9. If the JVM is from a commercial vendor, (eg: IBM, HP) check their release notes and news groups
  • 10. Using a database? Make sure JDBC type 4 drivers are used. Check their release notes.
  • 11. 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!
  • 12. 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 tomcat-user mailing list, whose archives you should search for more information.

Sharing sessions across containers for clustering or replication purposes is 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

First, add this to the top of your properties:

No Format

<property environment="env" />

Next find this line in the "war" target:

No Format

<classes dir="${build.dir}" includes="**/*.properties" />

Change it so it reads like this:

No Format

<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:

No Format
  
class FooWrapper { 
    static {

...

How do I share sessions across webapps?

You cannot share sessions directly across webapps, 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 tomcat-user mailing list, whose archives you should search for more information.

Sharing sessions across contains for clustering or replication is a different matter altogether.

Why doesn't the netbeans example build for me?

I have found 2 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:

No Format
  
class FooWrapper { 
    static { 
        System.loadLibrary("foo"); 
    } 

    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 -

No Format
    java.lang.UnsatisfiedLinkError: Native Library WEB-INF/lib/libfoo.so already loaded in another classloader 
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1525) 

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:

No Format

MyPrincipal p = request.getUserPrincipal();
String emailAddress = p.getEmailAddress();

Here are 4 ways you might get around the classloader boundary:

1) Reflection

No Format

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.

3) Common Interfaces

Rather than move the implementing custom classes up, you could define interfaces for your customs classes, and put the interfaces in the common directory. You're code would look like this:

System.loadLibrary("foo"); 
    } 

    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 -

No Format
    java.lang.UnsatisfiedLinkError: Native Library WEB-INF/lib/libfoo.so already loaded in another classloader 
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1525) 

...

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:

No Format

MyPrincipal p = request.getUserPrincipal();
String emailAddress = p.getEmailAddress();

Here are 4 ways you might get around the classloader boundary:

1) Reflection

No Format

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.

3) Common Interfaces

Rather than move the implementing custom classes up, you could define interfaces for your customs classes, and put the interfaces in the common directory. You're code would look like this:

No Format

public interface MyPrincipalInterface extends java.security.Principal {
  public String getEmailAddress();
}

public class MyPrincipal implements MyPrincipalInterface {
...
  public String getEmailAddress() {
    return emailAddress;
No Format

public interface MyPrincipalInterface extends java.security.Principal {
  public String getEmailAddress();
}

public class MyPrincipal implements MyPrincipalInterface {
...
  public String getEmailAddress() {
    return emailAddress;
  }
}

public class MyServlet implements Servlet {
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    MyPrincipalInterface p = (MyPrincipalInterface)request.getUserPrincipal();
    String emailAddress = p.getEmailAddress();
...
}

...

http://marc.theaimsgroup.com/?l=tomcat-user&m=106453566416102&w=2

and this:

http://marc.theaimsgroup.com/?l=tomcat-user&m=106621232531781&w=2

and thisPlus, "what SSL is all about anyway":

http://marc.theaimsgroup.com/?l=tomcat-user&m=106621232531781106692394104667&w=2

Plus, "what SSL is all about anyway":

http://marc.theaimsgroup.com/?l=tomcat-user&m=106692394104667&w=2

If you're looking for a certicate provider, check here: http://www.sslreview.com/

How do I install Tomcat as a service under Unix

...

2

If you're looking for a certicate provider, check here: http://www.sslreview.com/

...

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.

System V::In a typical UNIX System V setup, there is a directory containing startup scripts, and other directories which contain links to these startup scripts. Create the appropriate startup script for your setup, then create the appropriate links.

For more information on each, check your system documentation.

...

...

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 direclty directly into othe tomcat 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 tomcat and not a a Tomcat extension and is therefore non-standard.

No Format
Server server = ServerFactory.getServer();
//Note, this assumes the Container is "Catalina"
Service service = server.findService("Catalina");
Engine engine = (Engine) service.getContainer();
Host host = (Host) engine.findChild(engine.getDefaultHost());
//Note, this assumes your context is "myContext"
Context context = (Context) host.findChild("myContext");
Realm realm = context.getRealm();

...

  • Open a Bugzilla enhancement item with the explanation of your enhancements, and attach a diff -u format of your patch. We will evaluate and commit your patch as needed. Note that the Tomcat web site is updated with every release, so that documentation changes will not be visible as soon as you submit your Bugzilla item.

...

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:

No Format
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <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:

...