Why filter source
files?
Well there are many use cases you can think of. Any build time property that you want to have available runtime can be stored in a class member variable in your code. It may be the datetime, the svn revision or whatever. A common use case when working with GX WebManager Components is that you want to use the ${pom.groupId} and ${pom.artifactId} to construct your component identifiers. For example;
public static final String DOMAIN = "${pom.groupId}";
public static final String WCB_ID = "${pom.artifactId}";
Note: We could discuss if this is a good approach
compared to using resource files (that are filtered by default) and can be loaded
from the classpath at runtime, but that is beyond the scope of this post ;)
Filtering in Maven
Filtering is a standard feature in Maven and any typical
project uses it extensively. The resources plugin will apply filtering to
resources as configured and allows interpolation of variables in the form of
${some.property} against system properties, configured project properties and
declared additional property files. By default filtering will be applied to all
files in src/main/resources and src/test/resources because this is what the root
project object model declares, but you may configure any alternative in a
specific module.
Note: Always make sure binary resources are NOT being
filtered. Maven filtering will not distinguish between file types and as a
result may corrupt you images, executables etc.
Configuring the resources plugin
So, in order to filter the source files we need to tell the resources plugin to use them as resources. This is done by overruling the default configuration in the pom file as show below.
<project...>
...
<build>
...
<!-- Configure the source files as resources to be filtered
into a custom target directory -->
<resources>
<resource>
<directory>src/main/java</directory>
<filtering>true</filtering>
<targetPath>../filtered-sources/java</targetPath>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
...
</project>
Note: Because we are overruling the root pom default resource configuration so we need to explicitly include the src/main/resources explicitly.
Once you have added this to your project pom you can easily validate that is it is correct by executing the Maven lifecycle upto the process-resources phase and check that in fact the source files are now in the targetPath with the variables interpolated.
c:\myproject>mvn process-resources
Configuring the compiler plugin
Now that the filtered source files are in place you need to make sure the compiler plugin will use them during the compile phase and not the default which is src/main/java. As the compiler plugin will use the configured ${pom.build.sourceDirectory} you need to overrule this.
<project...>
...
<build>
...
<!-- Overrule the default pom source directory to match
our generated sources so the compiler will pick them up -->
<sourceDirectory>target/filtered-sources/java</sourceDirectory>
...
</build>
...
</project>
Once you have added this to your project pom you can easily validate that is it is correct by executing the Maven lifecycle upto the test phase and let a simple junit test validate that your class returns the interpolated result.
c:\myproject>mvn test
Conclusion
By adding a few lines of configuration to the pom declaring what the resource plugin should consider to be resources you have enabled filtering on all your source files.
Happy coding
Bram
Bram de Kruijff is Product Architect and one of the co-architects of the GX WebManager framework with a focus on OSGi and services framework. Bram is part of the NAF Web 2.0 forum group to define standards on community technologies.
Other blog entries: