Create a Maven Archetype from an existing project

Maven archetypes are project templates that can quickly jump start new projects that are based on a set of core files. One of my favorite examples is AppFuse. Matt has created archetypes for a variety of projects that will get you up and running with a basic app that has user management built in. For this example my goal is to turn the simple Spring MVC project into a template to create new example projects.

There are two ways to kickoff an archetype project:
1. Build the project layout by scratch and add files as need
2. Run the Maven archetype plugin on an existing project and configure from there.

Since we already have a sample project I’m going to cover option two.

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

mvn archetype:create-from-project

After some maven magic you should see “BUILD SUCCESS”.

[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. Since we need to make modifications we’ll 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 me 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 was created for us and has entries for integration testing.

Testing Archetypes

There is support for running integration tests which will verify project creating and even compare the generated project to a reference one. This is useful when building up a project. See archetype:integration-test for more information.

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.

archetype_layout

Looking through the src/main/java folder we see that all the packages from the original project are gone. This is because maven will add it back from the groupId or package variable when generating a new project. Anything from this root will still be retained in the new project. For example is the package is “com.luckyryan.sample” then webapp would become /src/main/java/com/luckyryan/sample/webapp. Anything under webapp with be stored respective to that folder.

After a quick look all seems to be in order so let’s look at the project options.

<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="SampleMVC"
    xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <requiredProperties>
        <requiredProperty key="groupId">
            <defaultValue>com.luckyryan</defaultValue>
        </requiredProperty>
        <requiredProperty key="artifactId"/>
        <requiredProperty key="version">
            <defaultValue>1.0-SNAPSHOT</defaultValue>
        </requiredProperty>
        <requiredProperty key="package">
            <defaultValue>com.luckyryan.sample</defaultValue>
        </requiredProperty>
    </requiredProperties>
  <fileSets>
    <fileSet filtered="true" packaged="true" encoding="UTF-8">
      <directory>src/main/java</directory>
      <includes>
        <include>**/*.java</include>
      </includes>
    </fileSet>
    <fileSet filtered="true" encoding="UTF-8">
      <directory>src/main/webapp</directory>
      <includes>
        <include>**/*.jsp</include>
        <include>**/*.xml</include>
      </includes>
    </fileSet>
    <fileSet filtered="true" encoding="UTF-8">
      <directory>src/main/resources</directory>
      <includes>
        <include>**/*.xml</include>
      </includes>
    </fileSet>
  </fileSets>
</archetype-descriptor>

I added the required properties at the top of the file. groupId,artifactId, package & version are used by default. I define them here to give default values since in my scenario they won’t change.

Custom Variables

You can define custom variables in this section. For each variable you will also need to add it in src/test/resources/projects/basic/archetype.properties as a key/value pair. The helpful part of required variable definition is maven will prompt the user to enter the value during project creation.

Files that contain variables must be in a fileSet with filtered=”true”. The default in file syntax is like a Velocity template “${varName}” but they can also be used in directory names as “__varname__” (two _ before and after the var name).

Filesets tell maven what needs to be coped and how. The filtered flag indicates that those files will be processed by the Velocity engine and any matching variables will be replaced. So if you have a need to change a value in a file or config the use the “${varName}” syntax and make sure it is in a file set with filtered=”true”. The packaged flag will copy those filed into a structure prefixed with the package property.

An excellent description of metadata files options can be found on the maven site.

Once the archetype matches what we want. It’s time to install it locally and generate a sample project.
1. From the archetype root run mvn install
2. Create a new project directory /Users/ryan/projects/new_sample
3. Run the generate command mvn archetype:generate -DarchetypeCatalog=local. Local tells maven to look to the local repo for all archetypes and present with a list to pick one.
4. Enter the required parameters and the project is created.
5. cd into the project directory and run mvn jetty:run
6. Preview the new app

Archetype DeploymentsOnce you want to share the archetype then the packaged jar will need to be deployed to a maven repo. From there you can use the following command to generate a new project.

mvn archetype:generate 
    -DarchetypeGroupId=you_archetype_group_id 
    -DarchetypeArtifactId=sample-spring-mvc-archetype 
    -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=new.project.id 
    -DartifactId=sample 
    -DarchetypeRepository=path_to_maven_repo_with_archetype_jar

This was a quick example to get exposure to creating archetypes. For more Maven information I recommend reviewing the Apache Maven site and the Maven: The Complete Reference.

5 Comments

  1. Josh Jacob October 14, 2016
    • Ryan October 17, 2016
  2. russ October 22, 2014
  3. sanchit June 30, 2014
  4. Kanna January 12, 2014

Leave a Reply

Your email address will not be published. Required fields are marked *