Sunday, September 18, 2011

How to use pre-compiled JSPs in a webapp with tomcat 7

Problem:
Recently I had the following requirement:

I had a webapp that has some jsp files which directly call some methods in some libraries. But those libraries are in a sandbox environment secured by Java Security Manager. Therefore only the calls that come from classes that are signed by a particular key, are allowed to be executed.

My webapp was not working until I guarantee the sandbox environment that the method calls are coming from a signed source.

Solution:
The solution for the above problem is consisted with following steps:
1. Pre-compile jsp files.
2. Package the pre compiled jsp files into a jar file.
3. Sign the jar file using the appropriate key.
4. Package the signed jar file in the WEB-INF/lib folder of the webapp
5. Remove all the jsp files from the webapp.

Walk through:
jspc-maven-plugin comes to the rescue in this occasion.

I will walk you through how to pre-compile jsp files of the example webapp of WSO2 AppServer by integrating pre-compiling step into the maven pom.xml.

Following is the complete pom.xml file with modifications to include the steps of pre-compiling and packaging the jsp files.

    
        org.wso2.appserver
        wso2appserver-samples-parent
        4.1.1
        ../../pom.xml
    

    4.0.0
    
    example
    war
    WSO2 AS - Example webapp

    
        
            org.wso2.carbon
            org.wso2.carbon.tomcat
            ${carbon.platform.version}
        
        
            org.apache.axis2.wso2
            axis2-client
            ${axis2.osgi.version}
        
        
            org.wso2.carbon
            org.wso2.carbon.authenticator.proxy
            ${carbon.platform.version}
        
        
            org.wso2.carbon
            org.wso2.carbon.authenticator.stub
            ${carbon.platform.version}
        
        
            org.wso2.carbon
            org.wso2.carbon.core.common
            ${carbon.platform.version}
        
        
            org.wso2.carbon
            org.wso2.carbon.core
        

        
            org.apache.axis2.wso2
            axis2
        
    

    
        
            
                org.codehaus.mojo
                build-helper-maven-plugin
                
                    
                        add-source
                        generate-sources
                        
                            add-source
                        
                        
                            
                                target/generated-code/src
                            
                        
                    
                
            

            
                org.codehaus.mojo.jspc
                jspc-maven-plugin
                
                    
                        
                            compile
                        
                    
                
                
                    ${pom.basedir}/src/main/resources/WEB-INF/web.xml
                    1.5
                    1.5
                    
                        ${pom.basedir}/src/main/resources
                        
                            **/*.jsp
                        
                    
                
                
                
                
                    
                        org.codehaus.mojo.jspc
                        jspc-compiler-tomcat6
                        2.0-alpha-3
                        
                        
                            
                                org.apache.tomcat
                                jasper
                            
                            
                                org.apache.tomcat
                                jasper-el
                            
                            
                                org.apache.tomcat
                                jasper-jdt
                            
                            
                                org.apache.tomcat
                                servlet-api
                            
                            
                                org.apache.tomcat
                                jsp-api
                            
                            
                                org.apache.tomcat
                                el-api
                            
                            
                                org.apache.tomcat
                                annotations-api
                            
                        
                    
                    
                    
                        org.apache.tomcat
                        tomcat-jasper
                        7.0.12
                    
                    
                    
                        org.eclipse.jdt.core.compiler
                        ecj
                        3.5.1
                    
                
            

            
                org.apache.maven.plugins
                maven-compiler-plugin
                
                    1.5
                    1.5
                
            
            
            
                org.apache.maven.plugins
                maven-war-plugin
                2.1-beta-1
                
                    example
                    
                        WEB-INF/classes/**,
                        WEB-INF/*,
                        WEB-INF/jsp/*,
                        WEB-INF/jsp2/*,
                        WEB-INF/lib/jstl.jar,
                        WEB-INF/lib/standard.jar,
                        WEB-INF/lib/jsp.jar,
                        **/axis2-client*.jar,
                        **/org.wso2.carbon.authenticator.proxy*.jar,
                        **/org.wso2.carbon.authenticator.stub*.jar,
                        **/org.wso2.carbon.core.common*.jar,
                        **/*.java,
                        **/tags/**,
                        **/servlets/**,
                        **/carbon/**,
                        **/*.class,
                        **/*.html,
                        jsp/images/*
                    
                    
                        
                            
                            src/main/resources
                        
                    
                    ${pom.basedir}/target/jspweb.xml
                
            
        
    


Following is what is done... please follow with the line numbers:

1. line 73 introduces jspc-maven-plugin to the pom.xml file.
This will compile jsp files to servlets and then into .class files which include the byte code. These can be found under "target/jsp-source" once the maven build succeeds.

2. Note the 'Configuration' element from line 83 to 93:
    - inputwebxml: specify where the original web.xml file of the webapp resides. jspc-maven-plugin will detect that and update the servlet mappings according to the compiled jsp files and create a new file called "jspweb.xml" in the target folder, which you need to package with the webapp instead of the original web.xml.
    - sources: specify where the jsp files resides in your webapp .

3. Then comes the trick: there is no jspc-maven-compiler plugin for tomcat 7 yet. So we need to use tomcat 6 version of it by removing the incompatibilities. This is what is done from line 97 to line 147.

4. As in line 190, you need to specify the new web.xml created by this plugin, to be included in the .war file of the webapp.

5. Now the step 1 mentioned in the above 'solution' section is achieved and the files obtained by pre-compiling jsp files are available in 'target/jsp-source' folder.

Now, in order to complete steps from 2-4 in the above 'solution', you may need to write a ant build.xml file or can integrate those steps into the pom.xml file itself. I did it through a ant build.xml file.

You can use jarsigner tool that comes with JDK installation  to sign the jar file containing the compiled jsps, as described here.

Once you include the compiled jsps in a jar file in the webapp, you need to remove the original jsp files from the webapp or avoid packaging them in the .war file because if they are included, those will be compiled and used by the servlet container instead of the already pre-compiled ones.

In my case, I had to remove the jsp files packaged inside web-inf/classes/carbon
and web-inf/classes/jsp/carbon of the webapp.

Hope this helps...

5 comments:

  1. Can you please tell me how I show codes such a way with line numbers and coloring and formatting? What is the technique, you are using?

    ReplyDelete
  2. Please refer to my previous blog post:
    http://hasini-gunasinghe.blogspot.com/2010/11/blogging-tips-embed-code-segments-in.html
    There I have mentioned some good references on how to get it done using Syntax Highlighter.

    ReplyDelete
  3. Hi Hasini ,

    Great blog! Is there an email address I could contact you in private?

    ReplyDelete
  4. I keep getting a jspc-maven-plugin 'compile': Unable to find the mojo???

    ReplyDelete
  5. Why are you using jspc-compiler-tomcat6 if you are attempting to compile for tomcat 7?

    ReplyDelete

Note: Only a member of this blog may post a comment.