|
How to Deploy to Apache Tomcat
|
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.
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.
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.
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
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.
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.
...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/
How not to use the Ubuntu repository...
JAVA_HOME=/home/russ/Downloads/jdk1.6.0_20 PATH="$PATH:$JAVA_HOME/bin"
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.
russ@tuonela:~/Downloads/apache-tomcat-6.0.26/webapps> cp ~/Downloads/dvdcatalog.war .
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.
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
This will yield the 500 error above. Why?
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.
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.
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.
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.
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.
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.