Configure encoding for different filetypes in maven?

encoding, maven

Solution

The question is an invaluable answer in itself, as apparently the complicated procedure the author provides is the only way to configure different encodings for various filtered file types. The example given, however, is specific to the author's non-standard use-case, and glosses over a few important details, without which actual use of the example is fraught with gotchas:

- It isn't obvious, but in the author's example the default resource copying goal `resources` is still enabled and runs in addition to the two defined goals!

- You'll notice that the author used the lifecycle phase `generate-resources` instead of the default `process-resources`. This is a trick to get around the first point above; by making the two `copy-resources` goals occur in an earlier lifecycle phase, the resources are copied according to the given rules, and then when the `default-resources` goal comes along the original resource copying is left intact, apparently because its `overwrite` setting defaults `false`. But it would be better to disable altogether the `default-resources` execution.

- The author provides an `outputDirectory` declaration. It would be natural to think that the author only provided this because a custom output directory was desired; after all, the `resources` goal provides a default value for this setting. Strangely, though, for the `copy-resources` goal this setting is actually required! There is a standard Maven variable `${project.build.outputDirectory}` which can be used as the value, however.

Building on the author's own example in the question, here is a cut-and-paste way to filter properties files using ISO-8859-1, copy other files without filtering, and prevent the default resource copying from occurring; all using the standard source and target directories:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-resources-plugin</artifactId>
  <version>2.7</version>
  <executions>
    <execution>
      <!-- Turn off default resource copying. -->
      <id>default-resources</id>
      <phase />
    </execution>
    <execution>
      <!-- Filter resources in properties files. -->
      <id>filter-properties-files</id>
      <phase>process-resources</phase>
      <goals>
        <goal>copy-resources</goal>
      </goals>
      <configuration>
        <encoding>ISO-8859-1</encoding>
        <outputDirectory>${project.build.outputDirectory}</outputDirectory>
        <resources>
          <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
              <include>**/*.properties</include>
            </includes>
          </resource>
        </resources>
      </configuration>
    </execution>
    <execution>
      <!-- Do not do property substitution in files that are not properties files, such as binary files. -->
      <id>copy-other-resources</id>
      <phase>process-resources</phase>
      <goals>
        <goal>copy-resources</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.outputDirectory}</outputDirectory>
        <resources>
          <resource>
            <directory>src/main/resources</directory>
            <filtering>false</filtering>
            <excludes>
              <exclude>**/*.properties</exclude>
            </excludes>
          </resource>
        </resources>
      </configuration>
    </execution>
  </executions>
</plugin>

Update: After more research, I believe that instead of disabling the default execution, one could simply modify the default execution to ignore properties files, and add filtering of properties files as an additional execution. Moreover if the `resources` goal were used instead of `copy-resources`, there would be no need to indicate an output directory or a phase, as `resources:resources` automatically binds to the `process-resources` phase and outputs to `${project.build.outputDirectory}`. Note that I've updated to version 3.1.0 of the plugin, so perhaps some of these options were not available in the version I used above. I have not tested this new, shorter configuration.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-resources-plugin</artifactId>
  <version>3.1.0</version>
  <executions>
    <execution>
      <!-- Ignore properties files by default. -->
      <id>default-resources</id>
      <configuration>
        <resources>
          <resource>
            <directory>${project.basedir}/src/main/resources</directory>
            <excludes>
              <exclude>**/*.properties</exclude>
            </excludes>
          </resource>
        </resources>
      </configuration>
    </execution>
    <execution>
      <!-- Filter resources in properties files using ISO-8859-1. -->
      <id>filter-properties-files</id>
      <goals>
        <goal>resources</goal>
      </goals>
      <configuration>
        <encoding>ISO-8859-1</encoding>
        <resources>
          <resource>
            <directory>${project.basedir}/src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
              <include>**/*.properties</include>
            </includes>
          </resource>
        </resources>
      </configuration>
    </execution>
  </executions>
</plugin>

Maybe someone could test this new configuration and let me know if it works the same as the original one I gave above.

Problem

I use the maven-resource-plugin to filter some resources in my maven project. In my parent project I have: ``` <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> ``` In a sub project I have a test.properties file which is a plain java properties file with default encoding=ISO-8859-1. This file contains: ``` aboutText=Version ${project.version} © 2012 blabla ``` To make sure this file filters correctly I have split the maven-resource-plugin into separate executions each with its encoding: ``` <plugin> <artifactId>maven-resources-plugin</artifactId> <configuration> <nonFilteredFileExtensions> <nonFilteredFileExtension>ico</nonFilteredFileExtension> <nonFilteredFileExtension>jar</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> <executions> <execution> <id>filter-properties-files</id> <phase>generate-resources</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <!-- java properties files are encoded in ISO-8859-1 so when filtering those files we stick with that encoding. --> <encoding>ISO-8859-1</encoding> <outputDirectory>${basedir}/after</outputDirectory> <resources> <resource> <filtering>true</filtering> <directory>${basedir}/before</directory> <includes> <include>**/*.properties</include> </includes> </resource> </resources> </configuration> </execution> <execution> <id>filter-non-properties-files</id> <phase>generate-resources</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <encoding>${project.build.sourceEncoding}</encoding> <outputDirectory>${basedir}/after</outputDirectory> <resources> <resource> <filtering>true</filtering> <directory>${basedir}/before</directory> <includes> <include>**/*.product</include> <include>**/*.inf</include> </includes> </resource> </resources> </configuration> </execution> </executions> </plugin> ``` This seems overkill and I have a feeling that I am either not using the plugin correctly or that this problem should be handled in another way. Maybe stick to encoding special characters in properties files directly: ``` aboutText=Version ${project.version} \u00a9 2012 blabla ``` ?

Original source

Related problems