Maven Archetypes Tutorial

Creating an archetype is a pretty straight forward process.

An archetype is a very simple artifact, that contains the project
prototype you wish to create.
An archetype is made up of:

1.an archetype descriptor (archetype.xml in directory:
src/main/resources/META-INF/maven/).
This file groups the resources as file sets (fileSets) 
that are going to be filtered by the archetype during the generation process
2.the prototype files that are copied by the archetype plugin
(directory: src/main/resources/archetype-resources/)
3.the prototype pom (pom.xml in: src/main/resources/archetype-resources)
4.a pom for the archetype (pom.xml in the archetype's root directory).

An example pom.xml for an archetype artifact looks as follows:

    <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/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>

      <groupId>my.groupId</groupId>
      <artifactId>my-archetype-id</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>jar</packaging>
    </project>

All you need to specify is a groupId, artifactId and version. These
three parameters will be needed later for invoking the archetype via
archetype:generate from the commandline.

Create the archetype descriptor

The archetype descriptor is a file called archetype.xml which must be
located in the src/main/resources/META-INF/maven/ directory. An example
of an archetype descriptor can be found in the quickstart archetype:

    <archetype
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype/1.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype/1.0.0
http://maven.apache.org/xsd/archetype-1.0.0.xsd">
      <id>quickstart</id>
      <sources>
        <source>src/main/java/App.java</source>
      </sources>
      <testSources>
        <source>src/test/java/AppTest.java</source>
      </testSources>
    </archetype>

The id-tag should be the same as the artifactId in the archetype pom.xml.
An optional <allowPartial>true</allowPartial> tag makes it possible to
run the archetype:generate even on existing projects.
The <sources>, <resources>, <testSources>, <testResources> and
<siteResources> tags represent the different sections of the project:

    <sources> = src/main/java
    <resources> = src/main/resources
    <testSources> = src/test/java
    <testResources> = src/test/resources
    <siteResources> = src/site

Create the prototype files and the prototype pom.xml

The next component of the archetype to be created is the prototype pom.xml.
Any pom.xml will do, just don't forget to the set artifactId and groupId
as variables ( ${artifactId} / ${groupId} ).
Both variables will be initialized from the commandline when calling
archetype:generate.
An example for a prototype pom.xml is:

    <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/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>

      <groupId>${groupId}</groupId>
      <artifactId>${artifactId}</artifactId>
      <version>${version}</version>
      <packaging>jar</packaging>

      <name>A custom project</name>
      <url>http://www.myorganization.org</url>

      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    </project>

Create a Maven Archetype from an existing project

First navigate to the root directory of the source project and run the
following maven command

mvn archetype:create-from-project

You should get something like this:
[INFO]
[INFO] --- maven-archetype-plugin:2.2:jar (default-jar) @
TestProject-archetype ---
[INFO] Building archetype jar:
/Users/ryan/projects/SampleMVC/target/generated-sources/archetype/target/SampleMVC-archetype-1.0
[INFO]
------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO]
------------------------------------------------------------------------
[INFO] Total time: 19.660s
[INFO] Finished at: Fri Feb 15 21:58:42 PST 2013
[INFO] Final Memory: 10M/554M
[INFO]
------------------------------------------------------------------------
[INFO] Archetype created in
/Users/ryan/projects/SampleMVC/target/generated-sources/archetype
[INFO]
------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO]
------------------------------------------------------------------------
[INFO] Total time: 22.853s
[INFO] Finished at: Fri Feb 15 21:58:43 PST 2013
[INFO] Final Memory: 8M/554M
[INFO]
------------------------------------------------------------------------

The first success is the packaged archetype.
This packages a jar file which can be used in a maven repo when
generating new projects.
If we need to make modifications we have to skip that for now.
The second success id the archetype project.
Copy the target/generated-sources/archetype to a new directory and
evaluate for changes.
The root structure is
– pom.xml
– src/
– target/
Target can be removed with mvn clean
pom.xml is the pom of the archetype and only has those things needed to
build the archetype jar. We’ll only need to change to a 1.0-SNAPSHOT
version since the first release is not final yet.
src/ is the archetype project source. This only has a few required
components. main & test are standard. test/resources has been created
for us and has entries for integration testing.
main/resources has two folders:
1. archetype-resources – this is the project template and what will be
generated when the archetype is run
2. META-INF/maven – this contains the archetype-metadata.xml file which
has the settings and options when generating a new project.
This file groups the resources as file sets (fileSets) that are going 
to be filtered by the archetype during the generation process.

Multi-module projects

Is common to have several modules in the application structure, for example,
the domain classes of a project can be grouped in a application-persist subproject,
the web application that serves as the application front-end can be in a application-webapp subproject, and so on.
All these submodules would be controlled by an Aggregator Project. The project layout should be in hierarchical form,
the parent/aggregator project must contain the module subprojects directories inside it.
If you start from a flat layout structure and run mvn archetype:create-from-project,
maven will generate the module archetype rosource folders in the directory /src/main/resources,
then in the archetype creation (mvn install) it will complain that it can't find the archetype resource files
inside the folder /src/main/resources/archetype-resources and will exit the execution with an error message.
To solve this problem you have to manually move the module archetype resources to the
/src/main/resources/archetype-resources directory or rearrange your project structure to the hierarchical form.
Is usually the case that the project modules are named <project-name>-module-name and reside inside the parent folder named <project-name>.
For example, given a project named nextgeo with the modules persist, web-services and web-app, a common project folder names for this modules would be:
nextgeo-persist, nextgeo-web-services and nextgeo-web-app all inside the nextgeo folder.
To process a project layout such as this, run mvn archetype:create-from-project inside the project parent folder,
then rename the subfolders nextgeo-persist, nextgeo-web-services and nextgeo-web-app (inside the src/main/resources/archetype-resources folder) to:
rootArtifactId-persist, rootArtifactId-web-services and rootArtifactId-web-app,
also in the archetype-metadata.xml you would see that the file-sets are grouped together by a <modules> tag:

<module id="nextgeo-persist" dir="nextgeo-persist" name="nextgeo-persist">
    <!-- Several file sets... -->
</module>  
<module id="nextgeo-web-app" dir="nextgeo-web-app" name="nextgeo-web-app">
    <!-- Several file sets... -->
</module>     
<!-- And so on... -->

Change the base project name (nextgeo) with the variable ${rootArtifactId},
except for the dir attribute that points to a folder name
(this must remain equal to the phisycal folder name or maven won't be able to copy/filter the folder and its content),
like this:

<module id="${rootArtifactId}-persist" dir="__rootArtifactId__-persist" name="${rootArtifactId}-persist">
    <!-- Several file sets... -->
</module>     
<module id="${rootArtifactId}-web-app" dir="__rootArtifactId__-web-app" name="${rootArtifactId}-web-app">
    <!-- Several file sets... -->
</module>     
<!-- And so on... -->

Configure the archetype.

Important Variables:

${rootArtifactId}:
It holds the value entered by the user as the project name
(the value that maven ask as the artifactId: in the prompt when the user runs the archetype)

${artifactId}:
If your project is composed by one module, this variable will have the same value as ${rootArtifactId},
but if the project contains several modules, this variable will be replaced by the module name inside every module folder,
for example: given a module named portlet-domain inside a project named portlet,
all the files inside this module folder that are to be filtered will have the value of the variable ${artifactId}
replaced by portlet-domain whereas the ${rootArtifactId} variable will be replaced by portlet.

${package}:
The user provided package for the project, also prompted by maven when the user runs the archetype.

${packageInPathFormat}:
The same value as ${package} variable but replacing '.' with the character '/', e.g:,
for the package com.foo.bar this variable is com/foo/bar.

${groupId}:
The user supplied groupId for the project, prompted by maven when the user runs the archetype.

${version}:
The user supplied version for the project, prompted by maven when the user runs the archetype

Unfortunately maven ignores empty directories when creating an archetype from a project.
But you can manually add these directories and the included java classes if you like to.
Therefor you only have to add them in the archetype-descriptor which is located in the /META-INF/maven/ directory.
It is called archetype-metadata.xml

<fileSet encoding="UTF-8">
        <directory>src/test/java</directory>
        <includes>
            <include>**/*.java</include>
        </includes>
    </fileSet> 

If you want to rename some of the project files or folders to the user supplied project name,
you have to change those files/folder names to rootArtifactId.
For example, rename the VAADIN/themes/test-portlet/test-portlet.scss to VAADIN/themes/test-portlet/__rootArtifactId__.scss,
so it will be renamed as the user supplied project name with the extension .scss.
Again, repeat this process with all those files and/or folders that you want to rename to reflect the user's project name.

Defining additional properties

The main properties that are used by the Velocity engine during a project's file generation are groupId, artifactId, version and package.
It is possible to define additional properties that must be valued before the file generation.
These additional properties can be provided with default values, which enable not to ask the user for there values.
Additional properties are defined in the archetype-metadata.xml file with:

<archetype-descriptor name="basic">
  <requiredProperties>
    <requiredProperty key="property-with-default">
      <defaultValue>default-value</defaultValue>
    </requiredProperty>
    <requiredProperty key="property-without-default"/>
  </requiredProperties>
...
</archetype-descriptor>

IMPORTANT: do not forget to declare these Properties in the archetype.properties file before!!!

Defining multiple modules in the archetype metadata

Inner modules of an archetype are used to create a multi-module Maven project from a single archetype.
Modules in the archetype-metadata.xml file are defined like this:

<archetype-descriptor name="multi-module">
  <fileSets>
    ...
  </fileSets>
  <modules>
    <module name="SubProject" id="subproject" dir="sub-project">
      <fileSets>
        ...
      </fileSets>
    </module>
  </modules>
</archetype-descriptor>

In the example above, the archetype multi-module contains a module named SubProject.
This module is located in the sub-project directory of the archetype. It also has the artifactId subproject.
The attributes name, id and dir of the module are used to determine the directory where the generated module's files will appear.
They also are used to determine the artifactId of the Maven project corresponding to this module.

Putting it all together

The <requiredProperties> element is only allowed as a child of <archetype-descriptor>.
Modules are allowed in <archetype-descriptor> and in <modules> (no limit is given).
<archetype-descriptor> and <modules> must define at least one <fileSet> each to be valid.
It is possible to define default values for required properties by defining say the groupId and giving it a default:

...
  <requiredProperties>
    <requiredProperty key="groupId">
      <defaultValue>com.company.department</defaultValue>
    </requiredProperty>
  </requiredProperties>

Filesets can be defined from the root directory of the module/project by having an empty <directory> element:

   ...
    <fileSet filtered="true" packaged="true">
      <directory></directory>
      <includes>
        ...
      </includes>
      <excludes>
        ...
      </excludes>
    </fileSet>

Install and deploy the archetype

You can now start to deploy your archetype.
At first install your archetype to your local maven configuration.

mvn install

Now that you have created an archetype, you can try it on your local
system by using the following command.
    mvn archetype:generate                                  \
      -DarchetypeGroupId=<archetype-groupId>                \
      -DarchetypeArtifactId=<archetype-artifactId>          \
      -DarchetypeVersion=<archetype-version>                \
      -DgroupId=<my.groupid>                                \
      -DartifactId=<my-artifactId>

In this command, you need to specify the full information about the
archetype you want to use (its groupId, its artifactId, its version) and
the information about the new project you want to create (artifactId and
groupId).
Don't forget to include the version of your archetype (if you don't
include the version, you archetype creation may fail with a message that
version:RELEASE was not found)
Once you are happy with the state of your archetype, you can deploy
(or submit it to ibiblio) it as any other artifact and the archetype
will then be available to any user of Maven.
h3. Archetype Deployments:
Once you want to share the archetype the packaged jar will need to be
deployed to a maven repo. From there you can use the mvn
archetype:generate
command.
You should be able to deploy it to a repo with:
mvn clean install deploy

Example for using RSB Archetypes to create new Projects.

The Archetypes groudId is rsb.

Thus enter the following command while you are in the correct directory for your new Project:

mvn archetype:generate -DarchetypeGroupId=rsb

Maven will now list up the available Archetypes filtered by the entered groudId rsb.
Just enter the Number for the Archetype you wish to use.
Afterwards you are going to be prompted to enter some values for new Project for example the versions you would like to use.