Self-signed JAR signing with Maven for webstart – without the keystore
Anyone reading the above title will have serious doubts about the validity of this article. But let me explain. Mind you, this is an article for development purposes, for production you'll probably need to have a keystore with a properly signed SSL certificate (then again, most webstart applications are intranet, so why bother).
That the Maven Webstart plugin hosted by Codehaus is ill-documented is a well known fact. However, as with most Maven-related subjects, you can learn a whole lot about its workings by looking at the code, or the examples if they are provided.
A beginner will read the plugin documentation, and then start fidgeting with the Java keytool utility to get the keystore needed for jar signing. Needless to say, the keytool utility isn't the easiest one of the lot. Probably after about half an hour you'll have a decent enough keystore, going through about every function of the keytool command-line. Then he'll utilize the keystore in the plugin (preferably using a relative path).
Why the Codehaus guys haven't mentioned the easier way on the plugin's website is beyond me, but here it is:
<plugin>
<groupId>org.codehaus.mojo.webstart</groupId>
<artifactId>webstart-maven-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>jnlp-download-servlet</goal>
</goals>
</execution>
</executions>
<configuration>
<outputDirectoryName>webstart</outputDirectoryName>
<excludeTransitive>false</excludeTransitive>
<jnlpFiles>
<jnlpFile>
<templateFilename>template.vm</templateFilename>
<outputFilename>myapp.jnlp</outputFilename>
<jarResources>
<jarResource>
<groupId>be.insaneprogramming</groupId>
<artifactId>myapp-gui</artifactId>
<version>${project.version}</version>
<mainClass>be.insaneprogramming.myapp.GUIMain</mainClass>
</jarResource>
</jarResources>
</jnlpFile>
</jnlpFiles>
<sign>
<keystore>/tmp/myappkeystore</keystore>
<keypass>m2m2m2</keypass>
<storepass>m2m2m2</storepass>
<alias>foobar</alias>
<validity>3650</validity>
<dnameCn>Insane Programming</dnameCn>
<dnameOu>Software Development</dnameOu>
<dnameO>Insane Programming</dnameO>
<dnameL>Maldegem</dnameL>
<dnameSt>Oost-Vlaanderen</dnameSt>
<dnameC>BE</dnameC>
<verify>false</verify>
<keystoreConfig>
<delete>true</delete>
<gen>true</gen>
</keystoreConfig>
</sign>
<outputJarVersions>true</outputJarVersions>
<verbose>true</verbose>
<unsign>true</unsign>
<verifyjar>false</verifyjar>
</configuration>
</plugin>
This configuration will create a keystore on the fly and use that one for the signing. The advantage?
- No keystore is needed in the project sourcetree or in a shared location
- No more messing around with the keytool
- Signing information is kept in the POM
- You can reuse information in the POM for the signing (organisation name etc.), or even use Maven properties and profiles to customize the signing without having to resort to multiple keystore or a keystore with multiple aliases.
For example you could do this in the signing configuration:... <validity>${signing.validity}</validity> <dnameCn>${signing.dname.cn}</dnameCn> <dnameOu>${signing.dname.ou}</dnameOu> <dnameO>${signing.dname.o}</dnameO> <dnameL>${signing.dname.l}</dnameL> <dnameSt>${signing.dname.st}</dnameSt> <dnameC>${signing.dname.c}</dnameC> ...where the placeholder information is kept in the company super POM. A lot easier to maintain, I reckon.
- The signature will always be valid when signing (no need to replace keystore to remove warnings)