6

I am working with a module that produces a WAR artifact through Maven. The module has a typical src/main/webapp directory. I'm using Maven's war plugin to supplement the webapp directory with another resource directory that can be programmatically provided at build time. So my plugin is configured in the POM like this:

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
        <webResources>
            <resource>
                <directory>src/main/webapp.${flavor}</directory>
            </resource>
        </webResources>
    </configuration>
</plugin>

Where ${flavor} defaults to a value in the root POM, or can optionally be overridden at build time with something like this:

mvn clean install -Dflavor=customer

The problem is the war plugin dies a fiery death during the build if it cannot find the directory provided for the resource (i.e. src/main/webapp.customer doesn't exist). My project can have many flavors, and I'd rather not have to create an empty directory for each possible flavor, just to appease the plugin.

Question(s): Is there a way to configure the war plugin to not fail the build when the directory does not exist? And if not, what is the best way to create this directory at build time when it does not already exist?

Thank you.

UPDATE

After additional thought and research, I decided to pursue a conditional creation of the "flavored" directory at build time, using the maven-antrun-plugin. After all, if the build needs the directory to be there - and will die without it - then the build should ensure the directory is there. So here's my antrun plugin execution:

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
        <execution>
            <id>created-flavored-resources-directory</id>
            <phase>process-resources</phase>
            <configuration>
                <target>
                    <mkdir dir="src/main/webapp.${flavor}"/>
                </target>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
</plugin>

The execution will create the directory only when the directory does not already exist. This allows us to have a directory in place... or not. Everything just works.

Matt
  • 23,363
  • 39
  • 111
  • 152
  • Let me just clarify, you want it to build against a resource that you are referencing but it doesn't exist? Why don't you create the default location. The default directory for the exploded WAR is target/. The finalName is usually in the form of -. This default directory can be overridden by specifying the webappDirectory parameter. – Karen12345 Jan 18 '18 at 18:58
  • The default directory Maven uses to assemble a WAR is `src/main/webapp`. That exists like normal. The `webResource` option allows us to **supplement** the webapp directory with additional resources, not override. So it's a useful mechanism. The `flavor` property is used during the build for other things, not just for this particular thing. So it'd be most flexible if a developer could *optionally* provide - for various modules - a supplemental `webapp` directory for a particular flavor, if that module's functionality demands it. But if it's not there, that should be fine too. – Matt Jan 18 '18 at 19:05
  • What error do you get? – SilverNak Jan 18 '18 at 19:22
  • [ERROR] Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.4:war (default-war) on project my-project: Execution default-war of goal org.apache.maven.plugins:maven-war-plugin.2.4:war failed: basedir /path/to/webapp/my-project/src/main/webapp.customer does not exist -> [Help 1] – Matt Jan 18 '18 at 19:28
  • I would suggest to take a look here: https://github.com/khmarbaise/multienv-maven-plugin/ – khmarbaise Jan 18 '18 at 19:35
  • @khmarbaise Thank you for the reference. It looks useful, but I'm happy with the way I have configured my build. This is simply a nagging issue. – Matt Jan 19 '18 at 01:29
  • I think the UPDATE section shouldn't have been part of question but rather the self-accepted answer. – Tomáš Záluský Mar 12 '18 at 18:44

1 Answers1

1

I had similar problem (actually found your question while googling for solution).

My observation was same as yours: directory must exist. However, it does not apply to <include>s. So I hope this would pass even if webapp.${flavor} subdir didn't exist:

<resource>
    <directory>src/main</directory>
    <includes>
        <include>webapp.${flavor}</include>
    </includes>
</resource>

The disadvantage is you cannot then use <targetPath> to rename dir.

My background: I had optional dir with built documentation which had to be bundled into war. The combination directory=${project.basedir}/../docs-build + include=** didn't work when docs-build directory didn't exist. In contrast, directory=${project.basedir}/.. + include=docs-build worked. (Finally I dropped this approach since I needed to rename dir but that's a different story.)

Tomáš Záluský
  • 10,735
  • 2
  • 36
  • 64