I want to rename static files when building my WAR file using maven-war-plugin, with version number. For intance, in my project I have a file:
src/main/webapp/css/my.css
I want it to appear in the WAR file as:
css/my-versionNumber.css
The same question was already asked (see Rename static files on maven war build), but the accepted answer is to rename a directory. I do not want to rename a directory, I want to rename the actual file.
Is this possible?
OK, I found a way, the principles come from: Automatic update of generated css files via m2e.
Renaming files
I chose to use Maven AntRun Plugin, because it allows to rename several files using a replacement pattern, see https://stackoverflow.com/a/16092997/1768736 for details.
Alternative solutions were to use:
maven-assembly-plugin
: but it doesn't support renaming of filesets, only renaming of individual files (see file assembly descriptor and comments of this answer: https://stackoverflow.com/a/4019057/1768736)
maven-resources-plugin
: it allows to copy resources, not to rename them (see copy resources mojo and comments of this question: Renaming resources in Maven)
Make renamed files available for maven-war-plugin
Copy files: the idea is to copy the renamed files into a temp directory, to be added by maven-war-plugin
to the WAR file as a web-resource. maven-war-plugin
builds the WAR during the packaging
phase, so we will need to copy renamed files before that.
Prevent maven-war-plugin
to manage the files to be renamed by maven-antrun-plugin
: this is done by using the parameter warSourceExcludes
.
Make it work from within Eclipse with m2e-wtp
Change lifecycle mapping: the problem is that m2e
by default doesn't execute all lifecycles defined in the POM file (to see the lifecycles executed/ignored, from Eclipse, go to your project properties, then Maven
> Lifecycle Mapping
). So you need to use the fake plugin org.eclipse.m2e.lifecycle-mapping
to add the maven-antrun-plugin
lifecycle, see life cycle mapping documentation.
Change maven-antrun-plugin
output directory: the problem is that m2e-wtp
acquires its web-resources before any lifecycle can be launched, so, before maven-antrun-plugin
can rename the files. As a workaround, we create a profile, activated only when the project is built by m2e
, to change the property used to set maven-antrun-plugin
output directory, to write directly into m2e-wtp
web-resources.
That's it! POM snippet:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<properties>
<!-- properties used to rename css files with version number. -->
<css.version>${project.version}</css.version>
<!-- Temp directory where to copy renamed files, later added by maven-war-plugin as web-resources. -->
<rename.tmp.directory>${project.build.directory}/rename_tmp</rename.tmp.directory>
</properties>
<!-- There is a problem when running the webapp from Eclipse: m2e-wtp acquires
the web-resources before any lifecycle can be launched, so, before
maven-antrun-plugin can rename the files. We define a profile so that
maven-antrun-plugin copies files directly into the m2e-wtp web-resources directory,
when running from Eclipse. -->
<profiles>
<profile>
<id>m2e</id>
<!-- This profile is only active when the property "m2e.version"
is set, which is the case when building in Eclipse with m2e,
see https://stackoverflow.com/a/21574285/1768736. -->
<activation>
<property>
<name>m2e.version</name>
</property>
</activation>
<properties>
<rename.tmp.directory>${project.build.directory}/m2e-wtp/web-resources/</rename.tmp.directory>
</properties>
</profile>
</profiles>
...
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>run</goal>
</goals>
<id>rename-resources</id>
<!-- perform copy before the package phase,
when maven-war-plugin builds the WAR file -->
<phase>process-resources</phase>
<configuration>
<target>
<!-- copy renamed files. -->
<copy todir="${rename.tmp.directory}/css/">
<fileset dir="src/main/webapp/css/">
<include name="**/*.css" />
</fileset>
<!-- See other Mappers available at http://ant.apache.org/manual/Types/mapper.html -->
<mapper type="glob" from="*.css" to="*-${css.version}.css"/>
</copy>
</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<!-- We do no let the maven-war-plugin take care of files that will be renamed.
Paths defined relative to warSourceDirectory (default is ${basedir}/src/main/webapp) -->
<warSourceExcludes>css/</warSourceExcludes>
<webResources>
<!-- include the resources renamed by maven-antrun-plugin,
at the root of the WAR file -->
<resource>
<directory>${rename.tmp.directory}</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
...
</plugins>
<!-- When running server from Eclipse, we need to tell m2e to execute
maven-antrun-plugin to rename files, by default it doesn't. We need to modify the life cycle mapping. -->
<pluginManagement>
<plugins>
<!-- This plugin is not a real one, it is only used by m2e to obtain
config information. This is why it needs to be put in the section
pluginManagement, otherwise Maven would try to download it. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<versionRange>[1.0.0,)</versionRange>
<goals>
<goal>run</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute>
<!-- set to true, otherwise changes are not seen,
e.g., to a css file, and you would need to perform
a project update each time. -->
<runOnIncremental>true</runOnIncremental>
</execute >
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
...
</build>
...
</project>
You need define
<properties>
<css.version>1.1.0</css.version>
</properties>
After that call it by EL
css/${css.version}.css