Sunday, January 13, 2013

Generating Java Web Start files using Gradle

Source Code: Example.

Problem

We have a Java Swing program and we need to create the files needed to use webstart in order to execute our program.

Solution

We have to follow the next steps:

Generate the key file

Using the keytool.exe program that is in "\bin" we will generate the key using:

keytool -genkey -alias http://www.anotes.org -keystore D:/temp/anotes.keys

Next to this we have to answer all the questions; at the end the file "anotes.keys" will have been generated

We have to copy this file to: "\src\jnlp\keys"

Create the graddle tasks

We need to do the following tasks:

  • Generate the jar of the project
  • Collect all jars and copy to specific directory
  • Sign all jars
  • Generate the jnlp files
  • Create the public task that will do all the process

Generate the jar of the project

Gradle has the "jar" task to do this.

Collect all jars and copy to specific directory

We have to create the following gradle task:

task copyFiles(type: Copy, dependsOn: [jar]) {
    from configurations.runtime
    from("build/libs")
    into("webstart/lib")
    include('*.jar')
}

In essence we are copying all jars ('*.jar') from both "configurations.runtime" (all dependent jars) and "build/libs" (all project jars) to "webstart/lib"

Sign all jars

We have to create the following gradle task:

task signAll(dependsOn: [copyFiles]) << {
    new File('webstart/signed').mkdirs()
    def libFiles = files { file('webstart/lib').listFiles() }
    libFiles.each {
        ant.signjar(
                destDir: 'webstart/signed',
                alias: 'http://www.anotes.org',
                jar: it,
                keystore: 'src/jnlp/keys/anotes.keys',
                storepass: 'anotes123',
                preservelastmodified: 'true')
    }
}

This task make the following:

  • Create directory "webstart/signed"
  • Sign all files that are in "webstart/lib" and put these ones in "webstart/signed". To do the signing the file "anotes.keys" is used.

Generate the jnlp files

We have to create the following task:

task generateJnlp(dependsOn: [signAll]) << {
    File jnlpTemplateFile = new File('src/jnlp/template/template.vm')
    def root = new XmlParser().parse(jnlpTemplateFile)
    def jnlpFileName = "gradle-webstart-example-${version}.jnlp"
    // Setting values in the jnlp template
    // Setting root values
    // File CodeBase
    // root.@codebase = 'file:/'+new File('webstart/signed').absolutePath
    // Http CodeBase
    root.@codebase = 'https://dl.dropbox.com/u/24028482/jnlp/gradle-webstart-example'
    root.@href = jnlpFileName
    // Setting information values
    def information = root.information[0]
    def title = information.title[0]
    def vendor = information.vendor[0]
    title.setValue("Gradle Webstart example")
    vendor.setValue("ANotes")
    def descriptionList = information.description
    descriptionList.each {
        it.setValue("Simple example of generating webstart files using gradle")
    }
    // Setting resources
    def resource = root.resources[0]
    def j2se = resource.j2se[0]
    j2se.@version = "1.6+"
    def collection = files { file('webstart/lib').listFiles() }
    def mainJar = "gradle-webstart-example-${version}.jar"
    collection.each {
        def resourceValues = [href: it.name]
        if (mainJar == it.name) {
            resourceValues = [href: it.name, main: 'true']
        }
        resource.appendNode('jar', resourceValues)
    }
    // Setting the main class
    def applicationDesc = root.'application-desc'[0]
    applicationDesc.'@main-class' = "org.anotes.example.gradlewebstart.MainApp"
    // Writing the jnlp file filled
    File jnlpFile = new File('webstart/signed/' + jnlpFileName)
    new XmlNodePrinter(new PrintWriter(jnlpFile)).print(root)
}

This task make the following:

  • Load the jnlp template from "src/jnlp/template/template.vm" using the XmlParser; that will facilitate the operations of reading and writing of the xml.
  • Setting values in the jnlp template

    • Setting codebase. If you want to use local file system uncomment the following:

      // File CodeBase    
      //root.@codebase = 'file:/'+new File('webstart/signed').absolutePath
      

      If you want to use url reference mantain the following (change the url for your specific path):

      // Http CodeBase
      root.@codebase = 'https://dl.dropbox.com/u/24028482/jnlp/gradle-webstart-example'
      
    • Setting information values

    • Setting resources - Write all the jar names, put "main=true" to the project jar
    • Setting the main Class
  • Save the new xml to:webstart/signed/gradle-webstart-example-1.jnlp"

Create the public task that will do all the process

task generateWebStartFiles (dependsOn: [generateJnlp])<< {
    println("Generating all webstart files in:webstart/signed")
}

From the command line you have to execute the following:

gradle generateWebStartFiles

and all the webstart files will be in: "webstart/signed/"

1 comments:

Jason Zwolak said...

Try using "$buildDir/libs" instead of "build/libs"... it's more robust to changes in the location of the build dir.

Post a Comment