8/26/2013

Caution: Maven binary file as resource should disable filter function.

In maven, sometimes when we use binary files as resources or assemble package from files that include binary files, like certificates, if we treat the binary file same as other resources, it may destroy the binary file.

First, the filter function of maven may destroy the binary file.

The description of filter function is in Maven Resource Document.
Basically,

Variables can be included in your resources. These variables, denoted by the ${...} delimiters, can come from the system properties, your project properties, from your filter resources and from the command line.
For example, if we have a resource src/main/resources/hello.txt containing
Hello ${name}
And a POM like this
<project>
  ...
  <name>My Resources Plugin Practice Project</name>
  ...
  <build>
    ...
    <resources>
      <resource>
        <directory>src/main/resources</directory>
      </resource>
      ...
    </resources>
    ...
  </build>
  ...
</project>
Upon calling
mvn resources:resources
This will create a resource output in target/classes/hello.txt which contains exactly the same text.
Hello ${name}
However, if we add a <filtering> tag to our POM and set it to true like this:
      ...
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
      ...
Our target/classes/hello.txt after calling
mvn resources:resources
would be
Hello My Resources Plugin Practice Project
That's because the name variable was replaced by the value of the project's name (which was specified in the POM).
Moreover, we can also assign values through the command line using the "-D" option. For example, to change the value for the variable name to "world", we can simply invoke this command:
mvn resources:resources -Dname="world"
And the output in target/classes/hello.txt would be
Hello world

So we should understand that if we treat the binary file same as other resources, like configuration as below:
      ...
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
      ...

Then when we run the program from the build, it'll throw exceptions when parse the binary file.

Instead, we should configure like this:
<resource>
    <directory>src/main/resources</directory>
    <excludes>
        <exclude>keystore/*</exclude>
    </excludes>
    <filtering>true</filtering>
 </resource>
 <resource>
    <directory>src/main/resources/keystore</directory>
    <filtering>false</filtering>
 </resource>


I see some questions are like "Generated Certificate Stops Working When Moved To Resources Folder"

Basically this is the reason.

Have fun.

Another place that we may face this issue is when we assemble the package.
In the assemble xml file, we need to include the binary file along with other resources into package.

For example:
<fileSets>
 <fileSet>
  <directory>${basedir}/../bin</directory>
  <outputDirectory>bin</outputDirectory>
  <filtered>true</filtered>
 </fileSet>
 <fileSet>
  <directory>${project.build.directory}/${project.artifactId}-${project.version}-bin/lib</directory>
  <outputDirectory>lib</outputDirectory>
 </fileSet>
 <fileSet>
  <directory>${basedir}/../resources</directory>
  <excludes>
   <exclude>keystore/*</exclude>
  </excludes>
  <outputDirectory>resources</outputDirectory>
  <filtered>true</filtered>
 </fileSet>
 <fileSet>
  <directory>${basedir}/../resources/keystore</directory>
  <outputDirectory>resources/keystore</outputDirectory>
  <filtered>false</filtered>
  <lineEnding>keep</lineEnding>
 </fileSet>
</fileSets>

In additional to the filter function, we can also set the lineEnding, directoryMode and fileMode to make sure the file will not be damaged when we make the assembling.








No comments:

Post a Comment