How to get maven archetype to generate empty directories?

If you think of a maven archetype as of a template for a new java project, you would probably expect it to produce a complete structure of directories and files for you. It is pretty likely you would need some of the directories to be empty. And this is exactly where your expectations would not match the maven-archetype plugin design (2.0-alpha-4). It seems like, in spite of its numerous assets, the archetype plugin has a little flaw: it does not provide an intuitive way to create an archetype which is capable of generating empty directories.

However I found out a somehow-not-so-elegant hack to cope with the problem. It turns out that the issue is well known to the developers and was addressed quite a long time ago as jira.codehaus.org/browse/ARCHETYPE-57. Anyhow, the provided solution gives you a possibility to create an empty directory. In order to do that you have to specify a fileset in the archetype-metadata.xml file (src/main/resources/META-INF/maven/archetype-metadata.xml).
So, for example if you want to create an empty dir src/java/main/configuration you should paste following code into the filesets section of the file:

<fileSet filtered="true" encoding="UTF-8">
 <directory>src/java/main/configuration</directory>
</fileSet>

This works fine as long as you don’t want packaging to be performed. Archetype plugin facilitates the process of creating directories in a way that you can specify a desired Java package for your project and appropriate directories would be created following the java convention. e.g. if you specify the package to be pl.company.project in normal circumstances you would expect to get a following structure:

src/java/main/pl/company/project/configuration.

Unfortunately setting fileSet directory to src/java/main/configuration would result in having

src/java/main/configuration/pl/company/project

as an outcome. This is, obviously not, what you want to achieve… and this is where the hack can be applied.

To achieve the desired result one has to resign from the packaging mechanism provided by the plugin (set packaged parameter of the fileset to false). Instead, one will specify  the insertion point manually.
It appears that paths defined in the archetype-metadata.xml file are processed by the velocity engine (which is quite surprising). Note that context variables have to be surrounded by __(double underscore).

Define your paths in a following manner:

<fileSet filtered="true" encoding="UTF-8">
 <directory>src/java/main/__packageAsDirectory__/configuration</directory>
</fileSet>

__packageAsDirectory__ will be replaced with the value of packageAsDirectory velocity variable. As you presume the packageAsDirectory variable does not exist yet. And this is  the not-so-elegant part of the solution.
You want to force the user to input the package in a form of a directory (i.e. slashes instead of dots). In order to do that you create a new required parameter, defining it in the archetype-metadata.xml file.

<requiredProperties>
 <requiredProperty key="packageAsDirectory"/>
</requiredProperties>

Of course, the users of your archetype have to be aware of what they input as there is no validation check performed on the input path. (e.g. pl/company/project is a valid value, but pl.company.project is invalid).

You can also ignore the package parameter and  give it some default value (you won’t really need it) e.g.:

<requiredProperties>
  <requiredProperty key="package">
   <defaultValue>PLEASE ENTER packageAsDirectory INSTEAD</defaultValue>
  </requiredProperty>
</requiredProperties>

Now, in order to convert slashes back to dots you set a velocity variable $package as demonstrated below:

#set ( $package = $packageAsDirectory.replaceAll("/", ".") )

Put this line at the top of every template file when needed – your .java files or any other file that uses the ${package} variable.

Have fun…

Advertisements

,

  1. #1 by icefox on March 2, 2010 - 9:25 am

    Hi,

    Your solution is working but I would make it in another way.
    I think that using the package property as base property instead of packageAsDirectory makes more sense, because it’s a standard property of the archetype plugin.

    So I would not add the packageAsDirectory property in the archetype-metadata.xml.
    And instead I would declare in on top of my pom.xml file.
    #set ( $packageAsDirectory = $package.replace(“.”, “/”) )

    And I will let the empty directory declaration in the archetype-metadata.xml like:

    src/java/main/__packageAsDirectory__configuration

    It’s exacly the same solution but instead of defining the packageAsDirectory property, you guess it from the standard maven-archetype package property.

    Cheers,

    • #2 by Boonefaes on January 28, 2011 - 8:24 am

      Hi,

      I’m facing the same maven problem and i prefer not answer the user for the package name neither. Did you success with your #set ( $packageAsDirectory = $package.replace(“.”, “/”) ) declaration ? I tried to put this on top of my pom.xml before call mvn install on my archetype put the maven xml parser doesn’t allow this delcaration neither in the pom.xml file nor in the archetype-metadata.xml file.

      How did you do to get this works ?

      Thx

      • #3 by marekdec on January 28, 2011 - 7:30 pm

        Did you actually need the replacement to happen in the pom file? It looks like you are looking for a place to put the set directive, but there is nothing to look for. It should be put where you want the replacement to happen – and for sure it must a part that will be processed and generated by the archetype plugin.
        Both archetype-metadata and pom.xml (i guess you refer to the archetype metadata pom) do not get processed by the velocity engine.

        The solution is to put this directive in every file that uses the ‘package’ variable.

      • #4 by Boonefaes on February 2, 2011 - 3:30 pm

        Hi,

        In fact the goal is to do something like that in the archetype-metadata.xml file but without prompt the user for anything :

        src/main/java/$package.replace(“.”, “/”)/aDirectory

        The goal is to add the empty “aDirectory” directory in the good package in the generated project.

  2. #5 by PomCompot on March 27, 2012 - 1:03 pm

    What about the new variable ${packageInPathFormat} in maven-archetype-plugin:2.2?

  3. #6 by loop on September 7, 2012 - 4:15 pm

    well using ${packageInPathFormat} in every file where it’s needed, and using __packageInPathFormat__ in archetype-metadata.xml, you just have to write this and it works

    src/java/main/__packageInPathFormat__/configuration

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: