How to Deploy to Apache Tomcat
to Ubuntu Lucid

Russell Bateman
April 2010
last update:

This isn't about setting up Tomcat with Eclipse for development, but how to set it up on your Linux computer host as the container-server it is.

A few words on Tomcat-Eclipse integration...

Deploying a web application involves building a WAR or EAR file and copying the same to some folder where the server container is assumed to auto-serve that file, i.e.: explode its contents out to a file subsystem whence they are served up.

Practically speaking, if you modify a web-relevant file such as a JSP file and want to publish that change to the Tomcat server, it involves building a whole new WAR are EAR file and replacing the file previously copied where, it is assumed, the server will notice the change and redeploy the file. This is what you must do if you're not using Eclipse (or, at least, not using Eclipse's Tomcat integration).

With Eclipse integration (support), publishing a project only involves copying individual files. If you modify a JSP file, publishing that change to the server only involves copying that JSP file; the server is restarted and you're up and running on the instance almost without knowing.

For example, with Eclipse integration, my application is published to Tomcat on the path:

<workspace>/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps

Where I see:

russ@tuonela:~> ll dev/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps total 0 drwxr-xr-x 4 russ russ 104 2011-08-05 08:54 . drwxr-xr-x 8 russ russ 232 2011-05-13 08:15 .. drwxr-xr-x 4 russ russ 128 2011-11-04 14:50 dvdcatalog drwxr-xr-x 3 russ russ 72 2011-05-05 10:02 ROOT

Also, there is also more support for changing the actual configuration of the server within Eclipse.

Sun JDK

Prior to installing Tomcat, ensure that you've got a rather late-mode Sun JDK installed for use by your computer host. If you keep up on automatic updates, you're probably already set there.

Tomcat installation

On Ubuntu, use the Synaptic Package Manager. Launch (from System -> Administration -> Synaptic Package Manager. Then click on Search and type "tomcat". Click the following packages to install (as well as accepting all their dependencies):

If you don't want Tomcat's examples or perfer to access the documents on-line, you can give those packages a miss.


Click Apply.

This was a helpful page: http://www.ubuntugeek.com/how-to-install-tomcat-6-on-ubuntu-9-04-jaunty.html. Follow the instructions on fixing up tomcat-users.xml scrupulously.

I also checked out How-To Geek: Installing Tomcat6 on Ubuntu.

Bounce Tomcat before going to the management link via:

root@taliesin:~> /etc/init.d/tomcat restart

Modifying tomcat-users.xml

This file is on the path /etc/tomcat6/tomcat-users.xml when Tomcat is installed formally, that is, using the Ubuntu repository. When downloaded privately, it's on the path conf/tomcat-users.xml.

This probably isn't necessary except and unless you wish to use the Apache Tomcat manager application. Nevertheless, I modified this file to contain the following lines in the <tomcat-users> element. I left the original commented lines in.

<role rolename="tomcat" /> <role rolename="role1" /> <role rolename="manager" /> <role rolename="admin" /> <role rolename="standard" /> <user username="tomcat" password="tomcat" roles="tomcat"/> <user username="both" password="tomcat" roles="tomcat,role1"/> <user username="role1" password="tomcat" roles="role1"/> <user username="russ" password="xxxxxxxxxx" roles="standard,manager" /> <user username="admin" password="tomcat" roles="manager,admin" />

I took an unnecessarily "blunderbuss" approach to this file because, at the time, I was trying desperately to get the Tomcat manager application to authenticate me.

Repository installation (continued)

Also, see Setting Up and Integrating Tomcat into Eclipse.

You can browse to http://localhost:8080/manager/ and use the manager page to upload your WAR and otherwise see what Tomcat applications exist, are running, etc.

(Note: you created your application's WAR file by right-clicking the project in Eclipse, choosing Export, then WAR File, then naming it and choosing some place in your file system to save it. You then sent it to your web server.)

You deploy your WAR file by copying to /var/lib/tomcat6/webapps/name and bouncing Tomcat. You browse to it via URL http://localhost:8080/name/thing.jsp where thing.jsp is whatever entry JSP you wish. In my case, this was http://localhost:8080/dvdcatalog/login.jsp.

I have so far got this error trying out my newly deployed DVD catalog application:

HTTP Status 500 -
type Exception report message description The server encountered an internal error () that prevented it from fulfilling this request. exception org.apache.jasper.JasperException: An exception occurred processing JSP page /login.jsp at line 19 16: //Locale.setDefault( new Locale( "fr" ) ); 17: %> 18: <body> 19: <f:view> 20: <f:loadBundle basename="com.etretatlogiciels.dvdcatalog.messages" var="msg" /> 21: 22: <div style="width: 300px"> Stacktrace: org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:510) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:419) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) root cause java.lang.RuntimeException: FacesContext not found javax.faces.webapp.UIComponentClassicTagBase.getFacesContext(UIComponentClassicTagBase.java:241) javax.faces.webapp.UIComponentClassicTagBase.getPreviousJspIdsSet(UIComponentClassicTagBase.java:1258) javax.faces.webapp.UIComponentClassicTagBase.checkIfItIsInAnIterator(UIComponentClassicTagBase.java:1243) javax.faces.webapp.UIComponentClassicTagBase.setJspId(UIComponentClassicTagBase.java:168) org.apache.jsp.login_jsp._jspx_meth_f_005fview_005f0(login_jsp.java:161) org.apache.jsp.login_jsp._jspService(login_jsp.java:116) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) note The full stack trace of the root cause is available in the Apache Tomcat/6.0.24 logs.

How to amend the Apache vhosts configuration...

...to steer everything Tomcat's way?

Later, on a real web server, add this at the end of the aintnoclouds.conf file, where aintnoclouds is the domain name whose entry page requires Tomcat. See (if it's still in place when you read this): http://www.aintnoclouds.com/.

ProxyRequests Off <Proxy *> Order deny,allow Allow from all </Proxy> ProxyPass /aintnoclouds/ http://localhost:8080/aintnoclouds/ ProxyPassReverse /aintnoclouds/ http://localhost:8080/aintnoclouds/ ProxyPass / http://localhost:8080/aintnoclouds/ ProxyPassReverse / http://localhost:8080/aintnoclouds/

New Tomcat from scratch instructions

How not to use the Ubuntu repository...

  1. Download Tomcat 6, uncompress and untar.
  2.  
  3. Download Sun JDK, make executable and execute.
  4.  
  5. Modify .bashrc to add:
    JAVA_HOME=/home/russ/Downloads/jdk1.6.0_20 PATH="$PATH:$JAVA_HOME/bin"
  6. With new shell, change to apache-tomcat-6.0.26/bin and start Tomcat:
    russ@tuonela:~/Downloads/apache-tomcat-6.0.26/bin> ./startup.sh Using CATALINA_BASE: /home/russ/Downloads/apache-tomcat-6.0.26 Using CATALINA_HOME: /home/russ/Downloads/apache-tomcat-6.0.26 Using CATALINA_TMPDIR: /home/russ/Downloads/apache-tomcat-6.0.26/temp Using JRE_HOME: /home/russ/Downloads/jdk1.6.0_20 Using CLASSPATH: /home/russ/Downloads/apache-tomcat-6.0.26/bin/bootstrap.jar

    (Note: when not expressly specified, JRE_HOME is derived from the value of JAVA_HOME in the invoking environment.

  7. Copy your WAR file to the webapps subdirectory.
    russ@tuonela:~/Downloads/apache-tomcat-6.0.26/webapps> cp ~/Downloads/dvdcatalog.war .
  8. Bounce Tomcat. Since you're not using the Ubuntu repository installation, but a private one, you'll need to
    russ@tuonela:~/Downloads/apache-tomcat-6.0.26/bin> ./shutdown.sh russ@tuonela:~/Downloads/apache-tomcat-6.0.26/bin> ./startup.sh

    (I create a new script, bounce.sh, in that subdirectory that just does this.

  9. Verify that Tomcat is up (the following reply from ps has been wrapped to fit here):
    russ@tuonela:~/Downloads/apache-tomcat-6.0.26/webapps$ ps -ef | grep [t]omcat russ 12988 1 1 09:20 pts/0 00:00:02 /home/russ/Downloads/jdk1.6.0_20/bin/java \ -Djava.util.logging.config.file=/home/russ/Downloads/apache-tomcat-6.0.26/conf/logging.properties \ -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager \ -Djava.endorsed.dirs=/home/russ/Downloads/apache-tomcat-6.0.26/endorsed \ -classpath /home/russ/Downloads/apache-tomcat-6.0.26/bin/bootstrap.jar \ -Dcatalina.base=/home/russ/Downloads/apache-tomcat-6.0.26 \ -Dcatalina.home=/home/russ/Downloads/apache-tomcat-6.0.26 \ -Djava.io.tmpdir=/home/russ/Downloads/apache-tomcat-6.0.26/temp \ org.apache.catalina.startup.Bootstrap start
  10. Now attempt to launch the web application. In a browser, enter http://localhost:8080/dvdcatalog/login.jsp and press Enter.

    This will yield the 500 error above. Why?

Onward and upward?

Pursuant to a thread I read in a JavaRanch forum, I changed *.jsf to *.jsp in web.xml in Eclipse, which still allowed login.jsp to work in that environment. Then I changed webapps/dvdcatalog/WEB-INF/web.xml similarly and refreshed the page. This led to (after a very long time):

An Error Occurred: +--------------------------------------------+ | context | | | | | | Caused by: | | java.lang.NullPointerException - context | +--------------------------------------------+ - Stack Trace java.lang.NullPointerException: context at javax.faces.component.UIComponentBase.getRenderer(UIComponentBase.java:862) at javax.faces.component.UIComponentBase.getRendersChildren(UIComponentBase.java:350) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:248) at org.apache.myfaces.application.jsp.JspViewHandlerImpl.actuallyRenderView(JspViewHandlerImpl.java:427) at org.apache.myfaces.application.jsp.JspViewHandlerImpl.renderView(JspViewHandlerImpl.java:383) at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:41) at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:140) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:182) at org.apache.myfaces.webapp.MyFacesServlet.service(MyFacesServlet.java:103) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:619) + Component Tree + Scoped Variables

This was reminiscent of an error I had got in Eclipse by changing the URL to http://localhost:8080/dvdcatalog/faces/login.jsf.

Wildly changing to http://localhost:8080/dvdcatalog/login.jsf in my browser (outside Eclipse in the real world I'm trying to conquer), I merely got an HTTP 404 (Not Found) error.

But, you object, the path is really http://localhost:8080/dvdcatalog/faces/login.jsp according to how it works in Eclipse.

The behavior is identical whether faces/ is in the path or not.

Grasping at straws, I've also tried using .faces as the extension—no difference.

Clearly though, it's a web.xml nightmare.

Wrap-up

Ultimately, this began working and, embarrassingly, I can't figure out why since I'm pretty certain what began to work was in fact what I was trying to fee Tomcat in the first place. As I didn't download the WAR file yet again, though I doctored (and undoctored) the web.xml file several times, in the end it's what I brought down that worked. To prove this to myself, I downloaded dvdcatalog.war afresh and it still worked.

As one is wont to say today, "Go figure."

I have not attempted to get this running using the Tomcat installed by Ubuntu.

Using wget to download the WAR file and deploy it

Here's a short session at the command line that demonstrates downloading and deploying a WAR file generated by Eclipse.

russ@tuonela:~/Downloads/apache-tomcat-6.0.26/webapps$ wget http://www.windofkeltia.com/dvdcatalog/dvdcatalog.war --2010-05-20 14:58:35-- http://www.windofkeltia.com/dvdcatalog/dvdcatalog.war Resolving www.windofkeltia.com... 69.169.174.12 Connecting to www.windofkeltia.com|69.169.174.12|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 11018701 (11M) [application/x-java-archive] Saving to: `dvdcatalog.war.1' 100%[==================================================================================================>] 11,018,701 342K/s in 22s 2010-05-20 14:58:57 (496 KB/s) - `dvdcatalog.war.1' saved [11018701/11018701] russ@tuonela:~/Downloads/apache-tomcat-6.0.26/webapps$ ll total 21552 drwxr-xr-x 10 russ russ 4096 2010-05-20 08:20 docs drwxr-xr-x 6 russ russ 4096 2010-05-20 14:56 dvdcatalog -rw-r--r-- 1 russ russ 11019235 2010-05-20 09:18 dvdcatalog.war -rw-r--r-- 1 russ russ 11018701 2010-05-20 11:54 dvdcatalog.war.1 drwxr-xr-x 5 russ russ 4096 2010-05-20 08:20 examples drwxr-xr-x 5 russ russ 4096 2010-05-20 08:20 host-manager drwxr-xr-x 5 russ russ 4096 2010-05-20 08:20 manager drwxr-xr-x 3 russ russ 4096 2010-05-20 08:20 ROOT russ@tuonela:~/Downloads/apache-tomcat-6.0.26/webapps$ pu ../bin ~/Downloads/apache-tomcat-6.0.26/bin ~/Downloads/apache-tomcat-6.0.26/webapps ~ russ@tuonela:~/Downloads/apache-tomcat-6.0.26/bin$ ./bounce.sh Using CATALINA_BASE: /home/russ/Downloads/apache-tomcat-6.0.26 Using CATALINA_HOME: /home/russ/Downloads/apache-tomcat-6.0.26 Using CATALINA_TMPDIR: /home/russ/Downloads/apache-tomcat-6.0.26/temp Using JRE_HOME: /home/russ/Downloads/jdk1.6.0_20 Using CLASSPATH: /home/russ/Downloads/apache-tomcat-6.0.26/bin/bootstrap.jar Using CATALINA_BASE: /home/russ/Downloads/apache-tomcat-6.0.26 Using CATALINA_HOME: /home/russ/Downloads/apache-tomcat-6.0.26 Using CATALINA_TMPDIR: /home/russ/Downloads/apache-tomcat-6.0.26/temp Using JRE_HOME: /home/russ/Downloads/jdk1.6.0_20 Using CLASSPATH: /home/russ/Downloads/apache-tomcat-6.0.26/bin/bootstrap.jar russ@tuonela:~/Downloads/apache-tomcat-6.0.26/bin$ po ~/Downloads/apache-tomcat-6.0.26/webapps ~ russ@tuonela:~/Downloads/apache-tomcat-6.0.26/webapps$ ll total 21552 drwxr-xr-x 10 russ russ 4096 2010-05-20 08:20 docs drwxr-xr-x 6 russ russ 4096 2010-05-20 14:56 dvdcatalog -rw-r--r-- 1 russ russ 11019235 2010-05-20 09:18 dvdcatalog.war -rw-r--r-- 1 russ russ 11018701 2010-05-20 11:54 dvdcatalog.war.1 drwxr-xr-x 5 russ russ 4096 2010-05-20 08:20 examples drwxr-xr-x 5 russ russ 4096 2010-05-20 08:20 host-manager drwxr-xr-x 5 russ russ 4096 2010-05-20 08:20 manager drwxr-xr-x 3 russ russ 4096 2010-05-20 08:20 ROOT

Then, turn to the browser and type http://localhost:8080/dvdcatalog/faces/login.jsp. At this point, it works.

Libraries list

There are the libraries on dvdcatalog/WEB-INF/lib—just in case it's useful to point this out:

-rw-r--r-- 1 russ russ 443432 2010-05-18 11:10 antlr-2.7.6.jar -rw-r--r-- 1 russ russ 322362 2010-05-18 11:10 cglib-nodep-2.2.jar -rw-r--r-- 1 russ russ 188671 2010-05-18 11:10 commons-beanutils-1.7.0.jar -rw-r--r-- 1 russ russ 46725 2010-05-18 11:10 commons-codec-1.3.jar -rw-r--r-- 1 russ russ 559366 2010-05-18 11:10 commons-collections-3.1.jar -rw-r--r-- 1 russ russ 571259 2010-05-18 11:10 commons-collections-3.2.jar -rw-r--r-- 1 russ russ 143602 2010-05-18 11:10 commons-digester-1.8.jar -rw-r--r-- 1 russ russ 76685 2010-05-18 11:10 commons-discovery-0.4.jar -rw-r--r-- 1 russ russ 60686 2010-05-18 11:10 commons-logging-1.1.1.jar -rw-r--r-- 1 russ russ 3893179 2010-05-18 11:10 hibernate3.jar -rw-r--r-- 1 russ russ 597476 2010-05-18 11:10 javassist-3.9.0.GA.jar -rw-r--r-- 1 russ russ 153115 2010-05-18 11:10 jdom-1.1.jar -rw-r--r-- 1 russ russ 56702 2010-05-18 11:10 jettison-1.0.1.jar -rw-r--r-- 1 russ russ 534827 2010-05-18 11:10 joda-time-1.6.jar -rw-r--r-- 1 russ russ 30691 2010-05-18 11:10 jstl-api-1.2.jar -rw-r--r-- 1 russ russ 392435 2010-05-18 11:10 jstl-impl-1.2.jar -rw-r--r-- 1 russ russ 10899 2010-05-18 11:10 jta-1.1.jar -rw-r--r-- 1 russ russ 391834 2010-05-18 11:10 log4j-1.2.15.jar -rw-r--r-- 1 russ russ 378921 2010-05-18 11:10 myfaces-api-1.2.8.jar -rw-r--r-- 1 russ russ 801254 2010-05-18 11:10 myfaces-impl-1.2.8.jar -rw-r--r-- 1 russ russ 732695 2010-05-18 11:10 mysql-connector-java-5.1.12-bin.jar -rw-r--r-- 1 russ russ 23445 2010-05-18 11:10 slf4j-api-1.5.8.jar -rw-r--r-- 1 russ russ 7600 2010-05-18 11:10 slf4j-simple-1.5.11.jar -rw-r--r-- 1 russ russ 179346 2010-05-18 11:10 stax-1.2.0.jar -rw-r--r-- 1 russ russ 26514 2010-05-18 11:10 stax-api-1.0.1.jar -rw-r--r-- 1 russ russ 520969 2010-05-18 11:10 wstx-asl-3.2.7.jar -rw-r--r-- 1 russ russ 5234 2010-05-18 11:10 xml-writer-0.2.jar -rw-r--r-- 1 russ russ 431568 2010-05-18 11:10 xom-1.1.jar -rw-r--r-- 1 russ russ 24956 2010-05-18 11:10 xpp3_min-1.1.4c.jar -rw-r--r-- 1 russ russ 431406 2010-05-18 11:10 xstream-1.3.1.jar

Note that Tomcat libraries like servlet-api.jar are conspicuously absent. This is because Tomcat already had them. You should neither put them explicitly on the Eclipse Build Path (except for Apache Tomcat vX.0 in the Libraries tab) nor in the Deployment Assembly. Otherwise, you'll get errors such as:

...jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class

However! If you're using ant to build for deployment, for Hudson/Jenkins/CruiseControl, etc., you may find you need this JAR (and others like it) to satisfy class definitions at compile time even though you won't need to deploy it. For this reason, you must keep it around, but it doesn't need to be added to Eclipse Build Path (usually) and you must not add it to the Deployment Assembly. This problem arises in the difference between Eclipse building and internally deploying to Tomcat versus a build done without what Eclipse knows and understands.

Appendix: Tomcat files installed (Ubuntu distribution)

Some of these are files and others are subdirectories below which Tomcat files are found. (Many results of locate were discarded.)

* below indicates the business area of Tomcat below which are webapps and the skel subdirectories.

This supposes you install Tomcat from Ubuntu repositories.

root@tuonela:/var/lib/tomcat6/webapps/dvdcatalog# locate tomcat /etc/tomcat6 /etc/cron.daily/tomcat6 /etc/default/tomcat6 /etc/init.d/tomcat6 /etc/rc0.d/K08tomcat6 /etc/rc1.d/K08tomcat6 /etc/rc2.d/S92tomcat6 /etc/rc3.d/S92tomcat6 /etc/rc4.d/S92tomcat6 /etc/rc5.d/S92tomcat6 /etc/rc6.d/K08tomcat6 /usr/bin/tomcat6-instance-create /usr/share/tomcat6/* /usr/share/tomcat6-admin /usr/share/tomcat6-docs /usr/share/tomcat6-examples /usr/share/doc/libtomcat6-java /usr/share/doc/tomcat6 /usr/share/doc/tomcat6-admin /usr/share/doc/tomcat6-common /usr/share/doc/tomcat6-docs /usr/share/doc/tomcat6-examples /usr/share/doc/tomcat6-user /usr/share/doc-base/tomcat6 /usr/share/java/tomcat-coyote-6.0.24.jar /usr/share/java/tomcat-coyote.jar /usr/share/java/tomcat-i18n-es-6.0.24.jar /usr/share/java/tomcat-i18n-es.jar /usr/share/java/tomcat-i18n-fr-6.0.24.jar /usr/share/java/tomcat-i18n-fr.jar /usr/share/java/tomcat-i18n-ja-6.0.24.jar /usr/share/java/tomcat-i18n-ja.jar /usr/share/java/tomcat-juli-6.0.24.jar /usr/share/java/tomcat-juli.jar /usr/share/man/man2/tomcat6-instance-create.2.gz /usr/share/maven-repo/org/apache/tomcat

The skeleton subdirectory doesn't come down with apache-tomcat-6.0.26.tar.gz

I found that apache-tomcat-6.0.26-deployer.tar.gz could be uncompressed, but not un-tarred.

Appendix: My working Tomcat installation (May 2011)

Where to deploy that WAR file?

This is written much later than the chaotic notes above. When you install Tomcat on Ubuntu Lucid, you end up with:

/var/lib/tomcat6/webapps
/usr/share/tomcat6

Note that Jenkins' working fodder (projects it's building) is on the path /usr/share/tomcat6/.jenkins/jobs/projectname, but it's /var/lib/tomcat6/webapps where jenkins.war is dropped.

But, it's on that same path (/var/lib/tomcat6/webapps) that you drop any WAR you hope to deploy. In the worst case, it doesn't then deploy, but bouncing Tomcat will do the trick.