How to precompile JSPs with the WebLogic wlappc Ant task

The following Ant snippet allows you to precompile your JSPs (and more) for WebLogic Server.

<!-- Define some properties -->
<property name="weblogic.server.dir" value="C:/Oracle/Middleware"/>
<property name="weblogic.server.lib.dir" value="${weblogic.server.dir}/wlserver_10.3/server/lib"/>
<property name="pathTo.weblogic.jar" value="${weblogic.server.lib.dir}/weblogic.jar"/>
<property name="war.src.dir" value="${basedir}/build/war"/>
<property name="war.dist.dir" value="${basedir}/dist"/>

<!-- Add the WebLogic appc task definition to the current project -->
<taskdef name="wlappc" classname="weblogic.ant.taskdefs.j2ee.Appc" classpath="${pathTo.weblogic.jar}"/>

<!-- Set up the classpath for the WebLogic appc task -->
<path id="wlappc.classpath">
    ...
</path>

<!-- Compile the source of your WAR file with weblogic.appc -->
<target name="wlCompileWarSrc">
    <wlappc source="${war.src.dir}" classpathref="wlappc.classpath" keepgenerated="true"
            debug="true" linenumbers="true" verbose="true" verbosejavac="true"/>
</target>

<!-- Make the project WAR -->
<target name="war" depends="wlCompileWarSrc">
    ...
</target>

When you deploy a WAR file with non-precompiled JSPs, WebLogic Server compiles the JSPs the first time they are accessed. This might print a console message like “Recompiling JSP [...], resource [...], because it is stale.“.

For my current project, compiling the first page usually takes 15 to 90 seconds (we have over 20 tiles per page). This is too long a wait for the first users of the server (users, plural, because every user has to wait for the compilation to finish; at 15 users/sec this can be quite a lot). This also affects the speed of the Continuous Integration tests and your own tests on your local WebLogic Server.

Solution 1: precompile=true in weblogic.xml

You can have WebLogic Server automatically precompile all modified JSPs when the Web application is (re-)deployed or when starting the server by setting precompile=true in the weblogic.xml of your WAR:

<jsp-descriptor>
    <precompile>true</precompile>
</jsp-descriptor>

This is not too bad except that it still takes (a lot of) time at server startup-time and thus delays how quickly the server is usable.

Solution 2: use weblogic appc at build-time

A better solution is to compile your JSPs when you build you WAR.
Note that you should not use the deprecated weblogic.jspc but prefer weblogic.appc.

I could not find too much documentation about appc and the wlappc Ant task. This document describes appc itself, this page describes wlappc. There are no real examples for Ant though.

First, you need to add the WebLogic appc task definition to your build.xml:

<taskdef name="wlappc" 
         classname="weblogic.ant.taskdefs.j2ee.Appc" 
         classpath="${pathTo.weblogic.jar}"/>

Then you invoke it at the appropriate time, e.g. before or after creating a WAR:

<target name="wlCompileWarSrc">
    <wlappc source="${war.src.dir}" 
            classpathref="wlappc.classpath" 
            keepgenerated="true"
            debug="true" 
            linenumbers="true" 
            verbose="true" 
            verbosejavac="true"/>
</target>

You can feed appc and wlappc an EAR, WAR, or JAR file or a directory. I prefer a directory so that no time is lost zipping (ear, war, jar ant tasks), unzipping and zipping again (wlappc ant task).

Note that the JVM and WebLogic Server versions used for compiling need to be the same as the version you deploy on, otherwise the server recompiles the JSPs again.

Appc does more than just compile your JSPs, it also validates your descriptors. Here is a typical wlappc output:

wlappc
[JspcInvoker]Checking web app for compliance.
[ComplianceChecker] Validating the servlet element with servlet-name named "...".
...
[ComplianceChecker] Checking servlet-mapping for servlet name : "...".
...
[ComplianceChecker] Checking filter-mapping with filter-name "...".
...
[jspc] Overriding descriptor option 'keepgenerated' with value specified on command-line 'true' 
[jspc]  -webapp specified, searching . for JSPs
[jspc] Compiling /....jsp
...
Compilation completed successfully

Comments are closed.