As I am the one who does most of our
OpenCms projects I am also the one who has to deploy new versions to our internal
Nexus repository so we can easily use the libraries from
Maven.
The guys developing OpenCms use Ant for their builds so there is no official Maven repository available.
Most of the time I added only the dependencies that are really necessary on compile time because creating a Maven POM by hand is quite cumbersome, not to mention the deployment of all the dependencies (either uploading to Nexus or deploying using Maven). One of those time consuming tasks that needs some automation.
I chose
Groovy for implementing a little helper script because it is really good at dealing with XML and it's always good to learn some new techniques. I already got some experience in modifying existing scripts but did not use it for creating something from scratch.
The script basically just reads a folder with jars and creates a pom for the whole project as well as a script for deploying all additional artifacts using Maven. Creating the files currently involves two steps:
- A properties file is created from the information that is guessed from the filename of the jars. As jars are often not named consistent this will not succeed for all jars. So you have to review the file and change some group names, artifactIds and versions (another step that could be automated, e.g. by querying a Nexus instance, but let's save some work for the future ;) ). Another properties file holds project and deployment information like project groupId and artifactId and the server to deploy to.
- The properties files are read again by another script and the project pom as well as the deployment script is generated.
Of course you also have to review the deployment script because you don't want to deploy any artifacts that are already available. A good way to find out which artifacts are missing is to call something like {{{mvn compile}}} on the generated pom.
I uploaded the
(uncommented) scripts and helper classes, maybe it's useful for somebody.
I guess there are far better solutions to creating maven projects from existing libraries, I am looking forward to hearing about them.
The XML manipulation features of Groovy are really nice. When writing XML you append your node structure to a builder object and it creates the markup for you. You always stay very close to the format you intend to output. E.g. this is the code to create the XML for a pom file:
def writer = new StringWriter();
def xmlBuilder = new MarkupBuilder(writer);
xmlBuilder.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')
groupId(project.group)
artifactId(project.artifact)
packaging('jar')
version(project.version)
name(project.artifact)
dependencies() {
dependencies.each() { dep ->
dependency {
groupId(dep.group)
artifactId(dep.artifact)
version(dep.version)
}
}
}
}
You are looking at this code and immediately can imagine the structure of the resulting XML. I like it!
Also, file manipulation is really nice. No need to do any resource cleanup. This code is responsible for writing the created pom file:
new File(dir + "pom.xml").withWriter() { out ->
out.println(projectPom.toString());
}
Some drawbacks I noticed when doing scripting like this:
- I tend to get sloppy while coding. Not adding semicolons to the end of lines, doing too many things in one class/script, ...
- Code completion in Netbeans is horrible if you are used to Java standards, but I guess that is just very hard to implement
- You have to compile manually, at least in Netbeans. If you are changing a Groovy class that is used by a script you have to remember to do a build because when running the script Netbeans will not compile it for you.
- A lot of coding errors are only discovered on runtime. E.g. using the wrong name for properties or calling a constructor that doesn't exist
I still can't imagine using a dynamic language on production code. Of course the deployment time tends to be shorter but still you have to execute the code to see if it is really correct. I doubt that writing tests could compensate for the lack of static type checking but probably this needs a shift of the mindset.