JSP Precompilation for ADF Applications
- by Duncan Mills
A question that comes up from time to time, particularly in relation to build automation, is how to best pre-compile the .jspx and .jsff files in an ADF application. Thus ensuring that the app is ready to run as soon as it's installed into WebLogic. In the normal run of things, the first poor soul to hit a page pays the price and has to wait a little whilst the JSP is compiled into a servlet. Everyone else subsequently gets a free lunch. So it's a reasonable thing to want to do...
Let Me List the Ways
So forth to Google (other search engines are available)... which lead me to a fairly old article on WLDJ - Removing Performance Bottlenecks Through JSP Precompilation. Technololgy wise, it's somewhat out of date, but the one good point that it made is that it's really not very useful to try and use the precompile option in the weblogic.xml file. That's a really good observation - particularly if you're trying to integrate a pre-compile step into a Hudson Continuous Integration process. That same article mentioned an alternative approach for programmatic pre-compilation using weblogic.jspc. This seemed like a much more useful approach for a CI environment. However, weblogic.jspc is now obsoleted by weblogic.appc so we'll use that instead. Thanks to Steve for the pointer there.
And So To APPC
APPC has documentation - always a great place to start, and supports usage both from Ant via the wlappc task and from the command line using the weblogic.appc command. In my testing I took the latter approach.
Usage, as the documentation will show you, is superficially pretty simple. The nice thing here, is that you can pass an existing EAR file (generated of course using OJDeploy) and that EAR will be updated in place with the freshly compiled servlet classes created from the JSPs. Appc takes care of all the unpacking, compiling and re-packing of the EAR for you. Neat.
So we're done right...? Not quite.
The Devil is in the Detail
OK so I'm being overly dramatic but it's not all plain sailing, so here's a short guide to using weblogic.appc to compile a simple ADF application without pain.
Information You'll Need
The following is based on the assumption that you have a stand-alone WLS install with the Application Development Runtime installed and a suitable ADF enabled domain created. This could of course all be run off of a JDeveloper install as well
1. Your Weblogic home directory. Everything you need is relative to this so make a note. In my case it's c:\builds\wls_ps4.
2. Next deploy your EAR as normal and have a peek inside it using your favourite zip management tool. First of all look at the weblogic-application.xml inside the EAR /META-INF directory. Have a look for any library references. Something like this:
<library-ref>
<library-name>adf.oracle.domain</library-name>
</library-ref>
Make a note of the library ref (adf.oracle.domain in this case) , you'll need that in a second.
3. Next open the nested WAR file within the EAR and then have a peek inside the weblogic.xml file in the /WEB-INF directory. Again make a note of the library references.
4. Now start the WebLogic as per normal and run the WebLogic console app (e.g. http://localhost:7001/console). In the Domain Structure navigator, select Deployments.
5. For each of the libraries you noted down drill into the library definition and make a note of the .war, .ear or .jar that defines the library. For example, in my case adf.oracle.domain maps to "C:\ builds\ WLS_PS4\ oracle_common\ modules\ oracle. adf. model_11. 1. 1\ adf. oracle. domain. ear". Note the extra spaces that are salted throughout this string as it is displayed in the console - just to make it annoying, you'll have to strip these out.
6. Finally you'll need the location of the adfsharebean.jar. We need to pass this on the classpath for APPC so that the ADFConfigLifeCycleCallBack listener can be found. In a more complex app of your own you may need additional classpath entries as well.
Now we're ready to go, and it's a simple matter of applying the information we have gathered into the relevant command line arguments for the utility
A Simple CMD File to Run APPC
Here's the stub .cmd file I'm using on Windows to run this.
@echo offREM Stub weblogic.appc Runner
setlocal
set WLS_HOME=C:\builds\WLS_PS4
set ADF_LIB_ROOT=%WLS_HOME%\oracle_common\modulesset COMMON_LIB_ROOT=%WLS_HOME%\wlserver_10.3\common\deployable-libraries
set ADF_WEBAPP=%ADF_LIB_ROOT%\oracle.adf.view_11.1.1\adf.oracle.domain.webapp.war
set ADF_DOMAIN=%ADF_LIB_ROOT%\oracle.adf.model_11.1.1\adf.oracle.domain.ear
set JSTL=%COMMON_LIB_ROOT%\jstl-1.2.war
set JSF=%COMMON_LIB_ROOT%\jsf-1.2.war
set ADF_SHARE=%ADF_LIB_ROOT%\oracle.adf.share_11.1.1\adfsharembean.jar
REM Set up the WebLogic Environment so appc can be found
call %WLS_HOME%\wlserver_10.3\server\bin\setWLSEnv.cmd
CLS
REM Now compile away!java weblogic.appc -verbose -library %ADF_WEBAPP%,%ADF_DOMAIN%,%JSTL%,%JSF% -classpath %ADF_SHARE% %1
endlocal
Running the above on a target ADF .ear file will zip through and create all of the relevant compiled classes inside your nested .war file in the \WEB-INF\classes\jsp_servlet\ directory (but don't take my word for it, run it and take a look!)
And So...
In the immortal words of the Pet Shop Boys, Was It Worth It? Well, here's where you'll have to do your own testing. In my case here, with a simple ADF application, pre-compilation shaved an non-scientific "3 Elephants" off of the initial page load time for the first access of each page. That's a pretty significant payback for such a simple step to add into your CI process, so why not give it a go.