1

I'm converting a build from Maven to Gradle, and in it, we do some resource filtering. Specifically, we have a block that looks like this:

<build>
    <finalName>${project.name}-${project.version}</finalName>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>src/test/resources</directory>
        <filtering>true</filtering>
      </testResource>
    </testResources>
    <filters>
        <filter>/path/to/more/resources.properties</filter>
        <filter>/path/to/more/resources.properties</filter>
        <filter>/path/to/more/resources.properties</filter>
    </filters>
</build>

...and we want to get something similar in Gradle.

The documentation for the Copy tasks with filter in them aren't that complete and don't describe what specific problem(s) I'm attempting to solve:

  • Filtering out specific resource files
  • Keeping the POM style of variables in use (${example.property})
  • Ensuring that the artifact makes its way into my WAR

How would I go about doing this?

Makoto
  • 104,088
  • 27
  • 192
  • 230

1 Answers1

1

This is an expansion of this Gradle-oriented answer with some more concrete examples.

First, we need to read in all of the resources we care about into something that the filter method of the Copy task will recognize. Conventionally, this has been just a standard Properties object.

That can be accomplished like so:

def resources = new Properties()
file($projectDir/src/main/resources/<insert-properties-file>.properties").withInputStream {
    resources.load(it)
}

Note that there may be a more elegant way to get more than one properties file in at once; this approach simply worked for me for a single file.

Next, we then need to actually do the filtering. That can be accomplished with the from closure. We leverage the ReplaceTokens class (which we can import) to do this, and configure the begin and end tokens to match our variable use.

from("$projectDir/path/to/folder/that/has/tokens/to/replace") {
    include "**/files-to-filter-on"
    filter(ReplaceTokens, tokens: resources, beginToken: "${", endToken: "}")
}

To get that into the WAR, we need to load that into the processResources task.

All together:

processResources {
    with copySpec {
        def resources = new Properties()
        file($projectDir/src/main/resources/<insert-properties-file>.properties").withInputStream {
        resources.load(it)
    }

    from("$projectDir/path/to/folder/that/has/tokens/to/replace") {
        include "**/files-to-filter-on"
        filter(ReplaceTokens, tokens: resources, beginToken: "${", endToken: "}")
    }
}

When you execute ./gradlew clean war, the resources you want to have filtered will be correctly filtered in the archive.

Makoto
  • 104,088
  • 27
  • 192
  • 230