1

To invalidate client (browser) caches for new releases, I have to add a random string parameter to my asset urls.

I develop a web application with Spring MVC and use Maven to build the project.

My question is how to generate such strings with Maven? It make sense when I have the possibility to place a variable in any file, JSP, tags like this:

<link rel="stylesheet" type="text/css" href="/css/master.css?cache={random}" media="all"/>

And replace the variable with the random string while building.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Robert Moszczynski
  • 1,081
  • 2
  • 16
  • 26

3 Answers3

3

Instead of generating a random String during the Maven build, you can just use the version number. This is different for every releases and will fit your use-case.

For this to work, you can use the filtering capabilites of the maven-war-plugin. In your JSP, declare the placeholder ${project.version}:

<link rel="stylesheet" type="text/css" href="/css/master.css?cache=${project.version}" media="all"/>

Then, during the Maven build, you can filter this file and Maven will automatically replace this placeholder with the current version.

<plugin>
  <artifactId>maven-war-plugin</artifactId>
  <version>2.6</version>
  <configuration>
    <webResources>
      <resource>
        <directory>src/main/webapp</directory>
        <filtering>true</filtering>
      </resource>
    </webResources>
  </configuration>
</plugin>

If you really want to generate a random String, you can use the maven-antrun-plugin with the following task (taken from this answer):

<scriptdef name="generateguid" language="javascript">
    <attribute name="property" />
    <![CDATA[
    importClass( java.util.UUID );

    project.setProperty( attributes.get( "property" ), UUID.randomUUID() );
    ]]>
</scriptdef>

<generateguid property="guid1" />
<echo message="${guid1}" />

The property guid1 will then hold your random String, be sure to set exportAntProperties to true in the plugin configuration. You can then apply the same logic as above (resource filtering) with the ${guid1} placeholder instead of ${project.version}

Community
  • 1
  • 1
Tunaki
  • 132,869
  • 46
  • 340
  • 423
  • After declaring the plugin I got 08-Oct-2015 14:21:02.740 SEVERE [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]] . Any idea? – Robert Moszczynski Oct 08 '15 at 12:29
  • @RobertMoszczynski That seems to be an error build the server startup. Was the property correctly replaced in the WAR file? – Tunaki Oct 08 '15 at 12:39
  • Yes, it was correctly replaced. The question is solved and the solution is very cool. Thank you! But maybe you have additionally a idea how tho solve the Tomcat problem. – Robert Moszczynski Oct 08 '15 at 12:45
  • @RobertMoszczynski I suggest you create another question with your POM and complete stacktrace. – Tunaki Oct 08 '15 at 12:46
  • I see that the replaced version is always 1.0-SNAPSHOT and I can't change it with 2.8.7... – Robert Moszczynski Oct 08 '15 at 12:59
  • I tried mvn dependency:purge-local-repository but it doesn't helped. – Robert Moszczynski Oct 08 '15 at 13:00
  • @RobertMoszczynski Are you saying that with a project having a version of 2.8.7 (i.e. the element "project > version" of the war is 2.8.7), the placeholder `${project.version}` gets replaced by 1.0-SNAPSHOT? This would be really weird. – Tunaki Oct 08 '15 at 13:03
  • Yes it is. There is a Maven inconsistency. No plan how to solve that. I will make a additional question for that. – Robert Moszczynski Oct 08 '15 at 13:07
  • Sorry, my script copied the war from a old 1.0-SNAPSHOT path. Yes, the variable is correctly replaced with 2.8.7. I create an another question special for the Tomcat exception. – Robert Moszczynski Oct 08 '15 at 13:19
0

You can make use of the filtering capability of the Maven resources plugin.

Here is how you would specify the resource plugin configuration for web resources. The WAR plugin makes use of the resource plugin internally, so the configuration is identical and you can refer to the documentation for the resources plugin.

sh0rug0ru
  • 1,596
  • 9
  • 9
  • The `maven-resources-plugin` is not appropriate here since we're talking about a JSP here – Tunaki Oct 08 '15 at 11:54
  • Sure it is. How do you think files are copied from `src/main/webapp` to the `target` folder? The WAR plugin uses the resources plugin internally to copy files, so the configuration options are identical. – sh0rug0ru Oct 08 '15 at 12:03
  • Let me rephrase, a JSP is not a main resources as per Maven terms, it is a webapp file so it should not be handled by this plugin. You're going to have to specify you filter src/main/webapp, which will add these files to the jar. In your edited answer, you link to `maven-WAR-plugin` documentation, not `maven-resources-plugin`. – Tunaki Oct 08 '15 at 12:06
  • Where are JSP files located? In `src/main/webapp`. This is just a standard resource provided by the WAR plugin, with the specific terminology of `webResources`. The configuration of `webResources` is identical to standalone resources, because they are implemented from the same Maven building blocks. – sh0rug0ru Oct 08 '15 at 12:10
  • I'm removing my downvote, I initially thought you were suggesting to use `` element instead of the `webResources` element of maven-war-plugin (because that's what you link to) – Tunaki Oct 08 '15 at 12:29
  • Thanks. I really should have just included an example instead of only referring to a link. The initial link provides very good practical example of how to do filtering in Maven, but is missing essential context. – sh0rug0ru Oct 08 '15 at 12:48
-1

As proposed by Tunaki, you can use the version number rather than a random number. In both cases Maven Resources Plugin and its filter option will help you.

See: http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html

EDIT : you can get version number with ${project.version} property in Maven.

Gaël J
  • 11,274
  • 4
  • 17
  • 32