<!-- --><style type="text/css">@import url(https://www.blogger.com/static/v1/v-css/navbar/3334278262-classic.css); div.b-mobile {display:none;} </style> </head><body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d7256432\x26blogName\x3dThe+Frustrated+Programmer\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLACK\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttp://frustratedprogrammer.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://frustratedprogrammer.blogspot.com/\x26vt\x3d5012862196962223429', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>
| Friday, July 16, 2004

JSP precompilation is a good thing for a couple reasons:
-Better error checking - Errors can be caught at compile-time rather than run-time.
-Faster - Compiling pages is slow. Compiling pages during your build process means a user will never have to wait for a page to compile.

For our project, speed was one of the main drivers for implmenting precompiling. At our current stage we give a lot of demos and the project owners are forced to go through the entire application before the demo so it looks as fast as possible. This is kinda silly with the tools available, so we tried to fix it.

Tomcat's official documentation includes a detailed explanation of how to setup page precompiling, but it is missing a couple things.
-"Insert the ${webapp.path}/WEB-INF/generated_web.xml at the right place inside the ${webapp.path}/WEB-INF/web.xml file." - This is a little sparse for someone who doesn't know Ant well. This blog entry was a nice help.
-Precompiling has a disadvantage, if you change the JSP it won't automatically recompile the page. This isn't ideal for development so we need to make it conditional.


<target name="jspc">
<taskdef classname="org.apache.jasper.JspC" name="jasper2">
<classpath refid="compile.classpath">
</classpath>

<mkdir dir="${gen.path}/jspc">
<jasper2>
validateXml="false"
uriroot="${webapp.path}"
webXmlFragment="${webapp.path}/WEB-INF/generated_web.xml"
outputDir="${gen.path}/jspc" />
<loadfile propery="file" srcfile="${webapp.path}/WEB-INF/generated_web.xml">
<copy file="${webapp.path}/WEB-INF/web_tmpl.xml"
tofile="${webapp.path}/WEB-INF/web.xml" filtering="true" overwrite="true"/>
</target>

<target name="compile">
<mkdir dir="${webapp.path}/WEB-INF/classes">
<javac destdir="${src.path}:${gen.path}/jspc">
optimize="off"
debug="on" failonerror="false"
srcdir="${webapp.path}/WEB-INF/src"
classpathrefid="compile.classpath"
excludes="**/*.smap">
</javac>

<!-- Since we're not doing a page recompile at this time, lets just copy the web_templ.xml to web.xml. -->
<filter token="genarated_web.xml" value=""/>
<copy file="${webapp.path}/WEB-INF/web_tmpl.xml"
tofile="${webapp.path}/WEB-INF/web.xml" filtering="true" overwrite="true"/>
</target>

<target name="dist" depends="compile,jspc"/>


Things to note:
-You first need to copy web.xml to web_templ.xml and insert @generated_web.xml@ where you want the servlet definitions to go. You also need to add web_templ.xml to CVS and remove web.xml from CVS.
-During a normal development compile, no JSP compilation will occur and the web_templ.xml will just be copied over to web.xml.
-During a 'dist' build, page compiling will occur and the generated_web.xml from Jasper will be included in your web.xml.
-I copied the jasper related jars from CATALINA_HOME/common/lib to lib/build. This directory is included at compile time ONLY. It is not copied into my war for deployment. (It also contains things like the servlet api jar.)
-In the begining I still had the servlet 2.3 api jars in my lib/build directory. This caused the following error:
java.lang.NoSuchMethodError:

javax.servlet.jsp.tagext.TagAttributeInfo.(Ljava/lang/String;ZLjava/lang/String;ZZ)V
This email helped me track it down.

Next Step: Can you use these pages in weblogic by including the jasper-runtime.jar in WEB-INF/lib?