Compiling JSP pages using ANT

Author: Kasper B. Graversen, 11/12/07
Keywords: ANT, Build script, Compile, JSP, Servlet
Abstract: Compiling JSP Code is the right thing to do. It enables you to get compile-time errors rather than run-time errors. It ensures consistency as all the JSP's and Java files can be shipped in one package.
subscribe to my RSS feed


Bookmark and Share


Compiling JSP pages using ANT

When JSP pages are uploaded to a web server and they are not compiled before a request for the page. Upon displaying the JSP for the first time, the webserver automatically compiles the JSP file into a servlet java file which then is compiled into a servlet class file. Then, an internal mapping similar to the web.xml is updated. This approach raises a number of issues.
  • Since the JSP is only compiled upon viewing, when you upload your JSP you need to view it in order to be 100% sure its error-free. Unless automated, this is tedious and is by all means time consuming
  • During compilation the server will seem unresponsive, and worse, if JSP's are uploaded to a live server, changes are that if the JSP's are being accessed during upload a newly uploaded JSP may use another old JSP (if that JSP is in the process of being uploaded or is awaiting to be uploaded). This may lead to some serious inconsistencies which may ripple all the way to the DB and cause long-term head-aches.
  • Against the idea of JSP compilation is that it may appear to be easier to just upload single changed JSP files rather than a large big chunk. While the argument may seem valid on the small scale it certainly does not scale up to several installations and many hundreds of JSP files. Especially not if the JSP's are relying on changed java classes.
  • The JSP compilation takes care of including Javascript included on pages. However, I have experienced that a weird integration of the FCKEditor did not work with JSP compiling. So be careful when you embark on the path of JSP compilation.
The end product of a JSP compilation is a .war file which can be dumped into your webservers webapp/ dir. The server should then auto-deploy it. To get to the .war file a number of steps are taken in ANT.
  • JSP's are compiled into servlets (target jsp_compile)
  • The compiled servlets are mapped in a generated web.xml file (in the argument webXmlFragment="${webapp.path}/WEB-INF/generated_web.xml") and this generated web.xml is merged with the original web.xml with the argument (addWebXmlMappings="true" . This enables the compiled JSP's to be accessed through a URL.
  • Servlets and your java code are compiled into classes.
  • Finally, it is all wrapped in the .war file.
<!-- path of the web source files -->
<property name="webapp.path" value="." />

<!-- build output name -->
<property name="output_war" value="myapp.war" />

<!-- paths to the Tomcat JSP compiler -->
<property name="catalina.home" value="C:\Programmer\Tomcat 5.5" />

<target name="make_war" depends="compile">
    <description>Harvest the compiled files and html files into a WAR file ready for deployment</description>
    <war destfile="${output_war}" webxml="${webapp.path}/WEB-INF/web.xml">
        <classes dir="${webapp.path}/WEB-INF/classes"/>
        <zipfileset dir="${webapp.path}/graphics/images/" prefix="images"/>
    </war>
</target>


<target name="compile" depends="jsp_compile">
    <description>
    Compile the generated servlets and change web.xml into mapping the servlets to the corresponding .jsp urls.
    </description>

    <mkdir dir="${webapp.path}/WEB-INF/classes"/>
    <mkdir dir="${webapp.path}/WEB-INF/lib"/>

    <javac destdir="${webapp.path}/WEB-INF/classes" srcdir="${webapp.path}/WEB-INF/src" >
        <classpath>
            <pathelement location="${webapp.path}/WEB-INF/classes" />
            <fileset dir="${webapp.path}/WEB-INF/lib">    <include name="*.jar" /></fileset>

            <pathelement location="${catalina.home}/common/classes" />
            <fileset dir="${catalina.home}/common/lib">    <include name="*.jar" /></fileset>

            <pathelement location="${catalina.home}/shared/classes" />
            <fileset dir="${catalina.home}/shared/lib">    <include name="*.jar" /></fileset>

            <fileset dir="${catalina.home}/bin">        <include name="*.jar" /></fileset>
        </classpath>
        <include name="**" />
        <exclude name="tags/**" />
    </javac>
</target>


<target name="jsp_compile" depends="clean_jspcompile">
    <description>Take all .jsp pages and convert them into servlets using the Tomcat jsp compiler</description>
    <taskdef classname="org.apache.jasper.JspC" name="jasper2">
        <classpath id="jspc.classpath">
            <fileset dir="${catalina.home}/bin"><include name="*.jar"/>    </fileset>
            <fileset dir="${catalina.home}/server/lib">    <include name="*.jar"/>    </fileset>
            <fileset dir="${catalina.home}/common/lib">    <include name="*.jar"/>    </fileset>
        </classpath>
    </taskdef>

    <jasper2 uriroot="${webapp.path}"
             webXmlFragment="${webapp.path}/WEB-INF/generated_web.xml"
             addWebXmlMappings="true"
             outputDir="${webapp.path}/WEB-INF/src/" />

              <!-- path to the compiler generated web.xml -->
              <!-- automatically merge the "generated_web.xml" into "web.xml" -->
              <!-- path to the output of the compilation  -->
</target>

<target name="clean_jspcompile">
    <description>clear the generated source files</description>
    <delete dir="${webapp.path}/WEB-INF/src"/>
</target>
Finally, you may run into problems when using the JSP include mechanism, since if you have a lot of "generic building blocks" these may be compiled into servlets, but they are not valid classes, i.e. when being compiled to byte-code, the compilation fails. To prevent this you need a target after the JSPs have been compiled that deletes these invalid servlet classes, before the servlets and the java code base is compiled.



Comments

If you have any comments to this article, please drop me a mail at firstclassthoughts at gmail dot com please indicate if I can't publish whole or parts of your comment on the site.


If you like this site consider subscribing to my RSS feed or how about subscribing by Email.


Help spread the word

Share this post on your favorite social bookmarking sites:
If you enjoyed this article, found it thought provoking, educative or otherwise good, please link to this page from your page or social bookmarking page. If you have any texts you think are worth publishing on First Class Thoughts, don't hesitate to send me a mail! Quality always welcome.


Bookmark and Share


The most recent contributions
28/07/09 Magic in mathematics II Fun with the number cyclic numbers, and specifically with 142857 as it is the smallest of such numbers.
13/07/09 My top 8 time-saving Firefox shortcuts This article presents my favorite top 8 time-saving shortcuts in Firefox 3.0 and Firefox 3.5. Get to know these and you'll be saving a lot of time. They have been ordered by "the element of most surprise"
20/05/09 Board Game Jungle speed / Arriba Review of the cool game "Jungle Speed" aka. "Arriba".
16/05/09 Danish Twin words "Twin words" are words that not only have multiple meanings, they must be composed next to each other in meaningful sentences. This article explores the concept of twin words.
Nothing of interest? Try browsing the entire article archive...