Developing with Tomcat and Eclipse: the Definitive Guide
I'm a big fan of Jetty's clean APIs and I use it both for development and production depending on a project, but since I'm sick and tired of people bashing Tomcat just because they haven't used it or use it wrong, I put this guide together for developing webapps (but obviously mostly Tapestry) in Eclipse with Tomcat.
Here's the toolset that you should be using: Eclipse 3.6, Sysdeo's Tomcat Plugin and Tomcat 7.x ( + M2Eclipse 0.1.x depending on whether you are using Maven or not). Eclipse WTP's generic container support is dog slow and error prone, just don't use it. There are other Tomcat plugins for Eclipse but Sysdeo's plugin is the most comprehensive one. Generic tools that try to support more than one container or technology tend to copy files around for easier deployment but avoid all of that - it slows things down and is completely unnecessary given the right set of tools.
It's assumed you have Java, Eclipse and m2eclipse installed. Below we use one of Tynamo's sample modules as an example but you could use any other web application as well. If you are otherwise starting pretty much from scratch, follow these steps to set everything up:
- Download Tomcat 7 and install to a location of choice
- Download Sysdeo Eclipse Tomcat Launcher. Unzip, copy the com.sysdeo.. folder to your /eclipse/plugins/ folder
- Restart Eclipse, verify you see the Tomcat control buttons in Eclipse toolbar
- svn checkout http://svn.codehaus.org/tynamo/trunk/tynamo-examples/recipe/ tynamo-recipe
- Import... / Existing Maven Projects, navigate to tynamo-recipe folder
- Configure Tomcat Launcher:
- In Window / Preferences / Tomcat, set Tomcat version to 6.x (even for 7.x) and set the home folder. Set Context declaration mode to context files
- In Tomcat / JVM Settings, add Jar/Zip item and point to tomcat-juli.jar found in your TOMCAT_HOME/bin folder (this is only needed for 7.x)
- In Tomcat / JVM parameters, add parameters as appropriate. I typically use at least: -Dtapestry.production-mode=false and -XX:MaxPermSize=256m
- In Tomcat / Tomcat Manager App, set manager app url and manager admin username and password correctly. Set manager app url to .../manager/text (for Tomcat 7.x - the default /manager/ is correct for previous versions)
- Install devloader for Tomcat (for Tomcat 7.x use this devloader I modified. The one from Sysdeo's isn't yet updated to handle 7.x. Unzip and copy the org folder and its contents to TOMCAT_HOME/lib
- In project properties (choose project, ALT+ENTER) configure Java build path
- For src/main/resources folder, set the output to the same as the source folder (i.e. src/main/resources, Eclipse doesn't have a separate checkbox for "don't copy")
- For default output folder, set the output to something else, such as /target/eclipse-classes than the Maven default (/target/classes) so you can use both Eclipse and Maven from command line without them stepping on each other
- In project properties / Tomcat
- Check "Is a Tomcat Project"
- Context name as you like, I often use just /ROOT for simplicity
- "Subdirectory to set as web application root", set "src/main/webapp"
- On "DevLoader ClassPath" tab, check activate DevLoader. Configure as appropriate, but typically "Check All" libraries, find servlet-api and uncheck it (obviously the container contains those classes and wants to load from there rather than as part of the web application). Also uncheck all of jre libs and "MAVEN2_CLASSPATH_CONTAINER" at the bottom, and for the simple webapp, you also need to uncheck the jetty-libs, particularly the servlet api included by Jetty.
- Enjoy live class reloading and your optimized development cycle
One of the most frustrating aspects with Sysdeo's launcher is the need to manually maintain the webapp classpath. When you are starting a new project, you frequently hit duplicate class errors which you need to fix first. However, in return you get full control of the classpath and very quick way of switching between different versions of a particular library. Personally I switch between development and release libraries quite often and nothing beats the convenience of developing and debugging a new version of a library in place together with your actual web application. With run-jetty-run (which I do use frequently), it's simpler and more automated to get started but it's not possible to directly modify the container's classpath and there's no context reload either. Choose the tool that better fits your development style, but in any case, it's always useful to know your tools.
In a nutshell:
- Know your tools
- Use the latest versions
- If there's a problem, it's worth fixing it
- Don't use the WTP integration - it's slow and error-prone