Posts Tagged ‘Archetype’

Working with Custom Maven Archetypes (Part 3)

February 25, 2010

In part 1 and part 2 of this series I was able to demonstrate how you can create a custom archetype and release it to a Maven repository. In this final part we’ll look at what you need to do to integrate it into your development process. This will involve the following steps:

  • Uploading the archetype and its associated metadata to a Maven Repository Manager.
  • Configuring an IDE to use the archetype.
  • Generating a skeleton project from the archetype.

Step 1 – Upload your archetype

In part 2 we covered releasing and deploying the archetype. For reasons of brevity I simply demonstrated deploying a release to the local file system, but if we wish to share our archetype we must deploy it to a remote repository that can be accessed by other developers. A remote Maven repository, in its simplest form, can be served up using a Http server such as Apache or Nginx. However, these days I would recommend that you use a Maven Repository Manager (MRM) instead, as these tools are purpose-built for serving (and deploying) Maven artefacts. There are basically three options for your MRM – Nexus, Artifactory or Archiva. A features matrix comparision is available here. All are available in open source flavours and both Nexus and Artifactory in particular are great tools. However, currently Artifactory is the only one that supports a Cloud-based service option which, as you might expect, integrates very well with our hosted Continuous Integration service. This allows you to provision yourself a fully-fledged MRM in very short order.

So, how do we add our archetype to the repository? This is a simple process using the built in Artifact Deployer of Artifactory which allows you to upload a file and supply its Maven GAV co-ordinates.

Artifactory Deployer

Artifactory Web-based Deployer

Next, we need to add some additional metadata about our archetype in the form of a ‘catalog’:


<?xml version="1.0" encoding="UTF-8"?>
<archetype-catalog>
  <archetypes>
    <archetype>
    <groupId>com.mikeci</groupId>
    <artifactId>mikeci-archetype-springmvc-webapp</artifactId>
    <version>0.1.4</version>
    <repository>http://mikeci.artifactoryonline.com/mikeci/libs-releases</repository>
    <description>Mike CI archetype for creating a Spring-Mvc web application.</description>
    </archetype>
  </archetypes>
</archetype-catalog>

This file should ideally be placed into an appropriate folder of a Maven repository and it contains information about all of the archetypes that live within the repository. We can simply add this file to our ‘libs-releases’ repository using Artifactory’s REST API:


curl -u username:password -f -d @archetype-catalog.xml -X PUT "http://mikeci.artifactoryonline.com/mikeci/libs-releases/archetype-catalog.xml"

Step 2 – Configure your IDE

Now that our archetype is deployed remotely, we can start to use it from within our IDE – in my case – Eclipse. To get good Maven integration inside Eclipse, you really should be using the latest release (0.10.0) of m2eclipse. Once m2eclipse is installed, it provides a handy feature that allows you to add and remove archetype catalogs. You will need to add your deployed archetypes catalog to the list of catalogs accessible from within m2eclipse. This ensures that you can access your custom archetypes when you run the Create a Maven Project wizard in Eclipse as we will see shortly.

Choose the menu item, Windows>Preferences, to open the Preferences dialog and drill down to the Maven>Archetypes preferences, as shown.


m2eclipse Archetype Prefs

Setting archetype preferences


Click Add Remote Catalog to bring up the Remote Archetype Catalog dialog. In the Catalog File text box, enter the path to your remote catalog file and in the Description text box, enter a name for your catalog:

m2eclipse Remote Catalog

Adding the catalog

Step 3 – Generate your project

You should now be ready to generate a skeleton Maven project inside Eclipse. Choose the menu item, File>New>Other, to open the Select a wizard dialog. From the scrollbox, select Maven Project and then click Next. Follow the wizard to configure your project location. Eventually, the wizard allows you to select the archetype to generate your Maven project. From the Catalog drop-down list, select your custom catalog. Then locate and select your archetype :

m2eclipse Select Archetype

Select the archetype

Click Next and enter the GAV values for your new project. Et voila – you should have just created a skeleton project based upon your custom archetype using a slick IDE wizard.

Pretty impressive, don’t you think?

Advertisements

Working with Custom Maven Archetypes (Part 2)

January 26, 2010

In part 1 of this series of blog entries I demonstrated how you can quickly create a custom Maven archetype. This nice feature of Maven allows you to produce template or skeleton projects, which are great for bootstrapping your development efforts. In this second part of the series, I’ll show you how to ‘production-ize’ your archetype, which involves the following steps:

  • Add your archetype to version control
  • Update the appropriate metadata elements in your archetype’s POM
  • Release your archetype using the maven-release-plugin

Step 1 – Add your archetype to version control

I decided to use Git as the VCS (version control system) for my archetype. This is in part due to the fact that we will soon be releasing a new version of Mike that supports projects hosted on the popular ‘Social coding’ site GitHub. GitHub offers free project hosting for ‘public’ (AKA open source) projects.

So, lets get down to business. First off, you must have the Git client installed of course. If you are on a flavour of *nix this is a cinch, but there is tooling support for other OS’ including TortoiseGit, from the creators of the popular TortoiseSVN client. As there are already plenty of tutorials about using Git, i’m not going to replicate all steps here. Try Git for the lazy if you are time poor, for a good intro.

First up, I navigate to a directory, initialise my Git repository and add my fledgling archetype:


~/foo$ cd mikeci-archetype-springmvc-webapp
~/foo/mikeci-archetype-springmvc-webapp$ git init
Initialized empty Git repository in /home/leggetta/foo/mikeci-archetype-springmvc-webapp/.git/
~/foo/mikeci-archetype-springmvc-webapp$ git add .
~/foo/mikeci-archetype-springmvc-webapp$ git commit -m "Initial commit"
Created initial commit fad815f: Initial commit
 13 files changed, 513 insertions(+), 0 deletions(-)
 create mode 100644 pom.xml
 create mode 100644 src/main/resources/META-INF/maven/archetype-metadata.xml
 create mode 100644 src/main/resources/META-INF/maven/archetype.xml
[...]

Now that i have my archetype added to a local Git repo, I want to share this via GitHub. This obviously requires a GitHub account and you also need to ensure you have added a public key to provide you with the requisite privileges to ‘push’ your changes. Once you’ve set up a bare repository on GitHub, you can execute the following commands:


~/foo/mikeci-archetype-springmvc-webapp$ git remote add origin git@github.com:amleggett/mikeci-archetype-springmvc-webapp.git
~/foo/mikeci-archetype-springmvc-webapp$ git push origin master
Counting objects: 34, done.
Compressing objects: 100% (22/22), done.
Writing objects: 100% (34/34), 21.23 KiB, done.
Total 34 (delta 1), reused 0 (delta 0)
To git@github.com:amleggett/mikeci-archetype-springmvc-webapp.git
 * [new branch]      master -> master

What did I just do? The command remote add origin [url] adds the location of the remote GitHub repository to my local repository configuration and calls it ‘origin’. When I type push origin master this sends or ‘pushes’ my local changes on the ‘master’ branch to the ‘origin’ server. The ‘master’ branch is one that is created by default for me when I initialized the repository above.

Step 2 – Updating the POM

For Maven to function effectively, you should always ensure that you include project VCS information in your POM file. Now that we’ve added the archetype to a Git repository we can include the appropriate <scm> configuration:


  <scm>
   <connection>
   scm:git:ssh://github.com/amleggett/${artifactId}.git
   </connection>
   <developerConnection>
   scm:git:ssh://git@github.com/amleggett/${artifactId}.git
   </developerConnection>
   <url>
   http://github.com/amleggett/${artifactId}
   </url>
  </scm>

It’s important to understand the meaning of each of the child elements of <scm>. The <connection> element defines a read-only url and the <developerConnection> element a read+write url. For both of these elements the url must adhere to the following convention:


 scm:<scm implementation>:<scm implementation-specific path>

Finally, the <url> element content should point to a browsable location and for me this is the GitHub repository home page. Note that in all cases, I’m using an interpolated value which is my project artifactId.

One handy tip is that you can verify this configuration by using the maven-scm-plugin. This plugin offers ‘vendor’ independent access to common VCS commands by offering a set of command mappings for the configured VCS. The validate goal should confirm all is well:


~/foo/mikeci-archetype-springmvc-webapp$ mvn scm:validate
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'scm'.
[INFO] --------------------------------------------------------------
[INFO] Building MikeCI Spring-Mvc web application archetype
[INFO]    task-segment: [scm:validate] (aggregator-style)
[INFO] --------------------------------------------------------------
[INFO] Preparing scm:validate
[INFO] No goals needed for project - skipping
[INFO] [scm:validate {execution: default-cli}]
[INFO] connectionUrl scm connection string is valid.
[INFO] project.scm.connection scm connection string is valid.
[INFO] project.scm.developerConnection scm connection string is valid.
[INFO] --------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] --------------------------------------------------------------

We also have to update the POM to tell Maven (or rather, the maven-deploy-plugin) where to deploy snapshot and released versions of our archetype. For the time being, i’m just going to specify my local filesystem as this destination, but in a real world example this would most likely point to a location appropriate for a Maven repository manager, such as Nexus or Artifactory:


 <distributionManagement>
  <repository>
   <id>release-repo</id>
   <url>file:///home/leggetta/foo/release-repository</url>
  </repository>
  <snapshotRepository>
   <id>snapshot-repo</id>
   <url>file:///home/leggetta/foo/snapshot-repository</url>
  </snapshotRepository>
 </distributionManagement>

Once satisfied with the POM modifications, I commit to my local Git repo and then push the changes to GitHub.

Step 3 – Releasing the archetype

So, i’m now almost ready to create my first early release of the archetype. I can accomplish this using the maven-release-plugin. This plugin exposes two major goals – prepare and perform.
The prepare goal does some pre-flight checking by running a build and verifying all is well before promoting the version in the pom and creating a tag of the release. The perform goal then checks out this tag, builds the project and deploys the resulting artefact to the Maven <repository> specified in your <distributionManagement> section.

Its always a good idea to use the most recent version of the maven-release-plugin, which is currently 2.0-beta-9. This will require a further POM modification and Git commit+push:


 <plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-release-plugin</artifactId>
  <version>2.0-beta-9</version>
 </plugin> 

Next, run the release:prepare goal. By default this runs interactively, prompting you in your shell to provide info about the release version and subsequent development version:


:~/foo/mikeci-archetype-springmvc-webapp$ mvn release:prepare
[INFO] Scanning for projects...
[INFO] --------------------------------------------------------------
[INFO] Building MikeCI Spring-Mvc web application archetype
[INFO]    task-segment: [release:prepare] (aggregator-style)
[INFO] --------------------------------------------------------------
[INFO] [release:prepare {execution: default-cli}]
[INFO] Verifying that there are no local modifications...
[...]
[INFO] Checking dependencies and plugins for snapshots ...
What is the release version for "MikeCI Spring-Mvc web application archetype"? (com.mikeci:mikeci-archetype-springmvc-webapp) 0.1.2: : 
[...]
[INFO] Release preparation complete.
[INFO] --------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] --------------------------------------------------------------

Then run release:perform. If it all goes smoothly, you should have something akin to the following in your remote repository:


~/foo$ ls -1 release-repository/com/mikeci/mikeci-archetype-springmvc-webapp/0.1.2/
mikeci-archetype-springmvc-webapp-0.1.2.jar
mikeci-archetype-springmvc-webapp-0.1.2.jar.md5
mikeci-archetype-springmvc-webapp-0.1.2.jar.sha1
mikeci-archetype-springmvc-webapp-0.1.2.pom
mikeci-archetype-springmvc-webapp-0.1.2.pom.md5
mikeci-archetype-springmvc-webapp-0.1.2.pom.sha1
mikeci-archetype-springmvc-webapp-0.1.2-sources.jar
mikeci-archetype-springmvc-webapp-0.1.2-sources.jar.md5
mikeci-archetype-springmvc-webapp-0.1.2-sources.jar.sha1

So, to summarise, I now have the appropriate configuration management in place to make changes to my archetype and release it to a Maven repository.
In the next part of this series, I’ll look into the different ways you can integrate your archetype into the development process.