During development I frequently have to deploy a large war-file (~45 MB) to a remote test server, normally I copy the file with scp to the server.
The WEB-INF/lib folder makes up the largest part of the war file, which includes all the required libraries (spring, apache-cxf, hibernate,...).
Now I'm searching for an fast and easy a way to redeploy only my altered files.
And how can I determine which packages are really needed by the webapp, because spring and apache-cxf comes with a lot of libs, I'm sure I don't need all of them.
Go to your project Directory and inside Dist Folder you will get war file that you copy on your tomcat. webApp Folder. Start the tomcat.
Perhaps the simplest way to deploy a WAR file to Tomcat is to copy the file to Tomcat's webapps directory. Copy and paste WAR files into Tomcat's webapps directory to deploy them. Tomcat monitors this webapps directory for changes, and if it finds a new file there, it will attempt to deploy it.
A web application can be deployed in Tomcat by one of the following approaches: Copy unpacked directory hierarchy into a subdirectory in directory $CATALINA_BASE/webapps/ . Tomcat will assign a context path to your application based on the subdirectory name you choose. We will use this technique in the build.
Improving on Rori Stumpf answer, here is a Gradle task for the 'thinning'
war {
archiveName "v1.war"
}
task createThinWar(type: Copy) {
dependsOn 'war'
def tmpFolder = "${buildDir}/tmp/thin"
def outputDir = "${buildDir}/libs"
// Extract the war (zip) contents
from zipTree("${outputDir}/v1.war")
into "${tmpFolder}/v1"
doLast {
// Extracting the war third party libraries to a separate dir
ant.move(file: "${tmpFolder}/v1/WEB-INF/lib", tofile: "${tmpFolder}/v1-libs")
// Zip the third party libraries dir
ant.zip(destfile: "${outputDir}/v1-libs.zip") {
fileset(dir: "${tmpFolder}/v1-libs")
}
// Finally zip the thinned war back
ant.zip(destfile: "${outputDir}/v1-thin.war") {
fileset(dir: "${tmpFolder}/v1")
}
}
}
This will generate v1-thin.war (weighting less then 1mb), and a libs zip.
deploy the thin war to the server (and reconstruct the libs there), and deploy the libs zip whenever you modified the versions/add libraries.
When you deploy a .war
, the first thing Tomcat does is to unpack that file into its webapps
directory, in a subdirectory with the same name as your .war
.
During development, you obviously have access to your .class
files, the .jar
files, configuration files and whatever else eventually goes into your .war
. You can easily establish a small subset of files affected by your changes. Figure that out, and then use a script or an ant
task or whatever to copy just that small handful of files straight into the webapps/yourapp
directory on the server.
To see your changes take effect, you'll need to re-start your application. If Tomcat is in development mode, one easy way to force a reload (and restart, of course) is to update WEB-INF/web.xml
. So have your deployment process touch
that file or otherwise update it in a way that will give it a new timestamp, scp
that over too (preferrably as the last of the files you update) and you should have a quick and easy reload.
What I do is exclude WEB-INF/lib/*.jar files from the WAR and reassemble on the server side. In my case, this trims a 60MB WAR down to 250k which allows for really fast deployment.
The <exclude name="**/lib/*.jar"/>
command is what excludes the jar's (see last code snippet for ANT build)
On the server side, it's quite easy to assemble a fully populated WAR from the trimmed WAR:
For example:
unzip ../myapp.trimmed.war
mkdir WEB-INF/lib
cp ../war_lib_repository/* WEB-INF/lib
zip -r ../myapp.war .
Maybe not the most elegant solution, but it saves time on frequent deployment of large WAR's. I'd like to be able to do this with Maven so if anyone has suggestions, please let me know.
ANT build.xml:
<property file="build.properties"/>
<property name="war.name" value="myapp.trimmedwar"/>
<property name="deploy.path" value="deploy"/>
<property name="src.dir" value="src"/>
<property name="config.dir" value="config"/>
<property name="web.dir" value="WebContent"/>
<property name="build.dir" value="${web.dir}/WEB-INF/classes"/>
<property name="name" value="${war.name}"/>
<path id="master-classpath">
<fileset dir="${web.dir}/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<!-- other classes to include -->
<fileset dir="${birt.runtime}/ReportEngine/lib">
<include name="*.jar"/>
</fileset>
<pathelement path="${build.dir}"/>
</path>
<target name="build" description="Compile main source tree java files">
<mkdir dir="${build.dir}"/>
<javac destdir="${build.dir}" debug="true" deprecation="false" optimize="false" failonerror="true">
<src path="${src.dir}"/>
<classpath refid="master-classpath"/>
</javac>
</target>
<target name="createwar" depends="build" description="Create a trimmed WAR file (/lib/*.jar) excluded for size">
<!-- copy the hibernate config file -->
<copy todir="${web.dir}/WEB-INF/classes">
<!-- copy hibernate configs -->
<fileset dir="${src.dir}/" includes="**/*.cfg.xml" />
</copy>
<copy todir="${web.dir}/WEB-INF/classes">
<fileset dir="${src.dir}/" includes="**/*.properties" />
</copy>
<!-- copy hibernate classes -->
<copy todir="${web.dir}/WEB-INF/classes" >
<fileset dir="${src.dir}/" includes="**/*.hbm.xml" />
</copy>
<war destfile="${name}.war" webxml="${web.dir}/WEB-INF/web.xml">
<fileset dir="${web.dir}">
<include name="**/*.*"/>
<!-- exlude the jdbc connector because it's on the server's /lib/common -->
<exclude name="**/mysql-connector*.jar"/>
<!-- exclude these jars because they're already on the server (will be wrapped into the trimmed war at the server) -->
<exclude name="**/lib/*.jar"/>
</fileset>
</war>
<copy todir="${deploy.path}" preservelastmodified="true">
<fileset dir=".">
<include name="*.war"/>
</fileset>
</copy>
</target>
I use rsync
to copy my .war
from my local machine to production. It usually provides a big speed up, around 8-10 times.
Another option is to use git
to store the .war
files. When you git push
a new .war
, only the differences are transferred. Also a big speed up. Some people say that git is not designed to store big files, it gets slow and does not work very well. In fact yes, the repo will grow a lot, but in some cases it could be a good option.
Some numbers: My .war
is about 50MB and when I deploy a new version, it only copies about ~4MB instead of uploading a complete new war. Both with git
and rsync
.
UPDATE: The problem I ran into it's the git repo cannot be cloned after it has several .war
versions because it will take forever to create all the deltas and transmit them to the client.
I changed the strategy by uploading the .war
files into dropbox. Dropbox also uses kind of rsync
and only copies deltas. From the server I wget the .war
and re-reploy the app. Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With