Programmers' Pain
2Feb/110

Things you shouldn’t do #1: Recursive Maven Builds

Recursion - You gotta know when to stopToday I've found a new way to kill the resources of my development PC via doing recursive Maven builds. Yes, recursive! Why? Because I can and it's fun! It started with an pretty old part of a Maven build which used Python scripts to compile Java classes outside of the Maven artefact scope. Those classes are than used to launch a little helper JVM which resolves the used annotations of a class you've passed to stdin and prints the annotations class name to stdout. You know, the usual stuff you do in case the used Java decompiler doesn't support Java annotations. It all started with a Maven project which did call a Python script...


<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/maven-v4_0_0.xsd"
>
	<modelVersion>4.0.0</modelVersion>
	<groupId>build</groupId>
	<artifactId>build</artifactId>
	<version>1.0-SNAPSHOT</version>
	<name>build</name>
	<packaging>jar</packaging>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-antrun-plugin</artifactId>
				<executions>
					<execution>
						<phase>install</phase>
						<configuration>
							<tasks>
								<exec executable="python" failonerror="true">
									<arg value="src/main/python/callChildBuild.py" />
								</exec>
							</tasks>
						</configuration>
						<goals>
							<goal>run</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

This Python script did contain some direct javac calls to compile classes and a bunch of other resources needed to build this annotation resolver tool. A smart ass like me than had the idea to create a local Maven build in the same folder as the Python script with a dedicated pom.xml file that will produce the annotation resolver tool. Therefore the direct javac calls and other stuff was replaced with a 'mvn clean install' call.

import subprocess
subprocess.call(["mvn", "clean", "install"])

Awesome! Removed some unneeded Python code, introduced a dedicated Maven build to produce a single jar file that will be launched afterwards with a simple 'java -cp <jarfile> <main class>' call by the same Python script. Things can be very straightforward sometimes. So let's give this new way of building and launching the tool a spin.

Since this Maven artefact is part of a bigger Maven build and contains a lot of dependencies I've triggered the top-level build and left my PC to finish some other things. When I came back I've wondered myself why I do see the KDE login screen on my monitors. After I've logged in I've found the following in the build log.

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building build
[INFO]    task-segment: [clean, install]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] [resources:resources {execution: default-resources}]
[INFO] [compiler:compile {execution: default-compile}]
[INFO] [resources:testResources {execution: default-testResources}]
[INFO] [compiler:testCompile {execution: default-testCompile}]
[INFO] [surefire:test {execution: default-test}]
[INFO] [jar:jar {execution: default-jar}]
[INFO] [install:install {execution: default-install}]
[INFO] [antrun:run {execution: default}]
[INFO] Executing tasks
     [exec] [INFO] Scanning for projects...
     [exec] [INFO] ------------------------------------------------------------------------
     [exec] [INFO] Building build
     [exec] [INFO]    task-segment: [clean, install]
     [exec] [INFO] ------------------------------------------------------------------------
     [exec] [INFO] [clean:clean {execution: default-clean}]
     [exec] [INFO] [resources:resources {execution: default-resources}]
     [exec] [INFO] [compiler:compile {execution: default-compile}]
     [exec] [INFO] [resources:testResources {execution: default-testResources}]
     [exec] [INFO] [compiler:testCompile {execution: default-testCompile}]
     [exec] [INFO] [surefire:test {execution: default-test}]
     [exec] [INFO] [jar:jar {execution: default-jar}]
     [exec] [INFO] [install:install {execution: default-install}]
     [exec] [INFO] [antrun:run {execution: default}]
     [exec] [INFO] Executing tasks
     [exec]      [exec] [INFO] Scanning for projects...
     [exec]      [exec] [INFO] ------------------------------------------------------------------------
     [exec]      [exec] [INFO] Building build
     [exec]      [exec] [INFO]    task-segment: [clean, install]
     [exec]      [exec] [INFO] ------------------------------------------------------------------------
     [exec]      [exec] [INFO] [clean:clean {execution: default-clean}]
     [exec]      [exec] [INFO] [resources:resources {execution: default-resources}]
     [exec]      [exec] [INFO] [compiler:compile {execution: default-compile}]
     [exec]      [exec] [INFO] [resources:testResources {execution: default-testResources}]
     [exec]      [exec] [INFO] [compiler:testCompile {execution: default-testCompile}]
     [exec]      [exec] [INFO] [surefire:test {execution: default-test}]
     [exec]      [exec] [INFO] [jar:jar {execution: default-jar}]
     [exec]      [exec] [INFO] [install:install {execution: default-install}]
     [exec]      [exec] [INFO] [antrun:run {execution: default}]
     [exec]      [exec] [INFO] Executing tasks
     [exec]      [exec]      [exec] [INFO] Scanning for projects...

WTF?! Why is Maven calling the same artefact build over and over again? And why did my PC reboot itself? Okay.. Kernel Panic in syslog 'Cannot allocate memory'.. interesting.. At least there aren't any loops around my changed Python code so that this 'subprocess.call()' code can't be called multiple times. Hmm.. Than let's check the called Maven sub-build and it's pom.xml file. Wait! The sub-build lives in the same directory as the called Python script. Does the maven-antrun-plugin change the working directory while calling the... FAIL!

So, things you shouldn't do #1: Recursive Maven Builds
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

Connect with Facebook

No trackbacks yet.