Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I create a custom classpath on a per application basis in Tomcat

For some applications I use ZK, others Hibernate, other Apache Commons, etc.

I don't want to deploy a 75MB war file, just because it uses lots of libraries.

I don't want to add the libraries to my tomcat lib folder, or nor the classpath to it's configuration as I may have an old application using library x.1 and another application using library x.2

For this reason, it would be great to have something in the web.xml or context.xml where I say something like:

<classpath>/usr/local/tomcat/custom-libs/zk-5.0.4</classpath> 

Note: The above is pseudo-code

like image 473
sparkyspider Avatar asked Jun 14 '11 15:06

sparkyspider


People also ask

What is classpath in Tomcat server?

A classpath is an argument that tells the JVM where to find the classes and packages necessary to run a program. The classpath is always set from a source outside the program itself.

How Tomcat ClassLoader works?

Like many server applications, Tomcat installs a variety of class loaders (that is, classes that implement java. lang. ClassLoader ) to allow different portions of the container, and the web applications running on the container, to have access to different repositories of available classes and resources.

Where do I put jar files in tomcat?

Package the JAR file in the WEB-INF\lib folder of the Java web application; Place the JAR file in the \lib subfolder of the Apache Tomcat installation; Configure a folder for shared JAR files by editing Tomcat's common.


2 Answers

From Tomcat 7 there is no mention of not being able to use the VirtualWebappLoader in production. I tried it and it works like a dream. Simply add the following to META-INF/context.xml:

<?xml version="1.0" encoding="UTF-8"?>  <Context antiJARLocking="true" path="/websandbox">     <Loader className="org.apache.catalina.loader.VirtualWebappLoader"           virtualClasspath="/usr/.../*.jar;/usr/.../*.jar"/> </Context> 

In Netbeans, under packaging, I just untick all the packages, taking the .war size down to nothing, make sure the dependencies are in the correct folders on the server and upload. Yey! No more 100 MB WAR file.

like image 189
sparkyspider Avatar answered Oct 11 '22 06:10

sparkyspider


Addition @Spider answer.

Tomcat Context hold Loader element. According to docs deployment descriptor (what in <Context> tag) can be placed in:

  • $CATALINA_BASE/conf/server.xml - bad - require server restarts in order to reread config
  • $CATALINA_BASE/conf/context.xml - bad - shared across all applications
  • $CATALINA_BASE/work/$APP.war:/META-INF/context.xml - bad - require repackaging in order to change config
  • $CATALINA_BASE/work/[enginename]/[hostname]/$APP/META-INF/context.xml - nice, but see last option!!
  • $CATALINA_BASE/webapps/$APP/META-INF/context.xml - nice, but see last option!!
  • $CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml - best - completely out of application and automatically scanned for changes!!!

Here my config which demonstrate how to use development version of project files out of $CATALINA_BASE hierarchy (note that I place this file into src/test/resources dir and intruct Maven to preprocess ${basedir} placeholders through pom.xml <filtering>true</filtering> so after build in new environment I copy it to $CATALINA_BASE/conf/Catalina/localhost/$APP.xml):

<Context docBase="${basedir}/src/main/webapp"          reloadable="true">     <!-- http://tomcat.apache.org/tomcat-7.0-doc/config/context.html -->     <Resources className="org.apache.naming.resources.VirtualDirContext"                extraResourcePaths="/WEB-INF/classes=${basedir}/target/classes,/WEB-INF/lib=${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>     <Loader className="org.apache.catalina.loader.VirtualWebappLoader"             virtualClasspath="${basedir}/target/classes;${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>     <JarScanner scanAllDirectories="true"/>      <!-- Use development version of JS/CSS files. -->     <Parameter name="min" value="dev"/>     <Environment name="app.devel.ldap" value="USER" type="java.lang.String" override="true"/>     <Environment name="app.devel.permitAll" value="true" type="java.lang.String" override="true"/> </Context> 

UPDATE Tomcat 8 change syntax for <Resources> and <Loader> elements, corresponding part now look like:

<Resources>     <PostResources className="org.apache.catalina.webresources.DirResourceSet"                    webAppMount="/WEB-INF/classes" base="${basedir}/target/classes" />     <PostResources className="org.apache.catalina.webresources.DirResourceSet"                    webAppMount="/WEB-INF/lib" base="${basedir}/target/${project.build.finalName}/WEB-INF/lib" /> </Resources> 
like image 35
gavenkoa Avatar answered Oct 11 '22 05:10

gavenkoa