Archive

Posts Tagged ‘Maven’

Patch Accepted

April 14, 2011 1 comment

Woo hoo! My patch to the maven-scala-plugin has been accepted!

That means that my GitHub pull request was accepted into the main repository. Users can get the fix by pulling down the code and building the plugin. The fix will be included in the next version of the plugin, which I will be sure to mention here!

Categories: code Tags: , ,

maven-scala-plugin

April 1, 2011 Leave a comment

Continuing from my last post: With the Scala script written, I wanted to integrate it into our Maven build as an optional step. But this didn’t go so well.

When running mvn scala:script with a link to my script file in the configured pom.xml, I got a Fatal Error. I also couldn’t get a simple helloWorld script to run, as a separate file or scripted right into the pom.xml file. This is the error I got:


[INFO] ------------------------------------------------------------------------
[ERROR] FATAL ERROR
[INFO] ------------------------------------------------------------------------
[INFO] scala/ScalaObject
scala.ScalaObject
[INFO] ------------------------------------------------------------------------
[INFO] Trace
java.lang.NoClassDefFoundError: scala/ScalaObject
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at org_scala_tools_maven.ScalaScriptMojo.runScript(ScalaScriptMojo.java:185)
at org_scala_tools_maven.ScalaScriptMojo.doExecute(ScalaScriptMojo.java:154)
at org_scala_tools_maven.ScalaMojoSupport.execute(ScalaMojoSupport.java:340)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:490)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:694)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:556)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:535)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)
at org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
Caused by: java.lang.ClassNotFoundException: scala.ScalaObject
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
... 33 more
[INFO] ------------------------------------------------------------------------

The maven-scala-plugin couldn’t even find the ScalaObject class, which is analagous to Java Object. Of course I googled the heck out of this error and found a few people suffering the same problem, but no one posted a solution. Then I found maven-scala-plugin’s repo on GitHub and discovered that this issue has been reported but not yet fixed. So I decided to download the source code and take a look.

Here’s what I found, in ScalaScriptMojo.java:

    private URLClassLoader createScriptClassloader(File scriptDir,
            Set<String> classpath) throws MalformedURLException {
        List<URL> urls = new ArrayList<URL>();

        // add the script directory to the classpath
        urls.add(scriptDir.toURI().toURL());

        for (String string : classpath) {
            urls.add(new URL("file://" + string));
        }

        URLClassLoader loader = new URLClassLoader(urls.toArray(new URL[urls
                .size()]), getClass().getClassLoader());
        return loader;
    }

That seemed like a pretty hinky way to me to send files to the URLClassLoader. The code that generates the Set of classpath Strings uses File.getCanonicalPath() to create the Strings. Thus they are platform-dependent Strings, and on a Windows box you can’t use them to create a valid File URL by prepending “file://” to them because the path separators are “\”. I assume that the plugin contributors are on Linux machines and couldn’t replicate the problem to fix it.

Like all the best bug fixes, this one was a one-liner:

for (String string : classpath) {
    urls.add(new File(string).toURI().toURL());
}

Now the URLs will be correct no matter what platform you’re on.

I forked the maven-scala-plugin repository on GitHub and checked in my fix. I was waiting to post this entry until my Pull Request was accepted by the repo owner, but I guess he is too busy working on other efforts. Until the request is accepted, please check out my forked repo.

Categories: code Tags: , ,

Maven & Eclipse

October 29, 2010 Leave a comment

Our project here uses Maven 2 to manage the dependencies and builds. I really like developing code in Eclipse, and I wanted to set up my Eclipse workspace easily from the existing Maven configuration.

The Maven Eclipse plugin makes that easy. Just run the following command:

mvn eclipse:eclipse

and the plugin generates the Eclipse project files, ready to be imported into your Eclipse workspace.

Well, that’s great and all, but when I tried it I saw this error:

[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Request to merge when 'filtering' is not identical. Original=source src/test: output=target/test-classes, include=[**/*.java], exclude=[], test=true, filtering=false, merging with=resource src/test: output=target/test-classes, include=[*.properties|*.xml], exclude=[**/*.java], test=true, filtering=true
[INFO] ------------------------------------------------------------------------

A Google search led me to this answer:
http://stackoverflow.com/questions/1397903/setting-project-for-eclipse-using-maven

Basically the problem is that something changed in the latest version of the Maven Eclipse plugin that prevents this from working with our Maven configuration.

The solution is to use the 2.6 version of the plugin instead.

mvn org.apache.maven.plugins:maven-eclipse-plugin:2.6:eclipse

Categories: code Tags: ,

keytool

October 28, 2010 Leave a comment

My most recent project, the Multimodal Operational Test Harness (OTH), is a thick Java Swing client used to gather biometrics and package them up into a properly formatted XML document. The Maven 2 build generates an uber jar including all the dependencies that can be run from the command line, but we also have a requirement to run as a WebStart application. It’s not generally required to digitally sign the software, but we have the requirement locally.

So here’s how I went about signing the OTH.

1) Generate the key pair and self-signed certificate.
I could have used the command line for this step, but instead I decided to use the Maven Keytool plugin.
Here’s a clip of the pom.xml file I created:

<pluginManagement>
	<plugins>
		<plugin>
			<groupId>org.codehaus.mojo</groupId>
			<artifactId>keytool-maven-plugin</artifactId>
			<executions>
				<execution>
					<phase>generate-resources</phase>
					<id>clean</id>
					<goals>
						<goal>clean</goal>
					</goals>
				</execution>
				<execution>
					<phase>generate-resources</phase>
					<id>genkey</id>
					<goals>
						<goal>genkey</goal>
					</goals>
				</execution>
			</executions>
			<configuration>
				<keystore>keystore.jks</keystore>
				<dname>cn=commonName, ou=organizationUnit, o=organizationName, c=countryCode</dname>
				<keypass>password</keypass>
				<storepass>password</storepass>
				<alias>OTH</alias>
				<keyalg>RSA</keyalg>
				<keysize>2048</keysize>
				<validity>3650</validity>
			</configuration>
		</plugin>
	</plugins>
</pluginManagement>

I know it’s not the best idea to put the passwords in the pom.xml file, but the security of this keystore isn’t very important and I wanted to allow other developers to access the keystore without needing to discover the password.

Take special note of the option. If you don’t specify this value, the default is only 90 days. 10 years is much better.

2) Instead of just relying on a self-signed certificate, I need to get my certificate signed by a Certificate Authority. To do that, I generate a certificate signing request (CSR) file.

keytool -certreq -alias oth -file oth.csr -keystore keystore.jks -v

3) I sent that through our security team to our Certificate Authority. They first sent me their root certificates. These have to be imported into our keystore before we can authtenticate the certificate reply.

keytool -importcert -file "rootcert.crt" -alias rootcert -trustcacerts -keystore keystore.jks -v

4) Then I receive my certificate reply from the certificate authority. Now I can import that into my keystore and my certificate is authenticated.

keytool -importcert -file "cert.txt" -trustcacerts -keystore keystore.jks -v

5) You can verify the contents of your keystore by running the following command:

keytool -list -keystore keystore.jks -v

6) Here’s the bit of Maven WebStart plugin configuration that uses the keystore to sign the war.

<plugin>
	<groupId>org.codehaus.mojo.webstart</groupId>
	<artifactId>webstart-maven-plugin</artifactId>
	<version>1.0-beta-1</version>
	<executions>
		<execution>
			<phase>compile</phase>
			<goals>
				<goal>jnlp-download-servlet</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<outputDirectory>src/webapp</outputDirectory>
		<excludeTransitive>true</excludeTransitive>
		<jnlpFiles>
			<jnlpFile>
				<templateFilename>jnlp_launch_template.vm</templateFilename>
				<outputFilename>oth.jnlp</outputFilename>
				<jarResources>
					<jarResource>
						<groupId>videology</groupId>
						<artifactId>videology-driver</artifactId>
						<version>1.0.0</version>
						<classifier>win32</classifier>
					</jarResource>
					...
				</jarResources>
			</jnlpFile>
		</jnlpFiles>
		<sign>
			<keystore>${project.basedir}/keystore.jks</keystore>
			<keypass>password</keypass>
			<storepass>password</storepass>
			<alias>OTH</alias>
			<verify>true</verify> <!-- verify that the signing operation succeeded -->
		</sign>
		<!-- BUILDING PROCESS -->
		<pack200>false</pack200>
		<gzip>false</gzip>
		<verbose>true</verbose>
		<outputJarVersions>true</outputJarVersions>
	</configuration>
</plugin>

Finally, here’s the URL of the documentation of the Java keytool tool.
http://download.oracle.com/javase/6/docs/technotes/tools/windows

Categories: code Tags: ,