Looking for Webstart Maven Plugin sample application

Ralph picture Ralph · Mar 4, 2011 · Viewed 12.3k times · Source

I am looking for source code for a complete application that uses the Webstart Maven Plugin.

Any ideas?

Answer

Jörn Horstmann picture Jörn Horstmann · Mar 7, 2011

I tried the webstart plugin in a prrof of concept involving an embedded tomcat server. The plugin is bound to the package phase and takes a longtime to execute, I would recommend to invoke it manually from the command line. It generates a zip file in the target directory containing the jnlp file and all dependencies. This file can then be extraced and put on a webserver. The url in the pom should point to this path on the server. When started, the app runs a tomcat server on localhost port 8080 with a simple servlet that just returns the requested path as a string.

Let me know if this works for you.

Here is the pom of the project, the plugin configuration was mostly copied from the documentation here

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.jhorstmann</groupId>
    <artifactId>EmbeddedTomcatWebstart</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>EmbeddedTomcatWebstart</name>
    <url>http://localhost/jnlp/</url>
    <organization>
        <name>Organisation</name>
    </organization>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <tomcat.version>7.0.6</tomcat.version>
    </properties>
    <repositories>
        <repository>
            <id>jboss</id>
            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
        </repository>
        <repository>
            <id>sonatype</id>
            <url>http://oss.sonatype.org/content/repositories/releases/</url>
        </repository>
    </repositories>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.3.1</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>net.jhorstmann.embeddedtomcat7.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo.webstart</groupId>
                <artifactId>webstart-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <!-- bind to phase, I prefer to call it manualls -->
                        <phase>package</phase>
                        <goals>
                            <goal>jnlp-inline</goal> <!-- use jnlp, jnlp-inline or jnlp-single as appropriate -->
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <!--outputDirectory></outputDirectory--> <!-- not required?? -->

                    <!-- Set to true to exclude all transitive dependencies. Default is false. -->
                    <excludeTransitive>false</excludeTransitive>

                    <!-- The path where the libraries are stored within the jnlp structure. not required. by default the libraries are within the working directory -->
                    <libPath>lib</libPath>
                    <outputJarVersions>true</outputJarVersions>
                    <!-- [optional] transitive dependencies filter - if omitted, all transitive dependencies are included -->
                    <dependencies>
                        <!-- Note that only groupId and artifactId must be specified here. because of a limitation of the Include/ExcludesArtifactFilter -->
                        <!--
                        <includes>
                            <include>commons-logging:commons-logging</include>
                            <include>commons-cli:commons-cli</include>
                        </includes>
                        -->
                        <!--
                        <excludes>
                            <exclude></exclude>
                        <excludes>
                        -->
                    </dependencies>

                    <!--
                    <resourcesDirectory>${project.basedir}/src/main/jnlp/resources</resourcesDirectory>
                    -->
                    <!-- default value -->

                    <!-- JNLP generation -->
                    <jnlp>
                        <!-- default values -->
                        <!--inputTemplateResourcePath>${project.basedir}</inputTemplateResourcePath-->
                        <!--inputTemplate>src/main/jnlp/template.vm</inputTemplate--> <!-- relative to inputTemplateResourcePath -->
                        <outputFile>app.jnlp</outputFile> <!-- defaults to launch.jnlp -->

                        <!-- used to automatically identify the jar containing the main class. -->
                        <!-- this is perhaps going to change -->
                        <mainClass>net.jhorstmann.embeddedtomcat7.App</mainClass>
                    </jnlp>


                    <!-- SIGNING -->
                    <!-- defining this will automatically sign the jar and its dependencies, if necessary -->
                    <sign>
                        <keystore>${basedir}/keystore</keystore>
                        <keypass>password</keypass>  <!-- we need to override passwords easily from the command line. ${keypass} -->
                        <storepass>password</storepass> <!-- ${storepass} -->
                        <!--storetype>fillme</storetype-->
                        <alias>EmbeddedTomcatWebstart</alias>

                        <!--validity>fillme</validity-->

                        <!-- only required for generating the keystore -->
                        <dnameCn>EmbeddedTomcatWebstart</dnameCn>
                        <dnameOu>Organisation Unit</dnameOu>
                        <dnameO>Organisation</dnameO>
                        <dnameL>Location</dnameL>
                        <dnameSt>State</dnameSt>
                        <dnameC>Country</dnameC>

                        <verify>true</verify> <!-- verify that the signing operation succeeded -->

                        <!-- KEYSTORE MANAGEMENT -->
                        <keystoreConfig>
                            <delete>true</delete> <!-- delete the keystore -->
                            <gen>true</gen>       <!-- optional shortcut to generate the store. -->
                        </keystoreConfig>
                    </sign>

                    <!-- BUILDING PROCESS -->

                    <pack200>true</pack200>
                    <gzip>true</gzip> <!-- default force when pack200 false, true when pack200 selected ?? -->

                    <!-- causes a version attribute to be output in each jar resource element, optional, default is false -->
                    <outputJarVersions>false</outputJarVersions>

                    <!--install>false</install--> <!-- not yet supported -->
                    <verbose>true</verbose>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-catalina</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-coyote</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
    </dependencies>
</project>

Here is a custom template for the jnlp file placed at src/main/jnlp/template.vm, I can't remember why I needed that exactly:

<?xml version="1.0" encoding="utf-8"?>
<jnlp
    spec="$jnlpspec"
    codebase="$project.Url"
    href="$outputFile">
  <information>
    <title>$project.Name</title>
    <vendor>$project.Organization.Name</vendor>
    <homepage href="$project.Url"/>
    <description>$project.Description</description>
#if($offlineAllowed)
    <offline-allowed/>
#end
  </information>
#if($allPermissions)
  <security>
     <all-permissions/>
  </security>
#end
  <resources>
    <j2se version="$j2seVersion"/>
     $dependencies
  </resources>
  <application-desc main-class="$mainClass"/>
</jnlp>

This is the main class at src/main/java/net/jhorstmann/embeddedtomcat7/App.java

package net.jhorstmann.embeddedtomcat7;

import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Wrapper;
import org.apache.catalina.startup.Tomcat;

public class App {

    public static void main(String[] args) throws LifecycleException, ServletException, IOException {
        File tmpDir = new File(System.getProperty("java.io.tmpdir"));
        File webappDir = new File(tmpDir, "embeddedtomcat7");
        webappDir.mkdir();

        final Tomcat tomcat = new Tomcat();
        tomcat.setPort(8080);
        tomcat.setBaseDir(tmpDir.getAbsolutePath());
        tomcat.getConnector().setURIEncoding("UTF-8");

        String contextPath = "/";

        Context context = tomcat.addContext(contextPath, webappDir.getAbsolutePath());
        Wrapper wrapper = tomcat.addServlet(contextPath, "Test", new TestServlet());
        //Wrapper wrapper = tomcat.addServlet(contextPath, "Async", new AsyncServlet());
        //wrapper.setAsyncSupported(true);

        wrapper.addMapping("/*");

        tomcat.start();

        tomcat.getServer().await();
    }
}

And finally a servlet at src/main/java/net/jhorstmann/embeddedtomcat7/TestServlet.java

package net.jhorstmann.embeddedtomcat7;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.println("<h1>" + req.getPathInfo() + "</h1>");
        writer.close();
    }
}