1

I'm using the maven-resources-plugin because I need to use a custom delimiter when doing my filtering. My artifact is a WAR.

I have some resources in my src/main/resources directory. Normally, when packaging a WAR, anything in this directory ends up in WEB-INF/classes. But I need those resources to be filtered first, then placed into the WEB-INF/classes directory. I'm having a hard time configuring the maven-resources-plugin to do that. Is there a way?

My POM looks like this:

<build>
    <finalName>my-app</finalName>
    <filters>
        <filter>${basedir}/src/main/properties/base.properties</filter>
    </filters>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.0.2</version>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <phase>validate</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <overwrite>true</overwrite>
                        <useDefaultDelimiter>false</useDefaultDelimiter>
                        <delimiters>
                            <delimiter>@</delimiter>
                        </delimiters>
                        <outputDirectory>${project.build.directory}</outputDirectory>
                        <resources>
                            <resource>
                                <directory>
                                    ${basedir}/src/main/resources
                                </directory>
                                <filtering>true</filtering>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
Matt
  • 23,363
  • 39
  • 111
  • 152

2 Answers2

1

Short answer:

The phase is wrong, validate is the second phase, should only be used for validation of the build environment and comes before the default process-resources phase, so your correct files become overriden.

Long answer:

Basically, you have two options two fix your problem:

Use a different / new execution for copying

If you really need different behaviours.

In that case, your phase is wrong. What happens is:

  • in the phase validate (Why there?), the resources are correctly filtered and copied
  • in the phase process-resources, the default-resources execution of the resources plugin runs the goal copy-resources, which overrides your filtered resources again in the unfiltered state.

If you really want to do it this way, put the resources into a different directory than src/main/resources, change the phase of of the execution to somewhat appropriate (as to not confuse) and please also change the id of the execution (to something like copy-specially-filtered-resource - the id can be used to explain why there is the need for a second execution)

Also, the output directory is wrong (would need to be: ${project.build.outputDirectory}, directory points only to the target folder.

 <build>
    <finalName>my-app</finalName>
    <filters>
        <filter>${basedir}/src/main/properties/base.properties</filter>
    </filters>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.0.2</version>
            <executions>
                <execution>
                    <id>copy-special-resources</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <overwrite>true</overwrite>
                        <useDefaultDelimiter>false</useDefaultDelimiter>
                        <delimiters>
                            <delimiter>@</delimiter>
                        </delimiters>
                        <outputDirectory>${project.build.outputDirectory}</outputDirectory>
                        <resources>
                            <resource>
                                <directory>
                                    ${basedir}/src/main/filtered
                                </directory>
                                <filtering>true</filtering>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Also, in this case, I would place the filters into the execution configuration as well (everything else is misleading).

Preferred: Simply reconfigure the resources plugin

Way shorter and easier would be to simply reconfigure the resources plugin, activate filtering for the resources globally and use the default execution (however, this would also be active for test-resources):

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
    <finalName>my-app</finalName>
    <filters>
        <filter>${basedir}/src/main/properties/base.properties</filter>
    </filters>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.0.2</version>
            <configuration>
                <useDefaultDelimiter>false</useDefaultDelimiter>
                <delimiters>
                    <delimiter>@</delimiter>
                </delimiters>
            </configuration>
        </plugin>
    </plugins>
</build>

Hint: Using the override config is usually a smell...

blackbuild
  • 5,026
  • 1
  • 23
  • 35
  • You have written about a `default-resources` goal which does not exist. It is the execution Id of the maven-resources-plugin bound by the default life cycle. And I can't recommend to use the maven-resources-plugin cause maven-war-plugin can be configured to handle that... – khmarbaise Jan 07 '18 at 21:58
  • 1
    @khmarbaise You are correct, I mistyped. I meant of course the execution `default-resources` of the goal `copy-resources` (the code itself was correct) - I corrected it. – blackbuild Jan 07 '18 at 22:11
  • @khmarbaise As to `resources` vs `war` plugin, one should differentiate. If we are using a classpath resource, I would indeed use the resources plugin, which is commonly used for classpath resources (since war plugin uses it as well). For Non-Classpath resource, however, I would of course use the war plugin. However, the question clearly talked about classpath resources (WEB-INF/classes) – blackbuild Jan 07 '18 at 22:14
0

First why not reading the documentation of maven-war-plugin

Based on the documentation you can define a configuration to use a supplemental directory and activate filtering for that directory like this:

 <configuration>
          <filters>
            <filter>properties/config.prop</filter>
          </filters>
          <nonFilteredFileExtensions>
            <!-- default value contains jpg,jpeg,gif,bmp,png -->
            <nonFilteredFileExtension>pdf</nonFilteredFileExtension>
          </nonFilteredFileExtensions>
          <webResources>
            <resource>
              <directory>resource2</directory>
              <!-- it's not a good idea to filter binary files -->
              <filtering>false</filtering>
            </resource>
            <resource>
              <directory>configurations</directory>
              <!-- enable filtering -->
              <filtering>true</filtering>
              <excludes>
                <exclude>**/properties</exclude>
              </excludes>
            </resource>
          </webResources>
        </configuration>

I would recommend to make a supplemental directory like src/main/filtered-resources which you configure to do filtering and the default resources directory I wouldn't change (no filtering by default). This makes it easier to understand.

If you want to change the delimiters you can add the configuration to the maven-war-plugin like this:

<delimiters>
  <delimiter>@</delimiter>
</delimiters>

So in the end there is no need to make supplemental configuration for maven-resources-plugin etc.

khmarbaise
  • 92,914
  • 28
  • 189
  • 235
  • As the OP asked about a classpath resource, IMHO the mechanisms for filtering classpath resources should be used, which would be the `resources` plugin. In your example, the filtered files would end up in the root of the War file, while the OP wanted them in `WEB-INF` classes. – blackbuild Jan 07 '18 at 22:16