Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Precompile JSP's with Gradle

im trying to change our build process from Maven to Gradle (V 2.9). In Maven i was using precompiling for JSP's like this:

        <plugin>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-jspc-maven-plugin</artifactId>
            <version>9.2.7.v20150116</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <id>jspc</id>
                    <goals>
                        <goal>jspc</goal>
                    </goals>
                    <configuration>
                        <excludes>**\/*inc_page_bottom.jsp,**\/*inc_page_top.jsp</excludes>
                        <includes>**\/*.jsp</includes>
                    </configuration>
                </execution>
            </executions>
        </plugin>

and it was working fine. Now im trying to find a way to do the same with gradle. I've found some informations/build.gradle examples but nothing was working really. Im currently using Tomcat 7 as servlet container and im planning to switch in some weeks to 8. Would be perfect of course to compile them for the target servlet container but first of all i would be happy to precompile them at all like i was doing this with maven for/with jetty.

A part of my current build.gradle which gives me a error:

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.bmuschko:gradle-tomcat-plugin:2.2.4'
    }
}

apply plugin: 'com.bmuschko.tomcat'

tomcat {
    jasper {
        validateXml = true
        errorOnUseBeanInvalidClassAttribute = false
        compilerSourceVM = "1.8"
        compilerTargetVM = "1.8"
    }
}

task compileJsps(type: JavaCompile, dependsOn: 'clean') {
    dependsOn tomcatJasper
    group = 'build'
    description = 'Translates and compiles JSPs'
    classpath = configurations.tomcat + sourceSets.main.output + sourceSets.main.runtimeClasspath
    sourceCompatibility = "1.8"
    targetCompatibility = "1.8"
    destinationDir = file("$buildDir/jasper-classes")
    sourceSets {
        main {
            java {
                srcDir "$buildDir/jasper"
            }
        }
    }
}

dependencies {
    def tomcatVersion = '7.0.59'
    tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
       "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",
       "org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}"
}

Im getting the following error:

:tomcatJasper FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':tomcatJasper'.
> org.apache.jasper.JasperException: file:/xxx/xxx/xxx/xxx/src/main/webapp/index.jsp (line: 6, column: 0) The value for the useBean class attribute xxx.xxx.xxx.XxxXxx is invalid.

Running this jsp's in Tomcat 7 works fine... Does anybody have a up to date howto or a hint?

like image 714
StephanM Avatar asked Dec 18 '15 11:12

StephanM


People also ask

How do I enable debugging in gradle?

To do that, just pick the Gradle Remote Debug configuration and then click the Debug icon on the project to be debugged. For more info, you can read the Gradle documentation.

How do I Precompile a JSP file?

To select precompilation, right-click the EAR or WAR file you wish to export and select Export > EAR file or Export > WAR file. In the Export dialog, select the checkbox Pre-compile JSP.

What is gradle compile?

Compile − The dependencies required to compile the production source of the project. Runtime − The dependencies required by the production classes at runtime. By default, it also includes the compile time dependencies. Test Compile − The dependencies required to compile the test source of the project.


2 Answers

With gradle, you can call the JSPC compiler directly. That way it's explicit as to what is going on. We're using something like the following.

A couple of things to note.

  1. The JSPC compiler has a dependency on Ant, so that needs to be added to the classpath
  2. The JSPC compiler uses log4j, so we create a properties file to output some basic logging
  3. The JSPC compiler is embedded within Jetty, which is a "providedCompile" dependency, hence on our runtime classpath.

Anyway, our gradle looks similar to;

configurations {
    jspc
}

dependencies {
    jspc 'org.apache.tomcat:tomcat-jasper:9.0.17'
    jspc 'org.apache.ant:ant:1.10.1'

}

def jspSrc = "$projectDir/src/main/webapp"
def jspJavaSrc = "$buildDir/jsp-java-source"
def jspPackage = "com.example.jsp"

task writeJspcProperties(type: WriteProperties) {
    outputFile = "$buildDir/log4j.jspc.properties"
    property('log4j.rootLogger', 'WARN, stdout')
    property('log4j.logger.org.apache', 'INFO, stdout')
    property('log4j.appender.stdout', 'org.apache.log4j.ConsoleAppender')
    property('log4j.appender.stdout.Target', 'System.out')
    property('log4j.appender.stdout.layout', 'org.apache.log4j.PatternLayout')
    property('log4j.appender.stdout.layout.ConversionPattern', '%d [%C] %m%n')
}

task jspToJava(type: JavaExec, dependsOn: [compileJava, writeJspcProperties]) {

    inputs.dir jspSrc
    outputs.dir jspJavaSrc

    File xmlPartial = file("$jspJavaSrc/WEB-INF/web.xml.partial")

    doFirst {
        // Create the target WEB-INF folder so the JspC can create the web.xml.partial
        File webInfFolder = xmlPartial.getParentFile()
        if (!webInfFolder.exists()) {
            webInfFolder.mkdirs()
        }
    }

    classpath = configurations.jspc + sourceSets.main.runtimeClasspath
    main = 'org.apache.jasper.JspC'
    jvmArgs "-Dlog4j.configuration=file:$buildDir/log4j.jspc.properties"

    args '-webapp', jspSrc,
            '-d', jspJavaSrc,
            '-p', jspPackage,
            '-webxmlencoding', 'UTF-8',
            '-webinc', xmlPartial.absolutePath

    doLast {
        // Merge the partial XML with the original
        String originalXML = file("$jspSrc/WEB-INF/web.xml").text
        String xmlToMerge = xmlPartial.text
        String mergedXML = originalXML.replaceFirst('(?s)(<web-app.*?>)', '$1' + xmlToMerge)
        file("$jspJavaSrc/WEB-INF/web.xml").text = mergedXML
    }
}

[Edit; greatly simplified the JSP compilation]

[Edit 2; explicitly add the tomcat-jasper dependency]

like image 134
gdt Avatar answered Sep 26 '22 20:09

gdt


In your main build.gradle at the bottom do

apply from: 'jspc.gradle'

Then your jspc.gradle file looks like:

buildscript {  
    repositories {  
       jcenter()  
    }  


    dependencies {  
        classpath 'com.bmuschko:gradle-tomcat-plugin:2.2.5'  
    }  
}  

apply plugin: com.bmuschko.gradle.tomcat.TomcatPlugin 
apply plugin: 'java'

dependencies {
   def tomcatVersion = '8.0.42'  
    tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",  
           "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",  
           "org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}",  
           "javax.servlet:jstl:1.2"  

    providedCompile "javax.servlet:servlet-api:2.5"  

}

then to use the precompile do:

gradle tomcatJasper
like image 34
Fresh Codemonger Avatar answered Sep 22 '22 20:09

Fresh Codemonger