2008-09-19

Using JSP Precompilation in WebLogic

Typically, when you deploy an application, WebLogic Server tries to precompile the JSPs of your application.

But why ? How is it sensed to work normally ? What does this mechanism offer ?

That's what I'm going to explain in this article.

 

How did it work before ?

Well the original schema is the following : you typically deploy your application to your application server.

Once it's deployed, the first user that accesses a JSP has to wait a little bit, the time the JSP got compiled (transformed into a servlet).

As you can see, there is a small problem here : the fact that the JSP is compiled when a user accesses it.

It implies that some users may have to experience a delay when requesting a page, that's not exactly the idea of a good quality of service ...

That's this issue the precompilation was designed to address.

 

How do I setup precompilation ?

Nowadays, almost all application servers use precompilation.

As written above, precompilation is a way to prevent first users from compiling pages and then wait for them to show up.

You may use precompilation before or during a deployment.

You've got several ways to do so :

Using the weblogic.appc tool (pre-deployment compilation)

One good practice is to take the precompilation step and remove it from the deployment process.

When I say remove, it doesn't mean that we're going to suppress it, but rather than we will reorder the process.

Note : You could also use weblogic.jspc but it's deprecated.

Execute the appc tool like :


image


You'll see that the size of the WAR has changed (initially 2k)


image


If we take a closer look at the content of the WAR, we see a new directory and a new file :


image


As you can see, a new object "__index.class" has been created in the jsp_servlet directory, under WEB-INF\classes.

Note : When using Workshop, you may precompile your JSP by just checking a box :


image


Using the default mechanism : weblogic.xml (during deployment)

The default behavior is to not compile JSPs. If you want to turn that feature on, you'll have to specify it in your DD weblogic.xml.

 

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app

xmlns:wls="http://www.bea.com/ns/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd

http://www.bea.com/ns/weblogic/weblogic-web-app http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd">
<wls:weblogic-version>10.3</wls:weblogic-version>
    <wls:context-root>JSP_Precompilation</wls:context-root>
    <wls:jsp-descriptor>
        <wls:precompile>true</wls:precompile>
        <wls:precompile-continue>true</wls:precompile-continue>
    </wls:jsp-descriptor>
</wls:weblogic-web-app>

Using the JSPClassServlet

You may also declare a servlet in your application that will take care of that task.

But the main con is the fact that you have to modify your application by adding extra components. To me, it's not a best practice.

But if you're interested in doing that : http://edocs.bea.com/wls/docs100/webapp/reference.html#wp73711

 

What's the difference when I precompile myself the JSP or when I let WebLogic do it ?

First of all, the deployment time :)

As the step of precompiling is doing prior to the deployment process, the latter is obviously shortened.

Second, in your directory tree, the location of your JSP won't be the same according to who does the precompilation job.

If you do it manually, compiled JSP will be located in the WEB-INF\classes directory of your WAR, as shown in the example with "weblogic.appc".


image


If you let WebLogic do it, it will be located (default) in the following tree (outside of the WAR), in the directory DOMAIN_HOME\servers\yourServer\tmp\_WL_user :


image


Or you may configure this directory by changing the attribute 'working-dir' in your weblogic.xml DD.

 

8 comments:

Pete said...

Something you must also do when pre-compiling outside the app server, is to make sure the JVM and app server where you are compiling is exactly the same as the version being deployed to.

If the app server detects a difference in versions, it will re-compile anyway.

I've spent lots of time looking at that problem!!

Maxence Button said...

Thanks Pete for that interesting comment !

==Slava said...

Thanks for useful post!

I have a more complicated issue, could you help me?

I have an apllication source code (very large amount of java files) and a lot of jsp files.

The issue is that: it is necessary to precompile some jsps and precompile all java files which jsp depends on.

So, I have not compiled jar files - all classes that are need for jsp I am to compile from source code.

I have no idea how can I do it, weblogic.appc does not compile source code.

Pete said...

All you need for the JSP's to compile with APPC is that all jar's that are used by the JSP's are available on the classpath when running APPC.

If you are talking about EJB classes - the same thing applies and APPC will use these.

Myself, I just compile the JSP code and let the app server worry about the EJB classes. Plain jar files don't compile with things like appc.

Pete

Maxence Button said...

Okay, Pete you proved to be the quickest to answer :)

@==Slava : I guess you're mixing up regular Java compilation & JSP/EJB precompilation.

http://download.oracle.com/docs/cd/E15051_01/wls/docs103/ejb/appc_ejbc.html

As Pete said, compile your Java code and make them available in the appc classpath, that should work fine.

Regards.

emeric said...

Thank you for that post. However, I just have an error at the end of the compilation. It tries to load a jar resource described in my persistence.xml and there is an error at this time:
file:/C:/Users/xxx/AppData/Local/Temp/appcgen_1350381687857/test.war/t32dgg/WEB-INF/classes/META-INF/persistence.xml [Location: Line: 11, C: 71]: The jar r
esource "WEB-INF/lib/my-jar-1.1.0.jar" cannot be loaded.

Can you help me?

emeric said...

Thank you for your post.
However I have an issue. At the end of the compilation, it tries to load a resource jar file described in my persistence.xml file:
file:/C:/Users/xxx/AppData/Local/Temp/appcgen_1350381687857/test.war/t32dgg/WEB-INF/classes/META-INF/persistence.xml [Location: Line: 11, C: 71]: The jar r
esource "WEB-INF/lib/my-jar-1.1.0.jar" cannot be loaded.

Can you help me?

Binh Nguyen said...

Thanks, nice tips